@oxy.so/bloom 7.1.4 → 7.2.0

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 (442) hide show
  1. package/assets/character-runtime/README.md +19 -114
  2. package/assets/character-runtime/legacy-engine.mjs +54 -406
  3. package/assets/character-runtime/legacy-geometry.mjs +85 -242
  4. package/assets/character-runtime/legacy-worker.mjs +23 -82
  5. package/assets/character-runtime/managed-avatar.mjs +18 -12
  6. package/assets/character-runtime/render-budget.mjs +11 -6
  7. package/assets/character-runtime/runtime.mjs +295 -744
  8. package/docs/adoption-matrix.mdx +12 -11
  9. package/docs/agent-avatar.mdx +8 -45
  10. package/docs/agent-creator.mdx +3 -13
  11. package/docs/app-shell.mdx +26 -2
  12. package/docs/appearance.mdx +16 -1
  13. package/docs/content-panel.mdx +4 -0
  14. package/docs/mail-thread.mdx +8 -0
  15. package/docs/page-footer.mdx +60 -0
  16. package/docs/sidebar.mdx +1 -1
  17. package/lib/commonjs/agent-avatar/AgentAvatar.js +1 -1
  18. package/lib/commonjs/agent-avatar/AgentAvatar.js.map +1 -1
  19. package/lib/commonjs/agent-avatar/CharacterAvatar.js +1 -2
  20. package/lib/commonjs/agent-avatar/CharacterAvatar.js.map +1 -1
  21. package/lib/commonjs/agent-avatar/config-character.js +0 -4
  22. package/lib/commonjs/agent-avatar/config-character.js.map +1 -1
  23. package/lib/commonjs/agent-avatar/legacy-recipe.js +6 -19
  24. package/lib/commonjs/agent-avatar/legacy-recipe.js.map +1 -1
  25. package/lib/commonjs/agent-creator/AgentCreatorBase.js +107 -67
  26. package/lib/commonjs/agent-creator/AgentCreatorBase.js.map +1 -1
  27. package/lib/commonjs/agent-creator/CharacterControls.js +5 -23
  28. package/lib/commonjs/agent-creator/CharacterControls.js.map +1 -1
  29. package/lib/commonjs/agent-creator/EmotionPicker.js +1 -8
  30. package/lib/commonjs/agent-creator/EmotionPicker.js.map +1 -1
  31. package/lib/commonjs/agent-creator/ShapeSilhouette.js +1 -8
  32. package/lib/commonjs/agent-creator/ShapeSilhouette.js.map +1 -1
  33. package/lib/commonjs/agent-creator/constants.js +17 -16
  34. package/lib/commonjs/agent-creator/constants.js.map +1 -1
  35. package/lib/commonjs/agent-creator/messages.js +1 -1
  36. package/lib/commonjs/agent-creator/messages.js.map +1 -1
  37. package/lib/commonjs/app-shell/AppShell.js +3 -2
  38. package/lib/commonjs/app-shell/AppShell.js.map +1 -1
  39. package/lib/commonjs/app-shell/AppShellBars.js +8 -5
  40. package/lib/commonjs/app-shell/AppShellBars.js.map +1 -1
  41. package/lib/commonjs/app-shell/AppShellEngine.js +81 -36
  42. package/lib/commonjs/app-shell/AppShellEngine.js.map +1 -1
  43. package/lib/commonjs/appearance/BloomScope.js +8 -3
  44. package/lib/commonjs/appearance/BloomScope.js.map +1 -1
  45. package/lib/commonjs/appearance/context.js.map +1 -1
  46. package/lib/commonjs/content-panel/ContentPanel.js +34 -23
  47. package/lib/commonjs/content-panel/ContentPanel.js.map +1 -1
  48. package/lib/commonjs/content-panel/ContentPanel.web.js +39 -17
  49. package/lib/commonjs/content-panel/ContentPanel.web.js.map +1 -1
  50. package/lib/commonjs/design-tokens/shapes.js +2 -2
  51. package/lib/commonjs/design-tokens/shapes.js.map +1 -1
  52. package/lib/commonjs/design-tokens/tokens.json +2 -2
  53. package/lib/commonjs/index.js +939 -927
  54. package/lib/commonjs/index.js.map +1 -1
  55. package/lib/commonjs/index.web.js +939 -927
  56. package/lib/commonjs/index.web.js.map +1 -1
  57. package/lib/commonjs/locale/translations/ar.js +1 -1
  58. package/lib/commonjs/locale/translations/ar.js.map +1 -1
  59. package/lib/commonjs/locale/translations/bn.js +1 -1
  60. package/lib/commonjs/locale/translations/bn.js.map +1 -1
  61. package/lib/commonjs/locale/translations/ca.js +1 -1
  62. package/lib/commonjs/locale/translations/ca.js.map +1 -1
  63. package/lib/commonjs/locale/translations/de.js +1 -1
  64. package/lib/commonjs/locale/translations/de.js.map +1 -1
  65. package/lib/commonjs/locale/translations/es.js +1 -1
  66. package/lib/commonjs/locale/translations/es.js.map +1 -1
  67. package/lib/commonjs/locale/translations/fr.js +1 -1
  68. package/lib/commonjs/locale/translations/fr.js.map +1 -1
  69. package/lib/commonjs/locale/translations/hi.js +1 -1
  70. package/lib/commonjs/locale/translations/hi.js.map +1 -1
  71. package/lib/commonjs/locale/translations/id.js +1 -1
  72. package/lib/commonjs/locale/translations/id.js.map +1 -1
  73. package/lib/commonjs/locale/translations/it.js +1 -1
  74. package/lib/commonjs/locale/translations/it.js.map +1 -1
  75. package/lib/commonjs/locale/translations/ja.js +1 -1
  76. package/lib/commonjs/locale/translations/ja.js.map +1 -1
  77. package/lib/commonjs/locale/translations/pt.js +1 -1
  78. package/lib/commonjs/locale/translations/pt.js.map +1 -1
  79. package/lib/commonjs/locale/translations/ru.js +1 -1
  80. package/lib/commonjs/locale/translations/ru.js.map +1 -1
  81. package/lib/commonjs/locale/translations/tr.js +1 -1
  82. package/lib/commonjs/locale/translations/tr.js.map +1 -1
  83. package/lib/commonjs/locale/translations/zh.js +1 -1
  84. package/lib/commonjs/locale/translations/zh.js.map +1 -1
  85. package/lib/commonjs/mail-thread/MailMessage.js +8 -14
  86. package/lib/commonjs/mail-thread/MailMessage.js.map +1 -1
  87. package/lib/commonjs/mail-thread/MailThread.js +6 -2
  88. package/lib/commonjs/mail-thread/MailThread.js.map +1 -1
  89. package/lib/commonjs/mail-thread/shared.js +2 -1
  90. package/lib/commonjs/mail-thread/shared.js.map +1 -1
  91. package/lib/commonjs/page-footer/PageFooter.js +137 -0
  92. package/lib/commonjs/page-footer/PageFooter.js.map +1 -0
  93. package/lib/commonjs/page-footer/PageFooterProvider.js +22 -0
  94. package/lib/commonjs/page-footer/PageFooterProvider.js.map +1 -0
  95. package/lib/commonjs/page-footer/context.js +11 -0
  96. package/lib/commonjs/page-footer/context.js.map +1 -0
  97. package/lib/commonjs/page-footer/index.js +27 -0
  98. package/lib/commonjs/page-footer/index.js.map +1 -0
  99. package/lib/commonjs/page-footer/types.js +6 -0
  100. package/lib/commonjs/page-footer/types.js.map +1 -0
  101. package/lib/commonjs/page-footer/use-page-footer-inset.js +19 -0
  102. package/lib/commonjs/page-footer/use-page-footer-inset.js.map +1 -0
  103. package/lib/commonjs/sidebar/Sidebar.js +6 -5
  104. package/lib/commonjs/sidebar/Sidebar.js.map +1 -1
  105. package/lib/commonjs/styles/panel-chrome.js +15 -1
  106. package/lib/commonjs/styles/panel-chrome.js.map +1 -1
  107. package/lib/module/agent-avatar/AgentAvatar.js +1 -1
  108. package/lib/module/agent-avatar/AgentAvatar.js.map +1 -1
  109. package/lib/module/agent-avatar/CharacterAvatar.js +1 -2
  110. package/lib/module/agent-avatar/CharacterAvatar.js.map +1 -1
  111. package/lib/module/agent-avatar/config-character.js +0 -4
  112. package/lib/module/agent-avatar/config-character.js.map +1 -1
  113. package/lib/module/agent-avatar/legacy-recipe.js +6 -19
  114. package/lib/module/agent-avatar/legacy-recipe.js.map +1 -1
  115. package/lib/module/agent-creator/AgentCreatorBase.js +109 -69
  116. package/lib/module/agent-creator/AgentCreatorBase.js.map +1 -1
  117. package/lib/module/agent-creator/CharacterControls.js +6 -24
  118. package/lib/module/agent-creator/CharacterControls.js.map +1 -1
  119. package/lib/module/agent-creator/EmotionPicker.js +1 -8
  120. package/lib/module/agent-creator/EmotionPicker.js.map +1 -1
  121. package/lib/module/agent-creator/ShapeSilhouette.js +1 -8
  122. package/lib/module/agent-creator/ShapeSilhouette.js.map +1 -1
  123. package/lib/module/agent-creator/constants.js +16 -8
  124. package/lib/module/agent-creator/constants.js.map +1 -1
  125. package/lib/module/agent-creator/messages.js +1 -1
  126. package/lib/module/agent-creator/messages.js.map +1 -1
  127. package/lib/module/app-shell/AppShell.js +3 -2
  128. package/lib/module/app-shell/AppShell.js.map +1 -1
  129. package/lib/module/app-shell/AppShellBars.js +8 -5
  130. package/lib/module/app-shell/AppShellBars.js.map +1 -1
  131. package/lib/module/app-shell/AppShellEngine.js +81 -36
  132. package/lib/module/app-shell/AppShellEngine.js.map +1 -1
  133. package/lib/module/appearance/BloomScope.js +8 -3
  134. package/lib/module/appearance/BloomScope.js.map +1 -1
  135. package/lib/module/appearance/context.js.map +1 -1
  136. package/lib/module/content-panel/ContentPanel.js +35 -24
  137. package/lib/module/content-panel/ContentPanel.js.map +1 -1
  138. package/lib/module/content-panel/ContentPanel.web.js +41 -19
  139. package/lib/module/content-panel/ContentPanel.web.js.map +1 -1
  140. package/lib/module/design-tokens/shapes.js +2 -2
  141. package/lib/module/design-tokens/shapes.js.map +1 -1
  142. package/lib/module/design-tokens/tokens.json +2 -2
  143. package/lib/module/index.js +1 -0
  144. package/lib/module/index.js.map +1 -1
  145. package/lib/module/index.web.js +1 -0
  146. package/lib/module/index.web.js.map +1 -1
  147. package/lib/module/locale/translations/ar.js +1 -1
  148. package/lib/module/locale/translations/ar.js.map +1 -1
  149. package/lib/module/locale/translations/bn.js +1 -1
  150. package/lib/module/locale/translations/bn.js.map +1 -1
  151. package/lib/module/locale/translations/ca.js +1 -1
  152. package/lib/module/locale/translations/ca.js.map +1 -1
  153. package/lib/module/locale/translations/de.js +1 -1
  154. package/lib/module/locale/translations/de.js.map +1 -1
  155. package/lib/module/locale/translations/es.js +1 -1
  156. package/lib/module/locale/translations/es.js.map +1 -1
  157. package/lib/module/locale/translations/fr.js +1 -1
  158. package/lib/module/locale/translations/fr.js.map +1 -1
  159. package/lib/module/locale/translations/hi.js +1 -1
  160. package/lib/module/locale/translations/hi.js.map +1 -1
  161. package/lib/module/locale/translations/id.js +1 -1
  162. package/lib/module/locale/translations/id.js.map +1 -1
  163. package/lib/module/locale/translations/it.js +1 -1
  164. package/lib/module/locale/translations/it.js.map +1 -1
  165. package/lib/module/locale/translations/ja.js +1 -1
  166. package/lib/module/locale/translations/ja.js.map +1 -1
  167. package/lib/module/locale/translations/pt.js +1 -1
  168. package/lib/module/locale/translations/pt.js.map +1 -1
  169. package/lib/module/locale/translations/ru.js +1 -1
  170. package/lib/module/locale/translations/ru.js.map +1 -1
  171. package/lib/module/locale/translations/tr.js +1 -1
  172. package/lib/module/locale/translations/tr.js.map +1 -1
  173. package/lib/module/locale/translations/zh.js +1 -1
  174. package/lib/module/locale/translations/zh.js.map +1 -1
  175. package/lib/module/mail-thread/MailMessage.js +8 -14
  176. package/lib/module/mail-thread/MailMessage.js.map +1 -1
  177. package/lib/module/mail-thread/MailThread.js +6 -2
  178. package/lib/module/mail-thread/MailThread.js.map +1 -1
  179. package/lib/module/mail-thread/shared.js +2 -1
  180. package/lib/module/mail-thread/shared.js.map +1 -1
  181. package/lib/module/page-footer/PageFooter.js +132 -0
  182. package/lib/module/page-footer/PageFooter.js.map +1 -0
  183. package/lib/module/page-footer/PageFooterProvider.js +18 -0
  184. package/lib/module/page-footer/PageFooterProvider.js.map +1 -0
  185. package/lib/module/page-footer/context.js +7 -0
  186. package/lib/module/page-footer/context.js.map +1 -0
  187. package/lib/module/page-footer/index.js +6 -0
  188. package/lib/module/page-footer/index.js.map +1 -0
  189. package/lib/module/page-footer/types.js +4 -0
  190. package/lib/module/page-footer/types.js.map +1 -0
  191. package/lib/module/page-footer/use-page-footer-inset.js +16 -0
  192. package/lib/module/page-footer/use-page-footer-inset.js.map +1 -0
  193. package/lib/module/sidebar/Sidebar.js +6 -5
  194. package/lib/module/sidebar/Sidebar.js.map +1 -1
  195. package/lib/module/styles/panel-chrome.js +14 -1
  196. package/lib/module/styles/panel-chrome.js.map +1 -1
  197. package/lib/typescript/commonjs/agent-avatar/CharacterAvatar.d.ts.map +1 -1
  198. package/lib/typescript/commonjs/agent-avatar/config-character.d.ts +0 -4
  199. package/lib/typescript/commonjs/agent-avatar/config-character.d.ts.map +1 -1
  200. package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts +10 -2
  201. package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts.map +1 -1
  202. package/lib/typescript/commonjs/agent-creator/AgentCreatorBase.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts +1 -2
  204. package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts.map +1 -1
  205. package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts +0 -1
  206. package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/agent-creator/ShapeSilhouette.d.ts.map +1 -1
  208. package/lib/typescript/commonjs/agent-creator/constants.d.ts +15 -7
  209. package/lib/typescript/commonjs/agent-creator/constants.d.ts.map +1 -1
  210. package/lib/typescript/commonjs/agent-creator/messages.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/app-shell/AppShellBars.d.ts +4 -0
  212. package/lib/typescript/commonjs/app-shell/AppShellBars.d.ts.map +1 -1
  213. package/lib/typescript/commonjs/app-shell/AppShellEngine.d.ts.map +1 -1
  214. package/lib/typescript/commonjs/app-shell/types.d.ts +11 -3
  215. package/lib/typescript/commonjs/app-shell/types.d.ts.map +1 -1
  216. package/lib/typescript/commonjs/appearance/BloomScope.d.ts +1 -1
  217. package/lib/typescript/commonjs/appearance/BloomScope.d.ts.map +1 -1
  218. package/lib/typescript/commonjs/appearance/context.d.ts +2 -2
  219. package/lib/typescript/commonjs/appearance/context.d.ts.map +1 -1
  220. package/lib/typescript/commonjs/appearance/types.d.ts +4 -1
  221. package/lib/typescript/commonjs/appearance/types.d.ts.map +1 -1
  222. package/lib/typescript/commonjs/content-panel/ContentPanel.d.ts +3 -4
  223. package/lib/typescript/commonjs/content-panel/ContentPanel.d.ts.map +1 -1
  224. package/lib/typescript/commonjs/content-panel/ContentPanel.web.d.ts +1 -1
  225. package/lib/typescript/commonjs/content-panel/ContentPanel.web.d.ts.map +1 -1
  226. package/lib/typescript/commonjs/content-panel/types.d.ts +2 -2
  227. package/lib/typescript/commonjs/design-tokens/shapes.d.ts +2 -2
  228. package/lib/typescript/commonjs/index.d.ts +1 -0
  229. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  230. package/lib/typescript/commonjs/index.web.d.ts +1 -0
  231. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  232. package/lib/typescript/commonjs/mail-thread/MailMessage.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/mail-thread/MailThread.d.ts +1 -1
  234. package/lib/typescript/commonjs/mail-thread/MailThread.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/mail-thread/shared.d.ts +1 -1
  236. package/lib/typescript/commonjs/mail-thread/shared.d.ts.map +1 -1
  237. package/lib/typescript/commonjs/mail-thread/types.d.ts +2 -0
  238. package/lib/typescript/commonjs/mail-thread/types.d.ts.map +1 -1
  239. package/lib/typescript/commonjs/page-footer/PageFooter.d.ts +7 -0
  240. package/lib/typescript/commonjs/page-footer/PageFooter.d.ts.map +1 -0
  241. package/lib/typescript/commonjs/page-footer/PageFooterProvider.d.ts +4 -0
  242. package/lib/typescript/commonjs/page-footer/PageFooterProvider.d.ts.map +1 -0
  243. package/lib/typescript/commonjs/page-footer/context.d.ts +3 -0
  244. package/lib/typescript/commonjs/page-footer/context.d.ts.map +1 -0
  245. package/lib/typescript/commonjs/page-footer/index.d.ts +5 -0
  246. package/lib/typescript/commonjs/page-footer/index.d.ts.map +1 -0
  247. package/lib/typescript/commonjs/page-footer/types.d.ts +26 -0
  248. package/lib/typescript/commonjs/page-footer/types.d.ts.map +1 -0
  249. package/lib/typescript/commonjs/page-footer/use-page-footer-inset.d.ts +7 -0
  250. package/lib/typescript/commonjs/page-footer/use-page-footer-inset.d.ts.map +1 -0
  251. package/lib/typescript/commonjs/sidebar/Sidebar.d.ts.map +1 -1
  252. package/lib/typescript/commonjs/sidebar/types.d.ts +1 -1
  253. package/lib/typescript/commonjs/styles/panel-chrome.d.ts +5 -0
  254. package/lib/typescript/commonjs/styles/panel-chrome.d.ts.map +1 -1
  255. package/lib/typescript/module/agent-avatar/CharacterAvatar.d.ts.map +1 -1
  256. package/lib/typescript/module/agent-avatar/config-character.d.ts +0 -4
  257. package/lib/typescript/module/agent-avatar/config-character.d.ts.map +1 -1
  258. package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts +10 -2
  259. package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts.map +1 -1
  260. package/lib/typescript/module/agent-creator/AgentCreatorBase.d.ts.map +1 -1
  261. package/lib/typescript/module/agent-creator/CharacterControls.d.ts +1 -2
  262. package/lib/typescript/module/agent-creator/CharacterControls.d.ts.map +1 -1
  263. package/lib/typescript/module/agent-creator/EmotionPicker.d.ts +0 -1
  264. package/lib/typescript/module/agent-creator/EmotionPicker.d.ts.map +1 -1
  265. package/lib/typescript/module/agent-creator/ShapeSilhouette.d.ts.map +1 -1
  266. package/lib/typescript/module/agent-creator/constants.d.ts +15 -7
  267. package/lib/typescript/module/agent-creator/constants.d.ts.map +1 -1
  268. package/lib/typescript/module/agent-creator/messages.d.ts.map +1 -1
  269. package/lib/typescript/module/app-shell/AppShellBars.d.ts +4 -0
  270. package/lib/typescript/module/app-shell/AppShellBars.d.ts.map +1 -1
  271. package/lib/typescript/module/app-shell/AppShellEngine.d.ts.map +1 -1
  272. package/lib/typescript/module/app-shell/types.d.ts +11 -3
  273. package/lib/typescript/module/app-shell/types.d.ts.map +1 -1
  274. package/lib/typescript/module/appearance/BloomScope.d.ts +1 -1
  275. package/lib/typescript/module/appearance/BloomScope.d.ts.map +1 -1
  276. package/lib/typescript/module/appearance/context.d.ts +2 -2
  277. package/lib/typescript/module/appearance/context.d.ts.map +1 -1
  278. package/lib/typescript/module/appearance/types.d.ts +4 -1
  279. package/lib/typescript/module/appearance/types.d.ts.map +1 -1
  280. package/lib/typescript/module/content-panel/ContentPanel.d.ts +3 -4
  281. package/lib/typescript/module/content-panel/ContentPanel.d.ts.map +1 -1
  282. package/lib/typescript/module/content-panel/ContentPanel.web.d.ts +1 -1
  283. package/lib/typescript/module/content-panel/ContentPanel.web.d.ts.map +1 -1
  284. package/lib/typescript/module/content-panel/types.d.ts +2 -2
  285. package/lib/typescript/module/design-tokens/shapes.d.ts +2 -2
  286. package/lib/typescript/module/index.d.ts +1 -0
  287. package/lib/typescript/module/index.d.ts.map +1 -1
  288. package/lib/typescript/module/index.web.d.ts +1 -0
  289. package/lib/typescript/module/index.web.d.ts.map +1 -1
  290. package/lib/typescript/module/mail-thread/MailMessage.d.ts.map +1 -1
  291. package/lib/typescript/module/mail-thread/MailThread.d.ts +1 -1
  292. package/lib/typescript/module/mail-thread/MailThread.d.ts.map +1 -1
  293. package/lib/typescript/module/mail-thread/shared.d.ts +1 -1
  294. package/lib/typescript/module/mail-thread/shared.d.ts.map +1 -1
  295. package/lib/typescript/module/mail-thread/types.d.ts +2 -0
  296. package/lib/typescript/module/mail-thread/types.d.ts.map +1 -1
  297. package/lib/typescript/module/page-footer/PageFooter.d.ts +7 -0
  298. package/lib/typescript/module/page-footer/PageFooter.d.ts.map +1 -0
  299. package/lib/typescript/module/page-footer/PageFooterProvider.d.ts +4 -0
  300. package/lib/typescript/module/page-footer/PageFooterProvider.d.ts.map +1 -0
  301. package/lib/typescript/module/page-footer/context.d.ts +3 -0
  302. package/lib/typescript/module/page-footer/context.d.ts.map +1 -0
  303. package/lib/typescript/module/page-footer/index.d.ts +5 -0
  304. package/lib/typescript/module/page-footer/index.d.ts.map +1 -0
  305. package/lib/typescript/module/page-footer/types.d.ts +26 -0
  306. package/lib/typescript/module/page-footer/types.d.ts.map +1 -0
  307. package/lib/typescript/module/page-footer/use-page-footer-inset.d.ts +7 -0
  308. package/lib/typescript/module/page-footer/use-page-footer-inset.d.ts.map +1 -0
  309. package/lib/typescript/module/sidebar/Sidebar.d.ts.map +1 -1
  310. package/lib/typescript/module/sidebar/types.d.ts +1 -1
  311. package/lib/typescript/module/styles/panel-chrome.d.ts +5 -0
  312. package/lib/typescript/module/styles/panel-chrome.d.ts.map +1 -1
  313. package/package.json +18 -1
  314. package/src/__tests__/support/adoption-matrix.ts +683 -0
  315. package/src/__tests__/support/card-surface.ts +25 -0
  316. package/src/__tests__/support/collision-fixture-barrel.ts +20 -0
  317. package/src/__tests__/support/commerce-harness.tsx +97 -0
  318. package/src/__tests__/support/composite.ts +68 -0
  319. package/src/__tests__/support/constructed-style-sheets.ts +68 -0
  320. package/src/__tests__/support/messages-in.ts +10 -0
  321. package/src/__tests__/support/press-host.ts +30 -0
  322. package/src/__tests__/support/rendered-style.ts +99 -0
  323. package/src/__tests__/support/unread-hook-fixture.ts +33 -0
  324. package/src/__tests__/support/worklet-capture-fixture.tsx +28 -0
  325. package/src/agent-avatar/AgentAvatar.tsx +1 -1
  326. package/src/agent-avatar/CharacterAvatar.tsx +1 -4
  327. package/src/agent-avatar/__tests__/artwork-golden.json +774 -0
  328. package/src/agent-avatar/config-character.ts +6 -39
  329. package/src/agent-avatar/legacy-recipe.ts +6 -34
  330. package/src/agent-creator/AgentCreatorBase.tsx +152 -121
  331. package/src/agent-creator/CharacterControls.tsx +14 -39
  332. package/src/agent-creator/EmotionPicker.tsx +16 -55
  333. package/src/agent-creator/ShapeSilhouette.tsx +1 -16
  334. package/src/agent-creator/__tests__/support/character-runtime-fixture.tsx +26 -0
  335. package/src/agent-creator/constants.ts +14 -47
  336. package/src/agent-creator/messages.ts +1 -2
  337. package/src/app-shell/AppShell.tsx +2 -2
  338. package/src/app-shell/AppShellBars.tsx +6 -4
  339. package/src/app-shell/AppShellEngine.tsx +51 -18
  340. package/src/app-shell/types.ts +11 -3
  341. package/src/appearance/BloomScope.tsx +5 -2
  342. package/src/appearance/context.ts +2 -2
  343. package/src/appearance/types.ts +4 -1
  344. package/src/content-panel/ContentPanel.tsx +32 -25
  345. package/src/content-panel/ContentPanel.web.tsx +32 -23
  346. package/src/content-panel/types.ts +2 -2
  347. package/src/design-tokens/shapes.ts +1 -1
  348. package/src/design-tokens/tokens.json +2 -2
  349. package/src/index.ts +1 -0
  350. package/src/index.web.ts +1 -0
  351. package/src/locale/translations/ar.ts +1 -1
  352. package/src/locale/translations/bn.ts +1 -1
  353. package/src/locale/translations/ca.ts +1 -1
  354. package/src/locale/translations/de.ts +1 -1
  355. package/src/locale/translations/es.ts +1 -1
  356. package/src/locale/translations/fr.ts +1 -1
  357. package/src/locale/translations/hi.ts +1 -1
  358. package/src/locale/translations/id.ts +1 -1
  359. package/src/locale/translations/it.ts +1 -1
  360. package/src/locale/translations/ja.ts +1 -1
  361. package/src/locale/translations/pt.ts +1 -1
  362. package/src/locale/translations/ru.ts +1 -1
  363. package/src/locale/translations/tr.ts +1 -1
  364. package/src/locale/translations/zh.ts +1 -1
  365. package/src/mail-thread/MailMessage.tsx +9 -11
  366. package/src/mail-thread/MailThread.tsx +3 -1
  367. package/src/mail-thread/shared.ts +2 -1
  368. package/src/mail-thread/types.ts +2 -0
  369. package/src/page-footer/PageFooter.tsx +96 -0
  370. package/src/page-footer/PageFooterProvider.tsx +9 -0
  371. package/src/page-footer/context.ts +6 -0
  372. package/src/page-footer/index.ts +4 -0
  373. package/src/page-footer/types.ts +26 -0
  374. package/src/page-footer/use-page-footer-inset.ts +17 -0
  375. package/src/sidebar/Sidebar.tsx +5 -4
  376. package/src/sidebar/types.ts +1 -1
  377. package/src/styles/panel-chrome.ts +9 -1
  378. package/src/theme/__tests__/__fixtures__/golden-resolved-tokens.json +9346 -0
  379. package/src/theme/__tests__/__fixtures__/tonal-glass-primary-failures.json +69 -0
  380. package/src/theme/__tests__/fixtures/color-engine-golden.json +1 -0
  381. package/assets/character-runtime/authored-parts.mjs +0 -754
  382. package/assets/character-runtime/catalog-parts.mjs +0 -362
  383. package/assets/character-runtime/character-recipe.mjs +0 -247
  384. package/assets/character-runtime/clippo-geometry.mjs +0 -679
  385. package/assets/character-runtime/controller-mode.mjs +0 -208
  386. package/assets/character-runtime/cyclops-geometry.mjs +0 -180
  387. package/assets/character-runtime/migrated-contours.mjs +0 -2067
  388. package/assets/character-runtime/migrated-faces.mjs +0 -59
  389. package/assets/character-runtime/pose-transition.mjs +0 -523
  390. package/assets/character-runtime/preparation-cache.mjs +0 -60
  391. package/assets/character-runtime/render-errors.mjs +0 -180
  392. package/assets/character-runtime/resolution.mjs +0 -10
  393. package/assets/character-runtime/sha256.mjs +0 -44
  394. package/assets/character-runtime/shared-programs.mjs +0 -534
  395. package/assets/character-runtime/shared-surface.mjs +0 -490
  396. package/assets/character-runtime/shared-textures.mjs +0 -420
  397. package/assets/character-runtime/thumbnails/eyes/todd.png +0 -0
  398. package/lib/commonjs/agent-avatar/character-colors.js +0 -19
  399. package/lib/commonjs/agent-avatar/character-colors.js.map +0 -1
  400. package/lib/commonjs/agent-avatar/character-shapes.js +0 -106
  401. package/lib/commonjs/agent-avatar/character-shapes.js.map +0 -1
  402. package/lib/commonjs/agent-creator/ClippoArtwork.js +0 -63
  403. package/lib/commonjs/agent-creator/ClippoArtwork.js.map +0 -1
  404. package/lib/commonjs/agent-creator/CyclopsArtwork.js +0 -45
  405. package/lib/commonjs/agent-creator/CyclopsArtwork.js.map +0 -1
  406. package/lib/commonjs/agent-creator/ToddArtwork.js +0 -29
  407. package/lib/commonjs/agent-creator/ToddArtwork.js.map +0 -1
  408. package/lib/module/agent-avatar/character-colors.js +0 -15
  409. package/lib/module/agent-avatar/character-colors.js.map +0 -1
  410. package/lib/module/agent-avatar/character-shapes.js +0 -97
  411. package/lib/module/agent-avatar/character-shapes.js.map +0 -1
  412. package/lib/module/agent-creator/ClippoArtwork.js +0 -59
  413. package/lib/module/agent-creator/ClippoArtwork.js.map +0 -1
  414. package/lib/module/agent-creator/CyclopsArtwork.js +0 -41
  415. package/lib/module/agent-creator/CyclopsArtwork.js.map +0 -1
  416. package/lib/module/agent-creator/ToddArtwork.js +0 -25
  417. package/lib/module/agent-creator/ToddArtwork.js.map +0 -1
  418. package/lib/typescript/commonjs/agent-avatar/character-colors.d.ts +0 -13
  419. package/lib/typescript/commonjs/agent-avatar/character-colors.d.ts.map +0 -1
  420. package/lib/typescript/commonjs/agent-avatar/character-shapes.d.ts +0 -19
  421. package/lib/typescript/commonjs/agent-avatar/character-shapes.d.ts.map +0 -1
  422. package/lib/typescript/commonjs/agent-creator/ClippoArtwork.d.ts +0 -6
  423. package/lib/typescript/commonjs/agent-creator/ClippoArtwork.d.ts.map +0 -1
  424. package/lib/typescript/commonjs/agent-creator/CyclopsArtwork.d.ts +0 -5
  425. package/lib/typescript/commonjs/agent-creator/CyclopsArtwork.d.ts.map +0 -1
  426. package/lib/typescript/commonjs/agent-creator/ToddArtwork.d.ts +0 -6
  427. package/lib/typescript/commonjs/agent-creator/ToddArtwork.d.ts.map +0 -1
  428. package/lib/typescript/module/agent-avatar/character-colors.d.ts +0 -13
  429. package/lib/typescript/module/agent-avatar/character-colors.d.ts.map +0 -1
  430. package/lib/typescript/module/agent-avatar/character-shapes.d.ts +0 -19
  431. package/lib/typescript/module/agent-avatar/character-shapes.d.ts.map +0 -1
  432. package/lib/typescript/module/agent-creator/ClippoArtwork.d.ts +0 -6
  433. package/lib/typescript/module/agent-creator/ClippoArtwork.d.ts.map +0 -1
  434. package/lib/typescript/module/agent-creator/CyclopsArtwork.d.ts +0 -5
  435. package/lib/typescript/module/agent-creator/CyclopsArtwork.d.ts.map +0 -1
  436. package/lib/typescript/module/agent-creator/ToddArtwork.d.ts +0 -6
  437. package/lib/typescript/module/agent-creator/ToddArtwork.d.ts.map +0 -1
  438. package/src/agent-avatar/character-colors.ts +0 -12
  439. package/src/agent-avatar/character-shapes.ts +0 -122
  440. package/src/agent-creator/ClippoArtwork.tsx +0 -49
  441. package/src/agent-creator/CyclopsArtwork.tsx +0 -27
  442. package/src/agent-creator/ToddArtwork.tsx +0 -24
@@ -1,679 +0,0 @@
1
- // Clippo is a native prepared-scene mesh, not a second renderer. The original
2
- // character controllers, lighting, gaze, blink and activity payload stay in use.
3
- import {
4
- authoredAssemblyRecords,
5
- translateAuthoredRecord,
6
- transformAuthoredRecord,
7
- } from './authored-parts.mjs';
8
- import { decodeAppearance } from './appearance-codec.mjs';
9
- import { sha256 } from './sha256.mjs';
10
- const encoder = new TextEncoder();
11
- const BODY = ':body:no-shadow:studio-fur-v6:';
12
- const VERSION = 'clippo-tube-v1';
13
- const fail = (message) => {
14
- throw new Error(`Clippo geometry: ${message}`);
15
- };
16
- const unit = (p) => {
17
- const n = Math.hypot(...p);
18
- if (!(n > 1e-9)) fail('degenerate tangent');
19
- return p.map((x) => x / n);
20
- };
21
- const point = ([x, y, z = 0]) => [(x - 650) / 240, (400 - y) / 240, z];
22
- export const CLIPPO_EYES = Object.freeze([
23
- Object.freeze({
24
- center: [-102 / 240, 135 / 240, 0.17],
25
- radius: [0.255, 0.265, 0.14],
26
- }),
27
- Object.freeze({
28
- center: [46 / 240, 93 / 240, 0.17],
29
- radius: [0.255, 0.265, 0.14],
30
- }),
31
- ]);
32
- /** Eye size follows the solid face, independently from native eye spacing.
33
- * A narrow native gap is a placement choice, not a request for shallow eyes. */
34
- export function clippoFaceEyeFit(bodyBounds, anchor) {
35
- const values = [
36
- ...bodyBounds.min,
37
- ...bodyBounds.max,
38
- ...anchor.min,
39
- ...anchor.max,
40
- ];
41
- if (
42
- !values.every(Number.isFinite) ||
43
- [bodyBounds, anchor].some((bounds) =>
44
- bounds.min.some((v, k) => v > bounds.max[k]),
45
- )
46
- )
47
- fail('invalid eye fitting bounds');
48
- const eyeScale = Math.max(
49
- 0.65,
50
- Math.min(1.2, (bodyBounds.max[0] - bodyBounds.min[0]) / 2),
51
- );
52
- return {
53
- eyeScale,
54
- center: [
55
- (anchor.min[0] + anchor.max[0]) / 2,
56
- (anchor.min[1] + anchor.max[1]) / 2,
57
- anchor.min[2] + 0.14 * eyeScale,
58
- ],
59
- radius: [0.2, 0.21, 0.14].map((v) => v * eyeScale),
60
- };
61
- }
62
- // Continuous open wire, from the inner endpoint through the upper curl to the
63
- // outer endpoint. The two holes come from geometry, never an alpha cutout.
64
- const PATH = [
65
- [
66
- [604, 383],
67
- [590, 484],
68
- [611, 528],
69
- [656, 530],
70
- ],
71
- [
72
- [656, 530],
73
- [707, 532],
74
- [688, 471],
75
- [684, 417],
76
- ],
77
- [
78
- [684, 417],
79
- [675, 350],
80
- [692, 264],
81
- [711, 218],
82
- ],
83
- [
84
- [711, 218],
85
- [742, 142],
86
- [689, 109],
87
- [648, 119],
88
- ],
89
- [
90
- [648, 119],
91
- [596, 115],
92
- [570, 179],
93
- [553, 235],
94
- ],
95
- [
96
- [553, 235],
97
- [521, 323],
98
- [520, 395],
99
- [536, 482],
100
- ],
101
- [
102
- [536, 482],
103
- [553, 589],
104
- [591, 669],
105
- [663, 657],
106
- ],
107
- [
108
- [663, 657],
109
- [744, 650],
110
- [769, 616],
111
- [754, 526],
112
- ],
113
- [
114
- [754, 526],
115
- [737, 442],
116
- [743, 403],
117
- [778, 360],
118
- ],
119
- ];
120
- function bezier(points, t) {
121
- const s = 1 - t;
122
- return [0, 1, 2].map(
123
- (k) =>
124
- s * s * s * points[0][k] +
125
- 3 * s * s * t * points[1][k] +
126
- 3 * s * t * t * points[2][k] +
127
- t * t * t * points[3][k],
128
- );
129
- }
130
- export function clippoPath(steps = 12) {
131
- if (!Number.isInteger(steps) || steps < 4 || steps > 64)
132
- fail('path resolution');
133
- return PATH.flatMap((curve, index) =>
134
- Array.from(
135
- { length: steps + (index === PATH.length - 1 ? 1 : 0) },
136
- (_, i) => bezier(curve.map(point), i / steps),
137
- ),
138
- );
139
- }
140
- /** A rounded, closed tube around an open planar centerline. Native vertex layout
141
- * stores three position/normal poses, two constant weights and a bend weight.
142
- * The editable original circle has zero position deltas; preserve that contract.
143
- */
144
- export function tubeMesh(path, radius = 0.063, sides = 12) {
145
- if (
146
- !Array.isArray(path) ||
147
- path.length < 2 ||
148
- path.length > 10000 ||
149
- !Number.isFinite(radius) ||
150
- radius <= 0 ||
151
- radius > 1 ||
152
- !Number.isInteger(sides) ||
153
- sides < 6 ||
154
- sides > 64
155
- )
156
- fail('tube parameters');
157
- if (
158
- path.some(
159
- (p) =>
160
- !Array.isArray(p) ||
161
- p.length !== 3 ||
162
- p.some((v) => !Number.isFinite(v)),
163
- )
164
- )
165
- fail('non-finite path');
166
- const ringCount = path.length + 8,
167
- vertices = new Float32Array(ringCount * sides * 24),
168
- indices = [];
169
- const tangent = path.map((p, i) =>
170
- unit(
171
- path[Math.min(i + 1, path.length - 1)].map(
172
- (v, k) => v - path[Math.max(0, i - 1)][k],
173
- ),
174
- ),
175
- );
176
- const rings = [];
177
- for (let i = 4; i > 0; i--) {
178
- const a = (i * Math.PI) / 8;
179
- rings.push({
180
- p: path[0].map((v, k) => v - tangent[0][k] * radius * Math.sin(a)),
181
- t: tangent[0],
182
- r: radius * Math.cos(a),
183
- cap: -Math.sin(a),
184
- });
185
- }
186
- path.forEach((p, i) => rings.push({ p, t: tangent[i], r: radius, cap: 0 }));
187
- for (let i = 1; i <= 4; i++) {
188
- const a = (i * Math.PI) / 8;
189
- rings.push({
190
- p: path
191
- .at(-1)
192
- .map((v, k) => v + tangent.at(-1)[k] * radius * Math.sin(a)),
193
- t: tangent.at(-1),
194
- r: radius * Math.cos(a),
195
- cap: Math.sin(a),
196
- });
197
- }
198
- rings.forEach(({ p, t, r, cap }, i) => {
199
- const n = unit([-t[1], t[0], 0]);
200
- for (let j = 0; j < sides; j++) {
201
- const a = (j / sides) * Math.PI * 2,
202
- radial = n.map((v, k) => v * Math.cos(a) + (k === 2 ? Math.sin(a) : 0));
203
- const normal = unit(radial.map((v, k) => (v * r) / radius + t[k] * cap));
204
- const at = (i * sides + j) * 24;
205
- vertices.set(
206
- p.map((v, k) => v + radial[k] * r),
207
- at,
208
- );
209
- for (const o of [3, 9, 15, 21]) vertices.set(normal, at + o);
210
- vertices[at + 18] = vertices[at + 19] = 1;
211
- vertices[at + 20] = 0;
212
- }
213
- });
214
- for (let i = 0; i < rings.length - 1; i++)
215
- for (let j = 0; j < sides; j++) {
216
- const a = i * sides + j,
217
- b = i * sides + ((j + 1) % sides),
218
- c = (i + 1) * sides + j,
219
- d = (i + 1) * sides + ((j + 1) % sides);
220
- indices.push(a, b, c, b, d, c);
221
- }
222
- return { vertices, indices: Uint32Array.from(indices) };
223
- }
224
- function boundsOf(vertices) {
225
- const min = [Infinity, Infinity, Infinity],
226
- max = [-Infinity, -Infinity, -Infinity];
227
- for (let i = 0; i < vertices.length; i += 24)
228
- for (let k = 0; k < 3; k++) {
229
- const v = vertices[i + k];
230
- if (!Number.isFinite(v)) fail('non-finite vertex');
231
- min[k] = Math.min(min[k], v);
232
- max[k] = Math.max(max[k], v);
233
- }
234
- return { min, max };
235
- }
236
- function boundsUnion(records) {
237
- return {
238
- min: [0, 1, 2].map((k) => Math.min(...records.map((r) => r.bounds.min[k]))),
239
- max: [0, 1, 2].map((k) => Math.max(...records.map((r) => r.bounds.max[k]))),
240
- };
241
- }
242
- function floats(prefix, offset, values) {
243
- const view = new DataView(
244
- prefix.buffer,
245
- prefix.byteOffset,
246
- prefix.byteLength,
247
- );
248
- values.forEach((v, k) => view.setFloat32(offset + k * 4, v, true));
249
- }
250
- function meshRecord(
251
- bytes,
252
- source,
253
- mesh,
254
- name,
255
- { body = false, prefix: customPrefix } = {},
256
- ) {
257
- const prefix =
258
- customPrefix ?? bytes.slice(source.start, source.nameOffset - 4),
259
- bounds = boundsOf(mesh.vertices);
260
- floats(prefix, 0, bounds.min);
261
- floats(prefix, 12, bounds.max);
262
- const encoded = encoder.encode(name),
263
- furBytes = body ? 4 : 0;
264
- if (mesh.vertices.length / 24 > 65535) fail('16-bit mesh limit');
265
- const packedIndices = Uint16Array.from(mesh.indices);
266
- const out = new Uint8Array(
267
- prefix.length +
268
- 4 +
269
- encoded.length +
270
- 4 +
271
- mesh.vertices.byteLength +
272
- 4 +
273
- packedIndices.byteLength +
274
- 4 +
275
- 7 +
276
- furBytes +
277
- 27,
278
- ),
279
- view = new DataView(out.buffer);
280
- let at = 0;
281
- out.set(prefix, at);
282
- at += prefix.length;
283
- view.setUint32(at, encoded.length, true);
284
- at += 4;
285
- out.set(encoded, at);
286
- at += encoded.length;
287
- view.setUint32(at, mesh.vertices.length / 24, true);
288
- at += 4;
289
- out.set(
290
- new Uint8Array(
291
- mesh.vertices.buffer,
292
- mesh.vertices.byteOffset,
293
- mesh.vertices.byteLength,
294
- ),
295
- at,
296
- );
297
- at += mesh.vertices.byteLength;
298
- at += 4;
299
- view.setUint32(at, packedIndices.length, true);
300
- at += 4;
301
- out.set(new Uint8Array(packedIndices.buffer), at);
302
- at += packedIndices.byteLength; // native 16-bit index stream
303
- let sourceFlags = source.vertexOffset + source.vertexCount * 96;
304
- const sourceView = new DataView(
305
- bytes.buffer,
306
- bytes.byteOffset,
307
- bytes.byteLength,
308
- );
309
- sourceFlags += 4 + sourceView.getUint32(sourceFlags, true) * 4;
310
- sourceFlags += 4 + sourceView.getUint32(sourceFlags, true) * 2;
311
- sourceFlags += 4;
312
- at += 4;
313
- out[at++] = bytes[sourceFlags];
314
- out[at++] = bytes[sourceFlags + 1];
315
- out[at++] = body ? 1 : 0;
316
- if (body) at += 4; // fur layout, zero fur strands
317
- const trailer = bytes.slice(source.geometryEnd, source.geometryEnd + 27);
318
- out.set(trailer, at);
319
- view.setUint32(at, mesh.vertices.length / 24, true);
320
- view.setUint32(at + 4, mesh.indices.length, true);
321
- return { bytes: out, name, bounds };
322
- }
323
- function nativeMesh(bytes, part) {
324
- const vertices = new Float32Array(part.vertexCount * 24),
325
- view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
326
- for (let i = 0; i < vertices.length; i++)
327
- vertices[i] = view.getFloat32(part.vertexOffset + i * 4, true);
328
- let at = part.vertexOffset + part.vertexCount * 96;
329
- const n32 = view.getUint32(at, true);
330
- at += 4;
331
- const indices = [];
332
- for (let i = 0; i < n32; i++) indices.push(view.getUint32(at + i * 4, true));
333
- at += n32 * 4;
334
- const n16 = view.getUint32(at, true);
335
- at += 4;
336
- for (let i = 0; i < n16; i++) indices.push(view.getUint16(at + i * 2, true));
337
- return { vertices, indices: Uint32Array.from(indices) };
338
- }
339
- function transformMesh(mesh, origin, scale, center) {
340
- for (let i = 0; i < mesh.vertices.length; i += 24) {
341
- for (let k = 0; k < 3; k++)
342
- mesh.vertices[i + k] =
343
- (mesh.vertices[i + k] - origin[k]) * scale[k] + center[k];
344
- for (const offset of [6, 12])
345
- for (let k = 0; k < 3; k++) mesh.vertices[i + offset + k] *= scale[k];
346
- for (const offset of [3, 9, 15, 21])
347
- mesh.vertices.set(
348
- unit([0, 1, 2].map((k) => mesh.vertices[i + offset + k] / scale[k])),
349
- i + offset,
350
- );
351
- }
352
- return mesh;
353
- }
354
- function centerOf(b) {
355
- return b.min.map((v, k) => (v + b.max[k]) / 2);
356
- }
357
- async function identity(value) {
358
- return sha256(encoder.encode(JSON.stringify([VERSION, value])));
359
- }
360
- function record(bytes, part) {
361
- return {
362
- bytes: bytes.slice(part.start, part.end),
363
- name: part.name,
364
- bounds: part.bounds,
365
- };
366
- }
367
- function eyeParts(bytes, parts, selectedEye) {
368
- const decoder = new TextDecoder();
369
- return parts.filter((p) => {
370
- const prefix = decoder.decode(
371
- bytes.subarray(p.start + 24, p.nameOffset - 4),
372
- );
373
- const raw = bytes.subarray(p.start + 24, p.nameOffset - 4);
374
- const label = encoder.encode(selectedEye);
375
- for (let i = 0; i + 4 + label.length <= raw.length; i++)
376
- if (
377
- new DataView(raw.buffer, raw.byteOffset + i, 4).getUint32(0, true) ===
378
- label.length &&
379
- label.every((v, k) => raw[i + 4 + k] === v)
380
- )
381
- return true;
382
- return prefix.includes('source_integrated_eye');
383
- });
384
- }
385
- function eyePrefix(bytes, part, origin, scale, center) {
386
- const prefix = bytes.slice(part.start, part.nameOffset - 4),
387
- v = new DataView(prefix.buffer);
388
- floats(
389
- prefix,
390
- 40,
391
- [0, 1, 2].map(
392
- (k) =>
393
- (v.getFloat32(40 + k * 4, true) - origin[k]) * scale[k] + center[k],
394
- ),
395
- ); // The original eye effect stores its local half-width/half-height after the
396
- // material name and normal basis. Scaling these with the mesh preserves blink.
397
- if (v.getUint32(108, true) !== 0) fail('unexpected eye attachment metadata');
398
- const effectAt = 116 + v.getUint32(112, true) + 36;
399
- if (prefix[effectAt] !== 5) fail('unknown native eye effect');
400
- for (let k = 0; k < 2; k++) {
401
- const at = effectAt + 2 + k * 4;
402
- v.setFloat32(at, v.getFloat32(at, true) * scale[k], true);
403
- }
404
- return prefix;
405
- }
406
- /** Replace selected Clippo geometry while preserving the original scene footer.
407
- * request.authoredParts.shape / .eyes are independent; other authored pieces
408
- * can be composed afterwards using these valid native eye anchor records.
409
- */
410
- export async function composeClippoAssembly(module, bytes, request) {
411
- const selected = request.authoredParts ?? {},
412
- shape = selected.shape === 'clippo',
413
- eyes = selected.eyes === 'clippo';
414
- if (!shape && !eyes) return bytes;
415
- const info = authoredAssemblyRecords(bytes),
416
- records = info.records.map((p) => record(bytes, p));
417
- const smoothSource = module.orbitPrepareAssembly(
418
- module.presetAppearance('blue_beret'),
419
- request.quality,
420
- `${request.key}:clippo-smooth`,
421
- false,
422
- );
423
- if (!smoothSource.bytes || smoothSource.error)
424
- fail(smoothSource.error || 'smooth material unavailable');
425
- const smoothBytes = smoothSource.bytes.slice(),
426
- smoothPart = authoredAssemblyRecords(smoothBytes).records[3];
427
- const smoothPrefix = (label, color) => {
428
- const prefix = smoothBytes.slice(
429
- smoothPart.start,
430
- smoothPart.nameOffset - 4,
431
- );
432
- const name = encoder.encode('beret');
433
- for (let i = 4; i + 5 <= prefix.length; i++)
434
- if (
435
- new DataView(prefix.buffer).getUint32(i - 4, true) === 5 &&
436
- name.every((v, k) => prefix[i + k] === v)
437
- )
438
- prefix.set(encoder.encode(label), i);
439
- floats(prefix, 40, [0, 0, 0]);
440
- floats(prefix, 96, [0, 0, 0]);
441
- if (color) {
442
- floats(prefix, 28, color);
443
- floats(prefix, 60, color);
444
- }
445
- return prefix;
446
- };
447
- if (shape) {
448
- const mesh = tubeMesh(
449
- clippoPath(request.quality === 0 ? 8 : 14),
450
- 0.063,
451
- request.quality === 0 ? 10 : 16,
452
- );
453
- const name =
454
- (await identity(['body', info.body.name, request.quality])) + BODY;
455
- records[0] = meshRecord(bytes, info.records[0], mesh, name, {
456
- body: true,
457
- prefix: smoothPrefix(
458
- 'metal',
459
- [0, 1, 2].map((k) =>
460
- new DataView(
461
- bytes.buffer,
462
- bytes.byteOffset,
463
- bytes.byteLength,
464
- ).getFloat32(info.records[0].start + 28 + k * 4, true),
465
- ),
466
- ),
467
- });
468
- }
469
- const appearance = decodeAppearance(request.appearance);
470
- const originalEyes = eyeParts(bytes, info.records.slice(1), appearance.eyes);
471
- if (originalEyes.length < 2) fail('missing native eye anchors');
472
- const anchors = [-1, 1].map((sign) => {
473
- const parts = originalEyes.filter(
474
- (p) => Math.sign(centerOf(p.bounds)[0]) === sign,
475
- );
476
- if (!parts.length) fail('missing eye side');
477
- return { parts, bounds: boundsUnion(parts) };
478
- });
479
- // The Clippo body places the two eyes at the reference's sloping upper face.
480
- if (shape && !eyes)
481
- for (let side = 0; side < 2; side++)
482
- for (const p of anchors[side].parts) {
483
- const origin = centerOf(anchors[side].bounds),
484
- center = CLIPPO_EYES[side].center;
485
- records[p.part] = await translateAuthoredRecord(
486
- bytes,
487
- p,
488
- center.map((v, k) => v - origin[k]),
489
- );
490
- }
491
- if (shape) {
492
- const center = centerOf(records[0].bounds),
493
- oldCenter = centerOf(info.body.bounds);
494
- const faceCenter = [0, 1, 2].map(
495
- (k) =>
496
- (centerOf(anchors[0].bounds)[k] + centerOf(anchors[1].bounds)[k]) / 2,
497
- ),
498
- newFace = [0, 1, 2].map(
499
- (k) => (CLIPPO_EYES[0].center[k] + CLIPPO_EYES[1].center[k]) / 2,
500
- );
501
- for (const p of info.records.slice(1)) {
502
- if (originalEyes.includes(p)) continue;
503
- const prefix = bytes.subarray(p.start, p.nameOffset - 4);
504
- const named = (label) => {
505
- const needle = encoder.encode(label);
506
- for (let i = 28; i + 4 + needle.length <= prefix.length; i++)
507
- if (
508
- new DataView(prefix.buffer, prefix.byteOffset + i, 4).getUint32(
509
- 0,
510
- true,
511
- ) === needle.length &&
512
- needle.every((v, k) => prefix[i + 4 + k] === v)
513
- )
514
- return true;
515
- return false;
516
- };
517
- if (appearance.accessories.some(named)) {
518
- // Scale the whole attachment about the original crown so a narrow metal
519
- // head does not inherit the much wider circle's hat/headphone footprint.
520
- const scale = 0.56;
521
- const origin = [oldCenter[0], info.body.bounds.max[1], oldCenter[2]];
522
- records[p.part] = await transformAuthoredRecord(bytes, p, {
523
- scale,
524
- origin,
525
- translate: [
526
- 0.02 - origin[0],
527
- records[0].bounds.max[1] - origin[1],
528
- -origin[2],
529
- ],
530
- });
531
- } else if (appearance.eyewear !== 'none' && named(appearance.eyewear))
532
- records[p.part] = await translateAuthoredRecord(bytes, p, [
533
- newFace[0] - faceCenter[0],
534
- newFace[1] - faceCenter[1],
535
- 0.31 - Math.max(...anchors.map((a) => a.bounds.max[2])),
536
- ]);
537
- }
538
- }
539
- if (eyes) {
540
- const prepared = module.orbitPrepareAssembly(
541
- module.presetAppearance('lime_frog'),
542
- request.quality,
543
- `${request.key}:clippo-eyes`,
544
- false,
545
- );
546
- if (!prepared.bytes || prepared.error)
547
- fail(prepared.error || 'native eye source unavailable');
548
- const sourceBytes = prepared.bytes.slice(),
549
- source = authoredAssemblyRecords(sourceBytes);
550
- const sources = source.records.slice(1, 5);
551
- if (sources.length !== 4) fail('native eye source changed');
552
- const replacements = [];
553
- for (let side = 0; side < 2; side++) {
554
- const pair = sources.slice(side * 2, side * 2 + 2),
555
- outer = pair[0],
556
- origin = centerOf(outer.bounds),
557
- anchor = anchors[side].bounds;
558
- const fittedEye = clippoFaceEyeFit(info.body.bounds, anchor);
559
- const layout = request.faceLayout;
560
- const eyeScale = layout ? layout.radius / 0.21 : fittedEye.eyeScale;
561
- const center = shape
562
- ? CLIPPO_EYES[side].center
563
- : layout
564
- ? [
565
- layout.centers[side][0],
566
- layout.centers[side][1],
567
- layout.centers[side][2] + 0.14 * eyeScale,
568
- ]
569
- : fittedEye.center;
570
- const radius = shape
571
- ? CLIPPO_EYES[side].radius
572
- : layout
573
- ? [0.2, 0.21, 0.14].map((v) => v * eyeScale)
574
- : fittedEye.radius,
575
- scale = radius.map(
576
- (r, k) => (r * 2) / (outer.bounds.max[k] - outer.bounds.min[k]),
577
- );
578
- for (const p of pair) {
579
- const mesh = transformMesh(
580
- nativeMesh(sourceBytes, p),
581
- origin,
582
- scale,
583
- center,
584
- ),
585
- prefix = eyePrefix(sourceBytes, p, origin, scale, center);
586
- if (p === pair[1]) {
587
- prefix[88] = 0;
588
- floats(prefix, 28, [0.16, 0.09, 0.09]);
589
- floats(prefix, 60, [0.16, 0.09, 0.09]);
590
- }
591
- const name =
592
- (await identity([p.name, center, scale, 'clippo-eye'])) +
593
- p.name.slice(64);
594
- replacements.push(meshRecord(sourceBytes, p, mesh, name, { prefix }));
595
- }
596
- const browPath = shape
597
- ? (side === 0
598
- ? [
599
- [548, 160],
600
- [568, 151],
601
- [592, 153],
602
- [608, 160],
603
- ]
604
- : [
605
- [696, 201],
606
- [714, 199],
607
- [734, 212],
608
- [746, 222],
609
- ]
610
- ).map(point)
611
- : [
612
- [-0.14, 0.35, 0],
613
- [-0.08, 0.41, 0],
614
- [0.08, 0.4, 0],
615
- [0.14, 0.35, 0],
616
- ].map((p) => p.map((v, k) => v * eyeScale + center[k]));
617
- if (shape) browPath.forEach((p) => (p[2] = 0.19));
618
- const browMesh = tubeMesh(
619
- Array.from({ length: 17 }, (_, i) => bezier(browPath, i / 16)),
620
- shape ? 0.065 : 0.045 * eyeScale,
621
- 12,
622
- ),
623
- prefix = smoothPrefix('brows', [0.16, 0.09, 0.09]);
624
- const name =
625
- (await identity(['brow', info.body.name, side, browPath])) +
626
- ':surface:shadow';
627
- replacements.push(
628
- meshRecord(bytes, info.records[0], browMesh, name, { prefix }),
629
- );
630
- }
631
- const eyeIndices = new Set(originalEyes.map((p) => p.part));
632
- const retained = records.filter((r, i) => !eyeIndices.has(i));
633
- retained.splice(1, 0, ...replacements);
634
- records.splice(0, records.length, ...retained);
635
- }
636
- const names = records.slice(1).map((r) => r.name),
637
- bodyName =
638
- (await identity([records[0].name, names])) +
639
- BODY +
640
- names.map((n) => `${n.length}:${n}`).join(':');
641
- // Body names index the full attachment set in the native cache.
642
- const first = records[0].bytes,
643
- oldName = encoder.encode(records[0].name),
644
- nameAt = findName(first, oldName),
645
- newName = encoder.encode(bodyName),
646
- renamed = new Uint8Array(first.length + newName.length - oldName.length);
647
- renamed.set(first.subarray(0, nameAt - 4));
648
- new DataView(renamed.buffer).setUint32(nameAt - 4, newName.length, true);
649
- renamed.set(newName, nameAt);
650
- renamed.set(first.subarray(nameAt + oldName.length), nameAt + newName.length);
651
- records[0].bytes = renamed;
652
- const result = new Uint8Array(
653
- 4 + records.reduce((n, r) => n + r.bytes.length, 0) + info.footer.length,
654
- ),
655
- view = new DataView(result.buffer);
656
- view.setUint32(0, records.length, true);
657
- let at = 4;
658
- for (const r of records) {
659
- result.set(r.bytes, at);
660
- at += r.bytes.length;
661
- }
662
- result.set(info.footer, at);
663
- const all = boundsUnion(records);
664
- for (const offset of [0, 28, 56]) {
665
- const b = offset === 28 ? records[0].bounds : all;
666
- floats(result, at + offset, b.min);
667
- floats(result, at + offset + 12, b.max);
668
- }
669
- authoredAssemblyRecords(result);
670
- return result;
671
- }
672
- function findName(bytes, name) {
673
- outer: for (let i = 4; i + name.length <= bytes.length; i++) {
674
- for (let k = 0; k < name.length; k++)
675
- if (bytes[i + k] !== name[k]) continue outer;
676
- return i;
677
- }
678
- fail('missing generated mesh name');
679
- }