@oxy.so/bloom 7.0.1 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/character-runtime/README.md +55 -0
- package/assets/character-runtime/appearance-codec.mjs +149 -0
- package/assets/character-runtime/integrity.json +6 -0
- package/assets/character-runtime/legacy-engine.mjs +105 -0
- package/assets/character-runtime/legacy-geometry.mjs +166 -0
- package/assets/character-runtime/legacy-worker.mjs +85 -0
- package/assets/character-runtime/managed-avatar.mjs +258 -0
- package/assets/character-runtime/orbit-characters.data +0 -0
- package/assets/character-runtime/orbit-characters.mjs +30 -0
- package/assets/character-runtime/orbit-characters.wasm +0 -0
- package/assets/character-runtime/preparation-worker.mjs +19 -0
- package/assets/character-runtime/render-budget.mjs +144 -0
- package/assets/character-runtime/runtime.mjs +851 -0
- package/assets/character-runtime/thumbnails/eyes/crescent_inset.png +0 -0
- package/assets/character-runtime/thumbnails/eyes/dots.png +0 -0
- package/assets/character-runtime/thumbnails/eyes/double_highlights.png +0 -0
- package/assets/character-runtime/thumbnails/eyes/highlight_capsules.png +0 -0
- package/assets/character-runtime/thumbnails/eyes/oval.png +0 -0
- package/assets/character-runtime/thumbnails/eyes/round_inset.png +0 -0
- package/assets/character-runtime/thumbnails/eyes/sleepy_lids.png +0 -0
- package/assets/character-runtime/thumbnails/eyes/sparkle_capsules.png +0 -0
- package/assets/character-runtime/thumbnails/eyes/swept_lids.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/capsule.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/circle.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/circle_two_ears.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/four_lobed_butterfly.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/heart.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/rounded_cube.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/rounded_diamond.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/rounded_head_two_ears.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/rounded_triangle.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/six_lobed_flower.png +0 -0
- package/assets/character-runtime/thumbnails/shapes/twelve_scalloped_rosette.png +0 -0
- package/docs/adoption-matrix.mdx +9 -9
- package/docs/agent-avatar.mdx +44 -10
- package/docs/agent-creator.mdx +12 -4
- package/docs/multi-agent-chat.mdx +12 -0
- package/docs/project-board.mdx +3 -3
- package/lib/commonjs/agent-avatar/AgentAvatar.js +15 -203
- package/lib/commonjs/agent-avatar/AgentAvatar.js.map +1 -1
- package/lib/commonjs/agent-avatar/AgentAvatarProvider.js +69 -0
- package/lib/commonjs/agent-avatar/AgentAvatarProvider.js.map +1 -0
- package/lib/commonjs/agent-avatar/CharacterAvatar.js +212 -0
- package/lib/commonjs/agent-avatar/CharacterAvatar.js.map +1 -0
- package/lib/commonjs/agent-avatar/ProceduralAvatar.js +216 -0
- package/lib/commonjs/agent-avatar/ProceduralAvatar.js.map +1 -0
- package/lib/commonjs/agent-avatar/artwork.js +4 -3
- package/lib/commonjs/agent-avatar/artwork.js.map +1 -1
- package/lib/commonjs/agent-avatar/avatar-color.js +16 -0
- package/lib/commonjs/agent-avatar/avatar-color.js.map +1 -0
- package/lib/commonjs/agent-avatar/character-html.js +25 -0
- package/lib/commonjs/agent-avatar/character-html.js.map +1 -0
- package/lib/commonjs/agent-avatar/character-runtime-module.js +39 -0
- package/lib/commonjs/agent-avatar/character-runtime-module.js.map +1 -0
- package/lib/commonjs/agent-avatar/character-webview.js +18 -0
- package/lib/commonjs/agent-avatar/character-webview.js.map +1 -0
- package/lib/commonjs/agent-avatar/config-character.js +36 -0
- package/lib/commonjs/agent-avatar/config-character.js.map +1 -0
- package/lib/commonjs/agent-avatar/context.js +6 -1
- package/lib/commonjs/agent-avatar/context.js.map +1 -1
- package/lib/commonjs/agent-avatar/index.js +7 -0
- package/lib/commonjs/agent-avatar/index.js.map +1 -1
- package/lib/commonjs/agent-avatar/legacy-contours.js +57 -0
- package/lib/commonjs/agent-avatar/legacy-contours.js.map +1 -0
- package/lib/commonjs/agent-avatar/legacy-recipe.js +112 -0
- package/lib/commonjs/agent-avatar/legacy-recipe.js.map +1 -0
- package/lib/commonjs/agent-avatar/messages.js +2 -1
- package/lib/commonjs/agent-avatar/messages.js.map +1 -1
- package/lib/commonjs/agent-avatar/model.js +2 -0
- package/lib/commonjs/agent-avatar/model.js.map +1 -1
- package/lib/commonjs/agent-creator/AgentCreatorBase.js +251 -25
- package/lib/commonjs/agent-creator/AgentCreatorBase.js.map +1 -1
- package/lib/commonjs/agent-creator/CharacterControls.js +115 -0
- package/lib/commonjs/agent-creator/CharacterControls.js.map +1 -0
- package/lib/commonjs/agent-creator/EmotionPicker.js +51 -18
- package/lib/commonjs/agent-creator/EmotionPicker.js.map +1 -1
- package/lib/commonjs/agent-creator/ShapeArc.js +56 -26
- package/lib/commonjs/agent-creator/ShapeArc.js.map +1 -1
- package/lib/commonjs/agent-creator/ShapeSilhouette.js +62 -0
- package/lib/commonjs/agent-creator/ShapeSilhouette.js.map +1 -0
- package/lib/commonjs/agent-creator/constants.js +48 -1
- package/lib/commonjs/agent-creator/constants.js.map +1 -1
- package/lib/commonjs/agent-creator/messages.js +9 -0
- package/lib/commonjs/agent-creator/messages.js.map +1 -1
- package/lib/commonjs/agent-creator/shared.js +7 -10
- package/lib/commonjs/agent-creator/shared.js.map +1 -1
- package/lib/commonjs/agent-thinking/AgentThinking.js +4 -62
- package/lib/commonjs/agent-thinking/AgentThinking.js.map +1 -1
- package/lib/commonjs/agent-thinking/ThinkingLabel.js +77 -0
- package/lib/commonjs/agent-thinking/ThinkingLabel.js.map +1 -0
- package/lib/commonjs/chart-cards/TokensChartCard.js +20 -5
- package/lib/commonjs/chart-cards/TokensChartCard.js.map +1 -1
- package/lib/commonjs/locale/translations/ar.js +11 -1
- package/lib/commonjs/locale/translations/ar.js.map +1 -1
- package/lib/commonjs/locale/translations/bn.js +11 -1
- package/lib/commonjs/locale/translations/bn.js.map +1 -1
- package/lib/commonjs/locale/translations/ca.js +11 -1
- package/lib/commonjs/locale/translations/ca.js.map +1 -1
- package/lib/commonjs/locale/translations/de.js +11 -1
- package/lib/commonjs/locale/translations/de.js.map +1 -1
- package/lib/commonjs/locale/translations/es.js +11 -1
- package/lib/commonjs/locale/translations/es.js.map +1 -1
- package/lib/commonjs/locale/translations/fr.js +11 -1
- package/lib/commonjs/locale/translations/fr.js.map +1 -1
- package/lib/commonjs/locale/translations/hi.js +11 -1
- package/lib/commonjs/locale/translations/hi.js.map +1 -1
- package/lib/commonjs/locale/translations/id.js +11 -1
- package/lib/commonjs/locale/translations/id.js.map +1 -1
- package/lib/commonjs/locale/translations/it.js +11 -1
- package/lib/commonjs/locale/translations/it.js.map +1 -1
- package/lib/commonjs/locale/translations/ja.js +11 -1
- package/lib/commonjs/locale/translations/ja.js.map +1 -1
- package/lib/commonjs/locale/translations/pt.js +11 -1
- package/lib/commonjs/locale/translations/pt.js.map +1 -1
- package/lib/commonjs/locale/translations/ru.js +11 -1
- package/lib/commonjs/locale/translations/ru.js.map +1 -1
- package/lib/commonjs/locale/translations/tr.js +11 -1
- package/lib/commonjs/locale/translations/tr.js.map +1 -1
- package/lib/commonjs/locale/translations/zh.js +11 -1
- package/lib/commonjs/locale/translations/zh.js.map +1 -1
- package/lib/commonjs/multi-agent-chat/AvatarHandoff.js +2 -4
- package/lib/commonjs/multi-agent-chat/AvatarHandoff.js.map +1 -1
- package/lib/commonjs/multi-agent-chat/ChatAgentProfile.js +97 -0
- package/lib/commonjs/multi-agent-chat/ChatAgentProfile.js.map +1 -0
- package/lib/commonjs/multi-agent-chat/EditorRail.js +4 -0
- package/lib/commonjs/multi-agent-chat/EditorRail.js.map +1 -1
- package/lib/commonjs/multi-agent-chat/MultiAgentChatBase.js +89 -126
- package/lib/commonjs/multi-agent-chat/MultiAgentChatBase.js.map +1 -1
- package/lib/commonjs/multi-agent-chat/ReplyRow.js +8 -11
- package/lib/commonjs/multi-agent-chat/ReplyRow.js.map +1 -1
- package/lib/commonjs/multi-agent-chat/handoff.js +5 -5
- package/lib/commonjs/multi-agent-chat/handoff.js.map +1 -1
- package/lib/commonjs/project-board/CreateTicketDialog.js +33 -2
- package/lib/commonjs/project-board/CreateTicketDialog.js.map +1 -1
- package/lib/commonjs/project-board/ProjectBoardBase.js +137 -38
- package/lib/commonjs/project-board/ProjectBoardBase.js.map +1 -1
- package/lib/commonjs/project-board/TicketCornerGenieSurface.web.js +34 -28
- package/lib/commonjs/project-board/TicketCornerGenieSurface.web.js.map +1 -1
- package/lib/commonjs/project-board/TicketDetailDialog.js +6 -3
- package/lib/commonjs/project-board/TicketDetailDialog.js.map +1 -1
- package/lib/commonjs/project-board/TicketGenieSurface.js +17 -7
- package/lib/commonjs/project-board/TicketGenieSurface.js.map +1 -1
- package/lib/commonjs/project-board/TicketGenieSurface.web.js +1 -1
- package/lib/commonjs/project-board/TicketGenieSurface.web.js.map +1 -1
- package/lib/commonjs/project-board/TicketPresence.js +125 -0
- package/lib/commonjs/project-board/TicketPresence.js.map +1 -0
- package/lib/commonjs/project-board/TicketTokenChart.js +23 -0
- package/lib/commonjs/project-board/TicketTokenChart.js.map +1 -0
- package/lib/commonjs/project-board/context.js +3 -1
- package/lib/commonjs/project-board/context.js.map +1 -1
- package/lib/commonjs/search/Search.js +12 -3
- package/lib/commonjs/search/Search.js.map +1 -1
- package/lib/commonjs/sidebar/SidebarToolbar.js +28 -14
- package/lib/commonjs/sidebar/SidebarToolbar.js.map +1 -1
- package/lib/commonjs/text-field/TextField.js +13 -7
- package/lib/commonjs/text-field/TextField.js.map +1 -1
- package/lib/module/agent-avatar/AgentAvatar.js +16 -204
- package/lib/module/agent-avatar/AgentAvatar.js.map +1 -1
- package/lib/module/agent-avatar/AgentAvatarProvider.js +65 -0
- package/lib/module/agent-avatar/AgentAvatarProvider.js.map +1 -0
- package/lib/module/agent-avatar/CharacterAvatar.js +208 -0
- package/lib/module/agent-avatar/CharacterAvatar.js.map +1 -0
- package/lib/module/agent-avatar/ProceduralAvatar.js +212 -0
- package/lib/module/agent-avatar/ProceduralAvatar.js.map +1 -0
- package/lib/module/agent-avatar/artwork.js +3 -3
- package/lib/module/agent-avatar/artwork.js.map +1 -1
- package/lib/module/agent-avatar/avatar-color.js +12 -0
- package/lib/module/agent-avatar/avatar-color.js.map +1 -0
- package/lib/module/agent-avatar/character-html.js +19 -0
- package/lib/module/agent-avatar/character-html.js.map +1 -0
- package/lib/module/agent-avatar/character-runtime-module.js +35 -0
- package/lib/module/agent-avatar/character-runtime-module.js.map +1 -0
- package/lib/module/agent-avatar/character-webview.js +14 -0
- package/lib/module/agent-avatar/character-webview.js.map +1 -0
- package/lib/module/agent-avatar/config-character.js +32 -0
- package/lib/module/agent-avatar/config-character.js.map +1 -0
- package/lib/module/agent-avatar/context.js +5 -0
- package/lib/module/agent-avatar/context.js.map +1 -1
- package/lib/module/agent-avatar/index.js +1 -0
- package/lib/module/agent-avatar/index.js.map +1 -1
- package/lib/module/agent-avatar/legacy-contours.js +53 -0
- package/lib/module/agent-avatar/legacy-contours.js.map +1 -0
- package/lib/module/agent-avatar/legacy-recipe.js +104 -0
- package/lib/module/agent-avatar/legacy-recipe.js.map +1 -0
- package/lib/module/agent-avatar/messages.js +2 -1
- package/lib/module/agent-avatar/messages.js.map +1 -1
- package/lib/module/agent-avatar/model.js +2 -0
- package/lib/module/agent-avatar/model.js.map +1 -1
- package/lib/module/agent-creator/AgentCreatorBase.js +248 -22
- package/lib/module/agent-creator/AgentCreatorBase.js.map +1 -1
- package/lib/module/agent-creator/CharacterControls.js +112 -0
- package/lib/module/agent-creator/CharacterControls.js.map +1 -0
- package/lib/module/agent-creator/EmotionPicker.js +52 -19
- package/lib/module/agent-creator/EmotionPicker.js.map +1 -1
- package/lib/module/agent-creator/ShapeArc.js +58 -28
- package/lib/module/agent-creator/ShapeArc.js.map +1 -1
- package/lib/module/agent-creator/ShapeSilhouette.js +57 -0
- package/lib/module/agent-creator/ShapeSilhouette.js.map +1 -0
- package/lib/module/agent-creator/constants.js +47 -0
- package/lib/module/agent-creator/constants.js.map +1 -1
- package/lib/module/agent-creator/messages.js +9 -0
- package/lib/module/agent-creator/messages.js.map +1 -1
- package/lib/module/agent-creator/shared.js +1 -9
- package/lib/module/agent-creator/shared.js.map +1 -1
- package/lib/module/agent-thinking/AgentThinking.js +5 -63
- package/lib/module/agent-thinking/AgentThinking.js.map +1 -1
- package/lib/module/agent-thinking/ThinkingLabel.js +73 -0
- package/lib/module/agent-thinking/ThinkingLabel.js.map +1 -0
- package/lib/module/chart-cards/TokensChartCard.js +20 -5
- package/lib/module/chart-cards/TokensChartCard.js.map +1 -1
- package/lib/module/locale/translations/ar.js +11 -1
- package/lib/module/locale/translations/ar.js.map +1 -1
- package/lib/module/locale/translations/bn.js +11 -1
- package/lib/module/locale/translations/bn.js.map +1 -1
- package/lib/module/locale/translations/ca.js +11 -1
- package/lib/module/locale/translations/ca.js.map +1 -1
- package/lib/module/locale/translations/de.js +11 -1
- package/lib/module/locale/translations/de.js.map +1 -1
- package/lib/module/locale/translations/es.js +11 -1
- package/lib/module/locale/translations/es.js.map +1 -1
- package/lib/module/locale/translations/fr.js +11 -1
- package/lib/module/locale/translations/fr.js.map +1 -1
- package/lib/module/locale/translations/hi.js +11 -1
- package/lib/module/locale/translations/hi.js.map +1 -1
- package/lib/module/locale/translations/id.js +11 -1
- package/lib/module/locale/translations/id.js.map +1 -1
- package/lib/module/locale/translations/it.js +11 -1
- package/lib/module/locale/translations/it.js.map +1 -1
- package/lib/module/locale/translations/ja.js +11 -1
- package/lib/module/locale/translations/ja.js.map +1 -1
- package/lib/module/locale/translations/pt.js +11 -1
- package/lib/module/locale/translations/pt.js.map +1 -1
- package/lib/module/locale/translations/ru.js +11 -1
- package/lib/module/locale/translations/ru.js.map +1 -1
- package/lib/module/locale/translations/tr.js +11 -1
- package/lib/module/locale/translations/tr.js.map +1 -1
- package/lib/module/locale/translations/zh.js +11 -1
- package/lib/module/locale/translations/zh.js.map +1 -1
- package/lib/module/multi-agent-chat/AvatarHandoff.js +3 -5
- package/lib/module/multi-agent-chat/AvatarHandoff.js.map +1 -1
- package/lib/module/multi-agent-chat/ChatAgentProfile.js +94 -0
- package/lib/module/multi-agent-chat/ChatAgentProfile.js.map +1 -0
- package/lib/module/multi-agent-chat/EditorRail.js +4 -0
- package/lib/module/multi-agent-chat/EditorRail.js.map +1 -1
- package/lib/module/multi-agent-chat/MultiAgentChatBase.js +89 -126
- package/lib/module/multi-agent-chat/MultiAgentChatBase.js.map +1 -1
- package/lib/module/multi-agent-chat/ReplyRow.js +9 -12
- package/lib/module/multi-agent-chat/ReplyRow.js.map +1 -1
- package/lib/module/multi-agent-chat/handoff.js +4 -4
- package/lib/module/multi-agent-chat/handoff.js.map +1 -1
- package/lib/module/project-board/CreateTicketDialog.js +33 -2
- package/lib/module/project-board/CreateTicketDialog.js.map +1 -1
- package/lib/module/project-board/ProjectBoardBase.js +138 -39
- package/lib/module/project-board/ProjectBoardBase.js.map +1 -1
- package/lib/module/project-board/TicketCornerGenieSurface.web.js +35 -29
- package/lib/module/project-board/TicketCornerGenieSurface.web.js.map +1 -1
- package/lib/module/project-board/TicketDetailDialog.js +7 -4
- package/lib/module/project-board/TicketDetailDialog.js.map +1 -1
- package/lib/module/project-board/TicketGenieSurface.js +17 -7
- package/lib/module/project-board/TicketGenieSurface.js.map +1 -1
- package/lib/module/project-board/TicketGenieSurface.web.js +1 -1
- package/lib/module/project-board/TicketGenieSurface.web.js.map +1 -1
- package/lib/module/project-board/TicketPresence.js +119 -0
- package/lib/module/project-board/TicketPresence.js.map +1 -0
- package/lib/module/project-board/TicketTokenChart.js +20 -0
- package/lib/module/project-board/TicketTokenChart.js.map +1 -0
- package/lib/module/project-board/context.js +2 -0
- package/lib/module/project-board/context.js.map +1 -1
- package/lib/module/search/Search.js +12 -3
- package/lib/module/search/Search.js.map +1 -1
- package/lib/module/sidebar/SidebarToolbar.js +29 -15
- package/lib/module/sidebar/SidebarToolbar.js.map +1 -1
- package/lib/module/text-field/TextField.js +13 -7
- package/lib/module/text-field/TextField.js.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/AgentAvatar.d.ts +2 -2
- package/lib/typescript/commonjs/agent-avatar/AgentAvatar.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/AgentAvatarProvider.d.ts +4 -0
- package/lib/typescript/commonjs/agent-avatar/AgentAvatarProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/CharacterAvatar.d.ts +4 -0
- package/lib/typescript/commonjs/agent-avatar/CharacterAvatar.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/ProceduralAvatar.d.ts +6 -0
- package/lib/typescript/commonjs/agent-avatar/ProceduralAvatar.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/artwork.d.ts +2 -1
- package/lib/typescript/commonjs/agent-avatar/artwork.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/avatar-color.d.ts +3 -0
- package/lib/typescript/commonjs/agent-avatar/avatar-color.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/character-html.d.ts +4 -0
- package/lib/typescript/commonjs/agent-avatar/character-html.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/character-runtime-module.d.ts +2 -0
- package/lib/typescript/commonjs/agent-avatar/character-runtime-module.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/character-webview.d.ts +24 -0
- package/lib/typescript/commonjs/agent-avatar/character-webview.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/config-character.d.ts +11 -0
- package/lib/typescript/commonjs/agent-avatar/config-character.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/context.d.ts +15 -0
- package/lib/typescript/commonjs/agent-avatar/context.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/index.d.ts +3 -1
- package/lib/typescript/commonjs/agent-avatar/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/legacy-contours.d.ts +5 -0
- package/lib/typescript/commonjs/agent-avatar/legacy-contours.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts +40 -0
- package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-avatar/messages.d.ts +1 -0
- package/lib/typescript/commonjs/agent-avatar/messages.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/model.d.ts +3 -0
- package/lib/typescript/commonjs/agent-avatar/model.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-avatar/types.d.ts +10 -1
- package/lib/typescript/commonjs/agent-avatar/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/AgentCreatorBase.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts +8 -0
- package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts +12 -1
- package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/ShapeArc.d.ts +11 -2
- package/lib/typescript/commonjs/agent-creator/ShapeArc.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/ShapeSilhouette.d.ts +6 -0
- package/lib/typescript/commonjs/agent-creator/ShapeSilhouette.d.ts.map +1 -0
- package/lib/typescript/commonjs/agent-creator/constants.d.ts +44 -0
- package/lib/typescript/commonjs/agent-creator/constants.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/context.d.ts +9 -0
- package/lib/typescript/commonjs/agent-creator/context.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/messages.d.ts +10 -0
- package/lib/typescript/commonjs/agent-creator/messages.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-creator/shared.d.ts +1 -1
- package/lib/typescript/commonjs/agent-creator/shared.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-thinking/AgentThinking.d.ts.map +1 -1
- package/lib/typescript/commonjs/agent-thinking/ThinkingLabel.d.ts +7 -0
- package/lib/typescript/commonjs/agent-thinking/ThinkingLabel.d.ts.map +1 -0
- package/lib/typescript/commonjs/chart-cards/TokensChartCard.d.ts +3 -1
- package/lib/typescript/commonjs/chart-cards/TokensChartCard.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/ar.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/bn.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/ca.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/de.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/es.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/fr.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/hi.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/id.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/it.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/ja.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/pt.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/ru.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/tr.d.ts.map +1 -1
- package/lib/typescript/commonjs/locale/translations/zh.d.ts.map +1 -1
- package/lib/typescript/commonjs/multi-agent-chat/AvatarHandoff.d.ts.map +1 -1
- package/lib/typescript/commonjs/multi-agent-chat/ChatAgentProfile.d.ts +11 -0
- package/lib/typescript/commonjs/multi-agent-chat/ChatAgentProfile.d.ts.map +1 -0
- package/lib/typescript/commonjs/multi-agent-chat/EditorRail.d.ts.map +1 -1
- package/lib/typescript/commonjs/multi-agent-chat/MultiAgentChatBase.d.ts.map +1 -1
- package/lib/typescript/commonjs/multi-agent-chat/ReplyRow.d.ts.map +1 -1
- package/lib/typescript/commonjs/multi-agent-chat/handoff.d.ts +2 -2
- package/lib/typescript/commonjs/multi-agent-chat/handoff.d.ts.map +1 -1
- package/lib/typescript/commonjs/project-board/CreateTicketDialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/project-board/ProjectBoardBase.d.ts.map +1 -1
- package/lib/typescript/commonjs/project-board/TicketCornerGenieSurface.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/project-board/TicketDetailDialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/project-board/TicketGenieSurface.d.ts.map +1 -1
- package/lib/typescript/commonjs/project-board/TicketPresence.d.ts +17 -0
- package/lib/typescript/commonjs/project-board/TicketPresence.d.ts.map +1 -0
- package/lib/typescript/commonjs/project-board/TicketTokenChart.d.ts +5 -0
- package/lib/typescript/commonjs/project-board/TicketTokenChart.d.ts.map +1 -0
- package/lib/typescript/commonjs/project-board/context.d.ts +2 -0
- package/lib/typescript/commonjs/project-board/context.d.ts.map +1 -1
- package/lib/typescript/commonjs/search/Search.d.ts.map +1 -1
- package/lib/typescript/commonjs/sidebar/SidebarToolbar.d.ts.map +1 -1
- package/lib/typescript/commonjs/text-field/TextField.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/AgentAvatar.d.ts +2 -2
- package/lib/typescript/module/agent-avatar/AgentAvatar.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/AgentAvatarProvider.d.ts +4 -0
- package/lib/typescript/module/agent-avatar/AgentAvatarProvider.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/CharacterAvatar.d.ts +4 -0
- package/lib/typescript/module/agent-avatar/CharacterAvatar.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/ProceduralAvatar.d.ts +6 -0
- package/lib/typescript/module/agent-avatar/ProceduralAvatar.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/artwork.d.ts +2 -1
- package/lib/typescript/module/agent-avatar/artwork.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/avatar-color.d.ts +3 -0
- package/lib/typescript/module/agent-avatar/avatar-color.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/character-html.d.ts +4 -0
- package/lib/typescript/module/agent-avatar/character-html.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/character-runtime-module.d.ts +2 -0
- package/lib/typescript/module/agent-avatar/character-runtime-module.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/character-webview.d.ts +24 -0
- package/lib/typescript/module/agent-avatar/character-webview.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/config-character.d.ts +11 -0
- package/lib/typescript/module/agent-avatar/config-character.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/context.d.ts +15 -0
- package/lib/typescript/module/agent-avatar/context.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/index.d.ts +3 -1
- package/lib/typescript/module/agent-avatar/index.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/legacy-contours.d.ts +5 -0
- package/lib/typescript/module/agent-avatar/legacy-contours.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts +40 -0
- package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts.map +1 -0
- package/lib/typescript/module/agent-avatar/messages.d.ts +1 -0
- package/lib/typescript/module/agent-avatar/messages.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/model.d.ts +3 -0
- package/lib/typescript/module/agent-avatar/model.d.ts.map +1 -1
- package/lib/typescript/module/agent-avatar/types.d.ts +10 -1
- package/lib/typescript/module/agent-avatar/types.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/AgentCreatorBase.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/CharacterControls.d.ts +8 -0
- package/lib/typescript/module/agent-creator/CharacterControls.d.ts.map +1 -0
- package/lib/typescript/module/agent-creator/EmotionPicker.d.ts +12 -1
- package/lib/typescript/module/agent-creator/EmotionPicker.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/ShapeArc.d.ts +11 -2
- package/lib/typescript/module/agent-creator/ShapeArc.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/ShapeSilhouette.d.ts +6 -0
- package/lib/typescript/module/agent-creator/ShapeSilhouette.d.ts.map +1 -0
- package/lib/typescript/module/agent-creator/constants.d.ts +44 -0
- package/lib/typescript/module/agent-creator/constants.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/context.d.ts +9 -0
- package/lib/typescript/module/agent-creator/context.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/messages.d.ts +10 -0
- package/lib/typescript/module/agent-creator/messages.d.ts.map +1 -1
- package/lib/typescript/module/agent-creator/shared.d.ts +1 -1
- package/lib/typescript/module/agent-creator/shared.d.ts.map +1 -1
- package/lib/typescript/module/agent-thinking/AgentThinking.d.ts.map +1 -1
- package/lib/typescript/module/agent-thinking/ThinkingLabel.d.ts +7 -0
- package/lib/typescript/module/agent-thinking/ThinkingLabel.d.ts.map +1 -0
- package/lib/typescript/module/chart-cards/TokensChartCard.d.ts +3 -1
- package/lib/typescript/module/chart-cards/TokensChartCard.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/ar.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/bn.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/ca.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/de.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/es.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/fr.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/hi.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/id.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/it.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/ja.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/pt.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/ru.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/tr.d.ts.map +1 -1
- package/lib/typescript/module/locale/translations/zh.d.ts.map +1 -1
- package/lib/typescript/module/multi-agent-chat/AvatarHandoff.d.ts.map +1 -1
- package/lib/typescript/module/multi-agent-chat/ChatAgentProfile.d.ts +11 -0
- package/lib/typescript/module/multi-agent-chat/ChatAgentProfile.d.ts.map +1 -0
- package/lib/typescript/module/multi-agent-chat/EditorRail.d.ts.map +1 -1
- package/lib/typescript/module/multi-agent-chat/MultiAgentChatBase.d.ts.map +1 -1
- package/lib/typescript/module/multi-agent-chat/ReplyRow.d.ts.map +1 -1
- package/lib/typescript/module/multi-agent-chat/handoff.d.ts +2 -2
- package/lib/typescript/module/multi-agent-chat/handoff.d.ts.map +1 -1
- package/lib/typescript/module/project-board/CreateTicketDialog.d.ts.map +1 -1
- package/lib/typescript/module/project-board/ProjectBoardBase.d.ts.map +1 -1
- package/lib/typescript/module/project-board/TicketCornerGenieSurface.web.d.ts.map +1 -1
- package/lib/typescript/module/project-board/TicketDetailDialog.d.ts.map +1 -1
- package/lib/typescript/module/project-board/TicketGenieSurface.d.ts.map +1 -1
- package/lib/typescript/module/project-board/TicketPresence.d.ts +17 -0
- package/lib/typescript/module/project-board/TicketPresence.d.ts.map +1 -0
- package/lib/typescript/module/project-board/TicketTokenChart.d.ts +5 -0
- package/lib/typescript/module/project-board/TicketTokenChart.d.ts.map +1 -0
- package/lib/typescript/module/project-board/context.d.ts +2 -0
- package/lib/typescript/module/project-board/context.d.ts.map +1 -1
- package/lib/typescript/module/search/Search.d.ts.map +1 -1
- package/lib/typescript/module/sidebar/SidebarToolbar.d.ts.map +1 -1
- package/lib/typescript/module/text-field/TextField.d.ts.map +1 -1
- package/package.json +8 -3
- package/src/agent-avatar/AgentAvatar.tsx +16 -296
- package/src/agent-avatar/AgentAvatarProvider.tsx +79 -0
- package/src/agent-avatar/CharacterAvatar.tsx +260 -0
- package/src/agent-avatar/ProceduralAvatar.tsx +303 -0
- package/src/agent-avatar/artwork.ts +3 -3
- package/src/agent-avatar/avatar-color.ts +17 -0
- package/src/agent-avatar/character-html.ts +21 -0
- package/src/agent-avatar/character-runtime-module.ts +37 -0
- package/src/agent-avatar/character-webview.ts +24 -0
- package/src/agent-avatar/config-character.ts +40 -0
- package/src/agent-avatar/context.ts +17 -0
- package/src/agent-avatar/index.ts +4 -1
- package/src/agent-avatar/legacy-contours.ts +76 -0
- package/src/agent-avatar/legacy-recipe.ts +123 -0
- package/src/agent-avatar/messages.ts +1 -0
- package/src/agent-avatar/model.ts +5 -0
- package/src/agent-avatar/types.ts +12 -1
- package/src/agent-creator/AgentCreatorBase.tsx +338 -39
- package/src/agent-creator/CharacterControls.tsx +150 -0
- package/src/agent-creator/EmotionPicker.tsx +43 -21
- package/src/agent-creator/ShapeArc.tsx +83 -29
- package/src/agent-creator/ShapeSilhouette.tsx +65 -0
- package/src/agent-creator/constants.ts +30 -0
- package/src/agent-creator/messages.ts +19 -0
- package/src/agent-creator/shared.ts +1 -15
- package/src/agent-thinking/AgentThinking.tsx +7 -70
- package/src/agent-thinking/ThinkingLabel.tsx +74 -0
- package/src/chart-cards/TokensChartCard.tsx +10 -6
- package/src/locale/translations/ar.ts +10 -1
- package/src/locale/translations/bn.ts +10 -1
- package/src/locale/translations/ca.ts +10 -1
- package/src/locale/translations/de.ts +10 -1
- package/src/locale/translations/es.ts +10 -1
- package/src/locale/translations/fr.ts +10 -1
- package/src/locale/translations/hi.ts +10 -1
- package/src/locale/translations/id.ts +10 -1
- package/src/locale/translations/it.ts +10 -1
- package/src/locale/translations/ja.ts +10 -1
- package/src/locale/translations/pt.ts +10 -1
- package/src/locale/translations/ru.ts +10 -1
- package/src/locale/translations/tr.ts +10 -1
- package/src/locale/translations/zh.ts +10 -1
- package/src/multi-agent-chat/AvatarHandoff.tsx +2 -5
- package/src/multi-agent-chat/ChatAgentProfile.tsx +116 -0
- package/src/multi-agent-chat/EditorRail.tsx +2 -0
- package/src/multi-agent-chat/MultiAgentChatBase.tsx +123 -175
- package/src/multi-agent-chat/ReplyRow.tsx +10 -9
- package/src/multi-agent-chat/handoff.ts +4 -4
- package/src/project-board/CreateTicketDialog.tsx +28 -4
- package/src/project-board/ProjectBoardBase.tsx +115 -21
- package/src/project-board/TicketCornerGenieSurface.web.tsx +11 -6
- package/src/project-board/TicketDetailDialog.tsx +5 -4
- package/src/project-board/TicketGenieSurface.tsx +9 -0
- package/src/project-board/TicketGenieSurface.web.tsx +1 -1
- package/src/project-board/TicketPresence.tsx +137 -0
- package/src/project-board/TicketTokenChart.tsx +14 -0
- package/src/project-board/context.ts +2 -0
- package/src/search/Search.tsx +6 -5
- package/src/sidebar/SidebarToolbar.tsx +27 -15
- package/src/text-field/TextField.tsx +12 -7
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Recovered character renderer
|
|
2
|
+
|
|
3
|
+
Serve this directory unchanged from a static URL and pass runtime.mjs's URL to
|
|
4
|
+
AgentAvatarProvider. The runtime loads lazily when an avatar becomes visible.
|
|
5
|
+
Serve .mjs as JavaScript and .wasm as application/wasm.
|
|
6
|
+
|
|
7
|
+
The four generated engine files are preserved byte for byte from the supplied
|
|
8
|
+
local beta. integrity.json records their SHA-256 hashes. The complete supplied
|
|
9
|
+
folder, including single-thread and threaded versions, was also backed up. The
|
|
10
|
+
supplied folder contained no engine source or license text; this directory does
|
|
11
|
+
not assign Bloom's license to those binaries.
|
|
12
|
+
|
|
13
|
+
runtime.mjs is an adapter for the original engine, retaining its appearance,
|
|
14
|
+
materials and animations. It owns loading, selection, input, display scaling and
|
|
15
|
+
resource lifetime. There is no replacement mesh renderer in the product.
|
|
16
|
+
|
|
17
|
+
Beta characters share one engine per document and all avatars share a 30fps
|
|
18
|
+
clock. Legacy contours isolate rendering modules to keep native geometry caches
|
|
19
|
+
from returning another silhouette; one worker prepares their scenes. Unused
|
|
20
|
+
modules are released. Static portrait preparation is serialized, cached (up to 64 images), and
|
|
21
|
+
releases its graphics surfaces after painting. Offscreen/background characters
|
|
22
|
+
stop rendering; pause and reduced motion freeze a complete visible frame. The
|
|
23
|
+
binary's initial reduced-motion flag can produce transparent frames; the adapter
|
|
24
|
+
freezes its own clock after painting instead.
|
|
25
|
+
|
|
26
|
+
Current editing supports the beta's original catalog combinations and actual
|
|
27
|
+
availability constraints. appearance-codec.mjs validates explicit RGB and optional eye
|
|
28
|
+
transform edits through the original engine. Untouched presets keep their bytes.
|
|
29
|
+
|
|
30
|
+
legacy-geometry.mjs transforms copies of prepared scene assemblies: existing
|
|
31
|
+
Bloom contours deform the body, pose deltas, normals and fur roots. The packaged
|
|
32
|
+
meshes, manifest and WASM remain untouched. The parser checks structural mesh
|
|
33
|
+
keys, counts, finite values and layout; it is tied to these recovered binaries.
|
|
34
|
+
legacy-worker.mjs applies the deformation before the original renderer consumes
|
|
35
|
+
it. The original wave and working activity operate on this geometry.
|
|
36
|
+
|
|
37
|
+
Eight distinct paper/blob contours use this path. Circle, triangle, flower,
|
|
38
|
+
diamond and heart recipes reuse the original beta shapes instead of duplicates.
|
|
39
|
+
Alien avatars are removed from the visible catalog, with saved-data compatibility. The
|
|
40
|
+
migrated bodies use the original catalog eyes at their authored proportions and
|
|
41
|
+
animations; old expression/eye transform fields no longer alter the 3D face.
|
|
42
|
+
Migrated bodies support original eyewear and accessories. Headwear, Bulb, bow
|
|
43
|
+
and Tuft receive rigid contour-relative translations; eyewear and headphones
|
|
44
|
+
keep original placement. A bounded reference cache identifies attachment meshes
|
|
45
|
+
without changing eyes, materials or fur vectors. Intact presets retain authored
|
|
46
|
+
signature reactions; edited and migrated bodies fall back to the original Wave.
|
|
47
|
+
Mascots and hidden faces still use SVG.
|
|
48
|
+
Original material/grain effects become the beta's 3D surface.
|
|
49
|
+
|
|
50
|
+
Browser gates (with Storybook running) are scripts/verify-character-avatars.mjs
|
|
51
|
+
and scripts/verify-legacy-avatars.mjs. They inspect painted pixels, interaction,
|
|
52
|
+
activity, transitions and resource cleanup, not just preparation callbacks.
|
|
53
|
+
|
|
54
|
+
The optional native bridge uses separate WebViews, which cannot share the web
|
|
55
|
+
engine/context caches. Physical-device validation remains pending.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded codec for the original renderer's ORBAST1 appearance records.
|
|
3
|
+
* Verified against the 108 recovered presets. Unsupported extensions fail closed;
|
|
4
|
+
* opaque model fields are retained, never guessed into new geometry parameters.
|
|
5
|
+
* This is an optional runtime asset and imports no package into Bloom's graph.
|
|
6
|
+
*/
|
|
7
|
+
const MAGIC = 'ORBAST1\0';
|
|
8
|
+
const RIG = 'ORBRIG1\0';
|
|
9
|
+
const HERE = 'ORBHERE1';
|
|
10
|
+
const LIMIT = 65536;
|
|
11
|
+
const textEncoder = new TextEncoder();
|
|
12
|
+
const textDecoder = new TextDecoder('utf-8', { fatal: true });
|
|
13
|
+
const fail = (message) => { throw new Error(`Appearance codec: ${message}`); };
|
|
14
|
+
const finite = (n) => typeof n === 'number' && Number.isFinite(n) && Math.abs(n) <= 3.4028234663852886e38;
|
|
15
|
+
function vector(value, n, label, positive = false) {
|
|
16
|
+
if (!Array.isArray(value) || value.length !== n || value.some(v => !finite(v) || (positive && v <= 0))) fail(`invalid ${label}`);
|
|
17
|
+
return value.slice();
|
|
18
|
+
}
|
|
19
|
+
function transform(value) {
|
|
20
|
+
return { position: vector(value.position ?? [0,0,0],3,'position'), rotation: vector(value.rotation ?? [0,0,0],3,'rotation'), scale: vector(value.scale ?? [1,1,1],3,'scale',true) };
|
|
21
|
+
}
|
|
22
|
+
class Reader {
|
|
23
|
+
constructor(bytes) {
|
|
24
|
+
if (!(bytes instanceof Uint8Array) || bytes.length > LIMIT) fail('expected at most 64 KB of Uint8Array');
|
|
25
|
+
this.b = bytes; this.v = new DataView(bytes.buffer,bytes.byteOffset,bytes.byteLength); this.i = 0;
|
|
26
|
+
}
|
|
27
|
+
need(n) { if (!Number.isInteger(n) || n < 0 || this.i+n > this.b.length) fail('truncated record'); }
|
|
28
|
+
bytes(n) { this.need(n); const b=this.b.slice(this.i,this.i+n);this.i+=n;return b; }
|
|
29
|
+
u8() { this.need(1);return this.b[this.i++]; }
|
|
30
|
+
bool() { const n=this.u8();if(n>1)fail('invalid presence flag');return n; }
|
|
31
|
+
u32() { this.need(4);const n=this.v.getUint32(this.i,true);this.i+=4;return n; }
|
|
32
|
+
count() { const n=this.u32();if(n>256)fail('collection exceeds limit');return n; }
|
|
33
|
+
f() { this.need(4);const n=this.v.getFloat32(this.i,true);this.i+=4;if(!finite(n))fail('non-finite scalar');return n; }
|
|
34
|
+
vec(n) { return Array.from({length:n},()=>this.f()); }
|
|
35
|
+
str() { const n=this.u32();if(n>4096)fail('string exceeds limit');return textDecoder.decode(this.bytes(n)); }
|
|
36
|
+
zero(n=1) { for(let j=0;j<n;j++)if(this.u8()!==0)fail('unsupported model extension'); }
|
|
37
|
+
tag(s) { return this.i+s.length <= this.b.length && s.split('').every((c,j)=>this.b[this.i+j]===c.charCodeAt(0)); }
|
|
38
|
+
trans() { return {position:this.vec(3),rotation:this.vec(3),scale:this.vec(3)}; }
|
|
39
|
+
optional(fn) { return this.bool() ? fn.call(this) : null; }
|
|
40
|
+
map(read) { const entries=[];const keys=new Set();for(let n=this.count();n;n--){const key=this.str();if(keys.has(key))fail('duplicate map key');keys.add(key);entries.push([key,read.call(this)]);}return Object.fromEntries(entries); }
|
|
41
|
+
}
|
|
42
|
+
class Writer {
|
|
43
|
+
constructor() { this.a=[]; }
|
|
44
|
+
bytes(b) { for(const n of b)this.a.push(n);if(this.a.length>LIMIT)fail('record exceeds 64 KB'); }
|
|
45
|
+
u8(n) { if(!Number.isInteger(n)||n<0||n>255)fail('invalid byte');this.a.push(n); }
|
|
46
|
+
u32(n) { if(!Number.isInteger(n)||n<0||n>4096)fail('invalid length');const b=new Uint8Array(4);new DataView(b.buffer).setUint32(0,n,true);this.bytes(b); }
|
|
47
|
+
f(n) { if(!finite(n))fail('non-finite scalar');const b=new Uint8Array(4);new DataView(b.buffer).setFloat32(0,n,true);this.bytes(b); }
|
|
48
|
+
vec(a,n) { vector(a,n,'vector').forEach(v=>this.f(v)); }
|
|
49
|
+
str(s) { if(typeof s!=='string')fail('invalid string');const b=textEncoder.encode(s);this.u32(b.length);this.bytes(b); }
|
|
50
|
+
tag(s) { this.bytes(textEncoder.encode(s)); }
|
|
51
|
+
zero(n=1) { for(let j=0;j<n;j++)this.u8(0); }
|
|
52
|
+
trans(t) { this.vec(t.position,3);this.vec(t.rotation,3);this.vec(t.scale,3); }
|
|
53
|
+
optional(v,fn) { this.u8(v==null?0:1);if(v!=null)fn.call(this,v); }
|
|
54
|
+
map(m,fn) { const entries=Object.entries(m);if(entries.length>256)fail('collection exceeds limit');this.u32(entries.length);for(const[k,v]of entries){this.str(k);fn.call(this,v);} }
|
|
55
|
+
finish() { if(this.a.length>LIMIT)fail('record exceeds 64 KB');return Uint8Array.from(this.a); }
|
|
56
|
+
}
|
|
57
|
+
function readModel(r) {
|
|
58
|
+
// Only the observed zero-valued model prefix is supported; its schema is unknown.
|
|
59
|
+
r.zero(4);
|
|
60
|
+
const m={bodyScale:r.vec(3),upperBodyStart:r.f(),upperBodyScale:r.f(),eyes:[]};
|
|
61
|
+
for(let j=0;j<2;j++){r.zero();m.eyes.push(r.optional(r.trans));}
|
|
62
|
+
// Unnamed flags and scalar remain opaque until their semantics are proven.
|
|
63
|
+
m.opaqueEyeFlags=[r.bool(),r.bool(),r.bool()];
|
|
64
|
+
m.opaqueEyeScalar=m.eyes.some(Boolean)?r.f():null;
|
|
65
|
+
m.eyeScale=r.vec(3);m.pupilScale=r.vec(3);
|
|
66
|
+
m.eyewear=r.optional(r.trans);r.zero();
|
|
67
|
+
m.accessories=r.map(r.trans);
|
|
68
|
+
m.materials=r.map(function(){const flags=this.u8();if(flags>7)fail('unsupported material flags');return {flags,albedo:flags&1?this.vec(3):null,roughness:flags&2?this.f():null,reflectance:flags&4?this.f():null};});
|
|
69
|
+
r.zero();m.headphonesCushionScale=r.vec(3);return m;
|
|
70
|
+
}
|
|
71
|
+
function writeModel(w,m) {
|
|
72
|
+
w.zero(4);w.vec(m.bodyScale,3);w.f(m.upperBodyStart);w.f(m.upperBodyScale);
|
|
73
|
+
if(!Array.isArray(m.eyes)||m.eyes.length!==2)fail('expected two eye transforms');
|
|
74
|
+
for(const eye of m.eyes){w.zero();w.optional(eye,w.trans);}
|
|
75
|
+
if(!Array.isArray(m.opaqueEyeFlags)||m.opaqueEyeFlags.length!==3)fail('invalid model flags');
|
|
76
|
+
for(const n of m.opaqueEyeFlags){if(n!==0&&n!==1)fail('invalid model flag');w.u8(n);}
|
|
77
|
+
if(m.eyes.some(Boolean))w.f(m.opaqueEyeScalar);
|
|
78
|
+
w.vec(m.eyeScale,3);w.vec(m.pupilScale,3);w.optional(m.eyewear,w.trans);w.zero();
|
|
79
|
+
w.map(m.accessories,w.trans);
|
|
80
|
+
w.map(m.materials,function(mat){const flags=mat.flags;if(!Number.isInteger(flags)||flags<0||flags>7)fail('unsupported material flags');this.u8(flags);if(flags&1)this.vec(mat.albedo,3);if(flags&2)this.f(mat.roughness);if(flags&4)this.f(mat.reflectance);});
|
|
81
|
+
w.zero();w.vec(m.headphonesCushionScale,3);
|
|
82
|
+
}
|
|
83
|
+
/** Decode only recognized, fully consumed record layouts. */
|
|
84
|
+
export function decodeAppearance(bytes) {
|
|
85
|
+
const r=new Reader(bytes);if(!r.tag(MAGIC))fail('unsupported record version');r.i+=8;
|
|
86
|
+
const a={version:1,shape:r.str(),color:r.str(),eyes:r.str(),eyewear:r.str()};
|
|
87
|
+
a.accessories=Array.from({length:r.count()},()=>r.str());a.accessoryColors=r.map(r.str);
|
|
88
|
+
a.constrained=r.bool();a.depth=r.f();a.model=r.optional(function(){return readModel(this);});
|
|
89
|
+
a.rig=null;a.hereCharacter=null;
|
|
90
|
+
if(r.tag(RIG)){r.i+=8;a.rig=r.vec(5);}
|
|
91
|
+
if(r.tag(HERE)){r.i+=8;a.hereCharacter={id:r.str(),name:r.str()};}
|
|
92
|
+
if(r.i!==bytes.length)fail('unsupported trailing extension');return a;
|
|
93
|
+
}
|
|
94
|
+
/** Encode a decoded record without changing its selection or opaque metadata. */
|
|
95
|
+
export function encodeAppearance(a) {
|
|
96
|
+
if(a.version!==1)fail('unsupported record version');const w=new Writer();w.tag(MAGIC);
|
|
97
|
+
for(const k of ['shape','color','eyes','eyewear'])w.str(a[k]);
|
|
98
|
+
if(!Array.isArray(a.accessories)||a.accessories.length>256)fail('invalid accessories');
|
|
99
|
+
w.u32(a.accessories.length);a.accessories.forEach(v=>w.str(v));w.map(a.accessoryColors,w.str);
|
|
100
|
+
if(a.constrained!==0&&a.constrained!==1)fail('invalid constrained flag');w.u8(a.constrained);w.f(a.depth);
|
|
101
|
+
w.optional(a.model,function(m){writeModel(this,m);});
|
|
102
|
+
if(a.rig){w.tag(RIG);w.vec(a.rig,5);}
|
|
103
|
+
if(a.hereCharacter){w.tag(HERE);w.str(a.hereCharacter.id);w.str(a.hereCharacter.name);}
|
|
104
|
+
return w.finish();
|
|
105
|
+
}
|
|
106
|
+
function defaultModel() {
|
|
107
|
+
return {bodyScale:[1,1,1],upperBodyStart:Math.fround(.35),upperBodyScale:1,eyes:[null,null],opaqueEyeFlags:[0,0,0],opaqueEyeScalar:null,eyeScale:[1,1,1],pupilScale:[1,1,1],eyewear:null,accessories:{},materials:{},headphonesCushionScale:[1,1,1]};
|
|
108
|
+
}
|
|
109
|
+
function rgb(value) {
|
|
110
|
+
if(typeof value==='string'){
|
|
111
|
+
if(!/^#[\da-f]{6}$/i.test(value))fail('bodyColor must be #RRGGBB');
|
|
112
|
+
return [1,3,5].map(i=>parseInt(value.slice(i,i+2),16)/255);
|
|
113
|
+
}
|
|
114
|
+
const a=vector(value,3,'bodyColor');if(a.some(v=>v<0||v>1))fail('bodyColor outside [0,1]');return a;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Return validated/normalized original-engine state. Does not mutate input bytes
|
|
118
|
+
* or the Character. Caller restores the result once after selections settle.
|
|
119
|
+
* Named Here presets are protected: demotion changes their authored appearance.
|
|
120
|
+
* Explicit {allowPresetDemotion:true} opts into this visible change for research;
|
|
121
|
+
* consumers should normally customize an already editable component state.
|
|
122
|
+
* Supports bodyColor (#RRGGBB or RGB01), bodyScale, eyeTransforms (two transforms),
|
|
123
|
+
* eyeScale, pupilScale, restingEyeClosure and eyeGazeScale. Unsupported keys throw.
|
|
124
|
+
* Eye transform rotations are degrees; positions use renderer body units.
|
|
125
|
+
*/
|
|
126
|
+
export function customizeAppearance(engine,bytes,patch,options={}) {
|
|
127
|
+
const allowed=new Set(['bodyColor','bodyScale','eyeTransforms','eyeScale','pupilScale','restingEyeClosure','eyeGazeScale']);
|
|
128
|
+
if(!patch||typeof patch!=='object'||Array.isArray(patch))fail('invalid patch');
|
|
129
|
+
for(const key of Object.keys(patch))if(!allowed.has(key))fail(`unsupported patch ${key}`);
|
|
130
|
+
if(typeof engine?.validateAppearance!=='function'||typeof engine?.normalizeAppearance!=='function')fail('original validator is required');
|
|
131
|
+
const a=decodeAppearance(bytes);
|
|
132
|
+
if(Object.keys(patch).length===0)return bytes.slice();
|
|
133
|
+
if(a.hereCharacter&&!options.allowPresetDemotion)fail('named preset customization would change its authored appearance');
|
|
134
|
+
a.hereCharacter=null;a.model??=defaultModel();const m=a.model;
|
|
135
|
+
if(patch.bodyColor!==undefined){const prev=m.materials.body??{flags:0,albedo:null,roughness:null,reflectance:null};m.materials.body={...prev,flags:prev.flags|1,albedo:rgb(patch.bodyColor)};}
|
|
136
|
+
for(const key of ['bodyScale','eyeScale','pupilScale'])if(patch[key]!==undefined)m[key]=vector(patch[key],3,key,true);
|
|
137
|
+
if(patch.eyeTransforms!==undefined){
|
|
138
|
+
if(!Array.isArray(patch.eyeTransforms)||patch.eyeTransforms.length!==2)fail('expected two eyeTransforms');
|
|
139
|
+
m.eyes=patch.eyeTransforms.map(transform);m.opaqueEyeFlags=[0,1,1];m.opaqueEyeScalar??=0;
|
|
140
|
+
}
|
|
141
|
+
if(patch.restingEyeClosure!==undefined||patch.eyeGazeScale!==undefined){
|
|
142
|
+
a.rig??=[0,1,1,1,1];
|
|
143
|
+
if(patch.restingEyeClosure!==undefined){const n=patch.restingEyeClosure;if(!finite(n)||n<0||n>1)fail('invalid restingEyeClosure');a.rig[0]=n;}
|
|
144
|
+
if(patch.eyeGazeScale!==undefined){const v=vector(patch.eyeGazeScale,2,'eyeGazeScale');if(v.some(n=>n<0))fail('negative eyeGazeScale');a.rig[3]=v[0];a.rig[4]=v[1];}
|
|
145
|
+
}
|
|
146
|
+
const result=encodeAppearance(a);const error=engine.validateAppearance(result);if(error)fail(error);
|
|
147
|
+
const normalized=engine.normalizeAppearance(result);const normalizedError=engine.validateAppearance(normalized);if(normalizedError)fail(normalizedError);
|
|
148
|
+
return normalized;
|
|
149
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"orbit-characters.mjs": "f3ba670dadba954df1618af83fa314641a4cfddd3597aca93a191c264374eed7",
|
|
3
|
+
"orbit-characters.data": "ffefb69b44f815cccb5f07b4d951d479e527dbabdca68ad9986cf695f9b9c440",
|
|
4
|
+
"orbit-characters.wasm": "c15f3692305c1385a12524e877199ba279b8d53e6bd37a9e533d626f12fcb94b",
|
|
5
|
+
"preparation-worker.mjs": "3caeea63dc364a0dc852a16b704323874902eb0f2a02cc9a2ddf4dc414ae8368"
|
|
6
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import createModule from './orbit-characters.mjs';
|
|
2
|
+
|
|
3
|
+
const pool = new Map();
|
|
4
|
+
const pending = new Map();
|
|
5
|
+
let worker,
|
|
6
|
+
idleTimer,
|
|
7
|
+
sequence = 0;
|
|
8
|
+
function preparationWorker() {
|
|
9
|
+
if (worker) return worker;
|
|
10
|
+
worker = new Worker(new URL('./legacy-worker.mjs', import.meta.url), {
|
|
11
|
+
type: 'module',
|
|
12
|
+
});
|
|
13
|
+
worker.onmessage = ({ data }) => {
|
|
14
|
+
const entry = pending.get(data.id);
|
|
15
|
+
if (!entry) return;
|
|
16
|
+
pending.delete(data.id);
|
|
17
|
+
entry.complete(data);
|
|
18
|
+
};
|
|
19
|
+
worker.onerror = () => {
|
|
20
|
+
const failed = [...pending.values()];
|
|
21
|
+
pending.clear();
|
|
22
|
+
worker?.terminate();
|
|
23
|
+
worker = undefined;
|
|
24
|
+
for (const entry of failed)
|
|
25
|
+
entry.complete({
|
|
26
|
+
error: 'Legacy character preparation failed',
|
|
27
|
+
milliseconds: 0,
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
return worker;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Separate geometry caches for different contours; one shared preparation worker.
|
|
34
|
+
* Unused rendering modules are released, never retained in an unbounded catalog.
|
|
35
|
+
*/
|
|
36
|
+
export async function acquireLegacyEngine(points) {
|
|
37
|
+
clearTimeout(idleTimer);
|
|
38
|
+
const key = JSON.stringify(points);
|
|
39
|
+
let entry = pool.get(key);
|
|
40
|
+
if (!entry) {
|
|
41
|
+
entry = { references: 0, module: null };
|
|
42
|
+
entry.module = createModule({
|
|
43
|
+
locateFile: (file) => new URL(file, import.meta.url).href,
|
|
44
|
+
}).then((module) => {
|
|
45
|
+
module.orbitPrepare = (id, appearance, quality, cacheKey, activities) => {
|
|
46
|
+
const request = ++sequence;
|
|
47
|
+
pending.set(request, {
|
|
48
|
+
owner: entry,
|
|
49
|
+
complete: (result) => {
|
|
50
|
+
module.orbitCompletePreparation(
|
|
51
|
+
id,
|
|
52
|
+
result.bytes ?? null,
|
|
53
|
+
result.error || '',
|
|
54
|
+
result.milliseconds || 0,
|
|
55
|
+
);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
try {
|
|
59
|
+
preparationWorker().postMessage({
|
|
60
|
+
id: request,
|
|
61
|
+
appearance,
|
|
62
|
+
quality,
|
|
63
|
+
key: cacheKey,
|
|
64
|
+
activities,
|
|
65
|
+
points,
|
|
66
|
+
});
|
|
67
|
+
} catch (error) {
|
|
68
|
+
pending.delete(request);
|
|
69
|
+
module.orbitCompletePreparation(id, null, String(error), 0);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
return module;
|
|
73
|
+
});
|
|
74
|
+
pool.set(key, entry);
|
|
75
|
+
}
|
|
76
|
+
entry.references++;
|
|
77
|
+
let released = false;
|
|
78
|
+
const release = () => {
|
|
79
|
+
if (released) return;
|
|
80
|
+
released = true;
|
|
81
|
+
if (--entry.references !== 0) return;
|
|
82
|
+
pool.delete(key);
|
|
83
|
+
for (const [id, request] of pending)
|
|
84
|
+
if (request.owner === entry) pending.delete(id);
|
|
85
|
+
if (!pool.size)
|
|
86
|
+
idleTimer = setTimeout(() => {
|
|
87
|
+
if (!pool.size) {
|
|
88
|
+
worker?.terminate();
|
|
89
|
+
worker = undefined;
|
|
90
|
+
}
|
|
91
|
+
}, 0);
|
|
92
|
+
};
|
|
93
|
+
try {
|
|
94
|
+
return { module: await entry.module, release };
|
|
95
|
+
} catch (error) {
|
|
96
|
+
release();
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const legacyEngineStats = () => ({
|
|
102
|
+
modules: pool.size,
|
|
103
|
+
pending: pending.size,
|
|
104
|
+
worker: !!worker,
|
|
105
|
+
});
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// Adapter for the recovered renderer's prepared vertex layout. Packaged meshes,
|
|
2
|
+
// resource manifests, the WASM binary, and the appearance record stay untouched.
|
|
3
|
+
const decoder = new TextDecoder(), encoder = new TextEncoder();
|
|
4
|
+
const BODY = ':body:no-shadow:studio-fur-v6:';
|
|
5
|
+
// Highlights are separate non-shadow-casting meshes in the original renderer.
|
|
6
|
+
const SURFACES = [':surface:shadow', ':surface:no-shadow'];
|
|
7
|
+
const SURFACE_KEY = /^[a-f0-9]{64}:surface:(?:shadow|no-shadow)$/;
|
|
8
|
+
const FUR_SURFACE_KEY = /^[a-f0-9]{64}:surface:shadow:studio-fur-v6:/;
|
|
9
|
+
const STRIDE = 96, TAU = Math.PI * 2;
|
|
10
|
+
function invalid(message) { throw new Error(`Unsupported prepared avatar geometry: ${message}`); }
|
|
11
|
+
function finite(value) { if (!Number.isFinite(value)) invalid('non-finite coordinate'); return value; }
|
|
12
|
+
function findAll(bytes, text) {
|
|
13
|
+
const needle = encoder.encode(text), result = [];
|
|
14
|
+
outer: for (let i = 0; i <= bytes.length - needle.length; i++) {
|
|
15
|
+
if (bytes[i] !== needle[0]) continue;
|
|
16
|
+
for (let j = 1; j < needle.length; j++) if (bytes[i + j] !== needle[j]) continue outer;
|
|
17
|
+
result.push(i);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Inspect the bounded, length-prefixed mesh records; reject unknown layouts. */
|
|
23
|
+
export function inspectLegacyAssembly(bytes) {
|
|
24
|
+
if (!(bytes instanceof Uint8Array) || bytes.length < 400) invalid('truncated assembly');
|
|
25
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
26
|
+
const uint = at => { if (at < 0 || at + 4 > bytes.length) invalid('truncated count'); return view.getUint32(at, true); };
|
|
27
|
+
const bodies = findAll(bytes, BODY);
|
|
28
|
+
if (bodies.length !== 1) invalid('expected one furry body');
|
|
29
|
+
const bodyStart = bodies[0] - 64;
|
|
30
|
+
const starts = [bodyStart, ...SURFACES.flatMap(kind => findAll(bytes, kind)
|
|
31
|
+
.map(i => i - 64)
|
|
32
|
+
.filter(i => {
|
|
33
|
+
if (i <= bodyStart || i < 4) return false;
|
|
34
|
+
const length = uint(i - 4);
|
|
35
|
+
if (length < 79 || length > 8192 || i + length > bytes.length) return false;
|
|
36
|
+
const name = decoder.decode(bytes.subarray(i, i + length));
|
|
37
|
+
return SURFACE_KEY.test(name) || FUR_SURFACE_KEY.test(name);
|
|
38
|
+
}))
|
|
39
|
+
.sort((a, b) => a - b)];
|
|
40
|
+
const meshCount = uint(0);
|
|
41
|
+
if (meshCount !== starts.length || meshCount > 40) invalid('mesh count/key mismatch');
|
|
42
|
+
const parts = starts.map((nameOffset, part) => {
|
|
43
|
+
const nameLength = uint(nameOffset - 4), name = decoder.decode(bytes.subarray(nameOffset, nameOffset + nameLength));
|
|
44
|
+
if (nameLength < 79 || nameLength > 8192 || nameOffset + nameLength > bytes.length || !/^[a-f0-9]{64}:/.test(name)) invalid('mesh identity');
|
|
45
|
+
if (part === 0 ? !name.includes(BODY) : !SURFACE_KEY.test(name) && !FUR_SURFACE_KEY.test(name)) invalid('mesh kind');
|
|
46
|
+
const vertexCount = uint(nameOffset + nameLength), vertexOffset = nameOffset + nameLength + 4;
|
|
47
|
+
if (vertexCount < 3 || vertexCount > 1000000) invalid('vertex count');
|
|
48
|
+
let at = vertexOffset + vertexCount * STRIDE;
|
|
49
|
+
const count32 = uint(at); at += 4;
|
|
50
|
+
if (count32 > 6000000 || at + count32 * 4 > bytes.length) invalid('32-bit indices');
|
|
51
|
+
for (let i = 0; i < count32; i++) if (uint(at + i * 4) >= vertexCount) invalid('index outside mesh');
|
|
52
|
+
at += count32 * 4;
|
|
53
|
+
const count16 = uint(at); at += 4;
|
|
54
|
+
if (count16 > 6000000 || at + count16 * 2 > bytes.length) invalid('16-bit indices');
|
|
55
|
+
for (let i = 0; i < count16; i++) if (view.getUint16(at + i * 2, true) >= vertexCount) invalid('index outside mesh');
|
|
56
|
+
at += count16 * 2;
|
|
57
|
+
// Empty supplemental vertex buffer followed by three boolean mesh flags.
|
|
58
|
+
if (at + 7 > bytes.length || uint(at) !== 0 || bytes[at + 4] > 1 || bytes[at + 5] > 1 || bytes[at + 6] > 1) invalid('mesh flags');
|
|
59
|
+
const hasFur = bytes[at + 6] === 1; at += 7;
|
|
60
|
+
const furCount = hasFur ? uint(at) : 0, furOffset = hasFur ? at + 4 : 0;
|
|
61
|
+
if (furCount > 1000000 || hasFur && furOffset + furCount * 64 > bytes.length) invalid('fur records');
|
|
62
|
+
const geometryEnd = hasFur ? furOffset + furCount * 64 : at;
|
|
63
|
+
if (geometryEnd > (starts[part + 1] === undefined ? bytes.length : starts[part + 1] - 4)) invalid('overlapping meshes');
|
|
64
|
+
if (part === 0 && !hasFur) invalid('body lacks fur layout');
|
|
65
|
+
if (FUR_SURFACE_KEY.test(name) && !hasFur) invalid('accessory lacks fur layout');
|
|
66
|
+
const min = [Infinity, Infinity, Infinity], max = [-Infinity, -Infinity, -Infinity];
|
|
67
|
+
for (let i = 0; i < vertexCount; i++) for (let k = 0; k < 24; k++) {
|
|
68
|
+
const value = finite(view.getFloat32(vertexOffset + i * STRIDE + k * 4, true));
|
|
69
|
+
if (k < 3) { min[k] = Math.min(min[k], value); max[k] = Math.max(max[k], value); }
|
|
70
|
+
}
|
|
71
|
+
return { part, name, nameOffset, nameLength, vertexCount, vertexOffset, furCount, furOffset, bounds: { min, max } };
|
|
72
|
+
});
|
|
73
|
+
return { body: parts[0], parts };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function mapper({ points, radii, depthScale = 1 }) {
|
|
77
|
+
if (!Number.isFinite(depthScale) || depthScale <= 0 || depthScale > 4) invalid('depth scale');
|
|
78
|
+
if (points && radii || !points && !radii) invalid('provide points or radii');
|
|
79
|
+
const count = (points || radii).length;
|
|
80
|
+
if (count < 16 || count > 65536) invalid('contour resolution');
|
|
81
|
+
if (points) for (const p of points) { if (p.length !== 2) invalid('contour point'); p.forEach(finite); }
|
|
82
|
+
else for (const radius of radii) if (!(finite(radius) > 0)) invalid('contour radius');
|
|
83
|
+
return (x, y, z) => {
|
|
84
|
+
const radius = Math.hypot(x, y), angle = (Math.atan2(y, x) + TAU) % TAU;
|
|
85
|
+
const slot = angle / TAU * count, index = Math.floor(slot), t = slot - index, next = (index + 1) % count;
|
|
86
|
+
if (points) return [radius * (points[index][0] * (1 - t) + points[next][0] * t), radius * (points[index][1] * (1 - t) + points[next][1] * t), z * depthScale];
|
|
87
|
+
const scale = radii[index] * (1 - t) + radii[next] * t;
|
|
88
|
+
return [x * scale, y * scale, z * depthScale];
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function derivative(map, p) {
|
|
92
|
+
const epsilon = .00005, base = map(...p);
|
|
93
|
+
const columns = [0, 1, 2].map(k => { const q = [...p]; q[k] += epsilon; return map(...q).map((v, i) => (v - base[i]) / epsilon); });
|
|
94
|
+
const [a, b, c] = columns;
|
|
95
|
+
const cross = (u, v) => [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];
|
|
96
|
+
const inverse = [cross(b, c), cross(c, a), cross(a, b)];
|
|
97
|
+
const determinant = a.reduce((sum, v, i) => sum + v * inverse[0][i], 0);
|
|
98
|
+
if (Math.abs(determinant) < .000001) invalid('singular contour');
|
|
99
|
+
return { base, vector: v => [0, 1, 2].map(i => columns.reduce((sum, col, j) => sum + col[i] * v[j], 0)), normal: v => [0, 1, 2].map(i => inverse.reduce((sum, col, j) => sum + col[i] * v[j], 0) / determinant) };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Rigid attachment anchors on the source circle, in the engine's XY units.
|
|
103
|
+
* Headwear attaches at the crown, bow at the chin, tuft on the upper-left rim.
|
|
104
|
+
* Eyewear and headphones retain the original engine's face/ear fitting.
|
|
105
|
+
*/
|
|
106
|
+
export function legacyAttachmentOffset(points, accessory) {
|
|
107
|
+
let anchor;
|
|
108
|
+
if (accessory === 'bow') anchor = [0, -1, 0];
|
|
109
|
+
else if (accessory === 'three_lobe') anchor = [-.5, Math.sqrt(.75), 0];
|
|
110
|
+
else if (['beanie', 'hat', 'beret', 'orb', 'crown'].includes(accessory)) anchor = [0, 1, 0];
|
|
111
|
+
else return undefined;
|
|
112
|
+
return mapper({ points })(...anchor).map((value, i) => value - anchor[i]);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Deform a COPY of one prepared circular body. points samples its new XY outline
|
|
117
|
+
* counterclockwise from +X, in renderer units (the source circle radius is 1).
|
|
118
|
+
* radii is the alternative polar representation. geometryKey is a SHA-256 hex
|
|
119
|
+
* identity of the source + deformation, used for the renderer's geometry cache.
|
|
120
|
+
* Attachments may explicitly transform a numbered part around an origin.
|
|
121
|
+
*/
|
|
122
|
+
export function deformLegacyAssembly(bytes, options) {
|
|
123
|
+
const info = inspectLegacyAssembly(bytes), result = bytes.slice();
|
|
124
|
+
if (!/^[a-f0-9]{64}$/.test(options.geometryKey || '')) invalid('missing geometry cache key');
|
|
125
|
+
const view = new DataView(result.buffer), map = mapper(options);
|
|
126
|
+
const read = at => [0, 1, 2].map(i => view.getFloat32(at + i * 4, true));
|
|
127
|
+
const write = (at, values) => values.forEach((v, i) => view.setFloat32(at + i * 4, finite(v), true));
|
|
128
|
+
const unit = v => { const n = Math.hypot(...v); return n > 1e-9 ? v.map(x => x / n) : v; };
|
|
129
|
+
function transform(part, mapping) {
|
|
130
|
+
for (let i = 0; i < part.vertexCount; i++) {
|
|
131
|
+
const at = part.vertexOffset + i * STRIDE, p = read(at), d = derivative(mapping, p);
|
|
132
|
+
// The two pose positions are DELTAS: preserve zero as zero and deform the
|
|
133
|
+
// target position before subtracting the newly transformed base.
|
|
134
|
+
for (const offset of [24, 48]) { const delta = read(at + offset), target = mapping(...p.map((v, k) => v + delta[k])); write(at + offset, target.map((v, k) => v - d.base[k])); }
|
|
135
|
+
for (const offset of [12, 36, 60, 84]) write(at + offset, unit(d.normal(read(at + offset))));
|
|
136
|
+
write(at, d.base);
|
|
137
|
+
}
|
|
138
|
+
for (let i = 0; i < part.furCount; i++) {
|
|
139
|
+
const at = part.furOffset + i * 64, d = derivative(mapping, read(at));
|
|
140
|
+
write(at, d.base); write(at + 12, unit(d.normal(read(at + 12)))); write(at + 24, unit(d.vector(read(at + 24))));
|
|
141
|
+
}
|
|
142
|
+
result.set(encoder.encode(options.geometryKey), part.nameOffset);
|
|
143
|
+
}
|
|
144
|
+
transform(info.body, map);
|
|
145
|
+
for (const attachment of options.attachments || []) {
|
|
146
|
+
const part = info.parts[attachment.part];
|
|
147
|
+
if (!part || part.part === 0) invalid('attachment index');
|
|
148
|
+
const scale = attachment.scale || [1, 1, 1], origin = attachment.origin || [0, 0, 0], translate = attachment.translate || [0, 0, 0];
|
|
149
|
+
if ([scale, origin, translate].some(v => v.length !== 3 || v.some(x => !Number.isFinite(x))) || scale.some(x => x <= 0)) invalid('attachment transform');
|
|
150
|
+
transform(part, (...p) => p.map((v, k) => (v - origin[k]) * scale[k] + origin[k] + translate[k]));
|
|
151
|
+
// Independent transformed parts must not alias the body's cache identity.
|
|
152
|
+
const key = options.attachmentKeys?.[attachment.part];
|
|
153
|
+
if (!/^[a-f0-9]{64}$/.test(key || '')) invalid('attachment cache key');
|
|
154
|
+
result.set(encoder.encode(key), part.nameOffset);
|
|
155
|
+
}
|
|
156
|
+
// Keep original extents while admitting moved accessories and the new body.
|
|
157
|
+
const transformed = [info.body, ...(options.attachments || []).map(a => info.parts[a.part])];
|
|
158
|
+
for (const part of transformed) for (let i = 0; i < part.vertexCount; i++) {
|
|
159
|
+
const p = read(part.vertexOffset + i * STRIDE);
|
|
160
|
+
for (let k = 0; k < 3; k++) {
|
|
161
|
+
view.setFloat32(4 + k * 4, Math.min(view.getFloat32(4 + k * 4, true), p[k]), true);
|
|
162
|
+
view.setFloat32(16 + k * 4, Math.max(view.getFloat32(16 + k * 4, true), p[k]), true);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Shared preparation worker. Only copies of completed scenes are deformed;
|
|
2
|
+
// the recovered engine, packaged meshes and native manifests remain intact.
|
|
3
|
+
import createModule from './orbit-characters.mjs';
|
|
4
|
+
import { decodeAppearance, encodeAppearance } from './appearance-codec.mjs';
|
|
5
|
+
import {
|
|
6
|
+
deformLegacyAssembly,
|
|
7
|
+
inspectLegacyAssembly,
|
|
8
|
+
legacyAttachmentOffset,
|
|
9
|
+
} from './legacy-geometry.mjs';
|
|
10
|
+
const engine = createModule({
|
|
11
|
+
locateFile: (file) => new URL(file, import.meta.url).href,
|
|
12
|
+
});
|
|
13
|
+
const digest = async (value) =>
|
|
14
|
+
Array.from(
|
|
15
|
+
new Uint8Array(
|
|
16
|
+
await crypto.subtle.digest('SHA-256', typeof value === 'string' ? new TextEncoder().encode(value) : value),
|
|
17
|
+
),
|
|
18
|
+
(byte) => byte.toString(16).padStart(2, '0'),
|
|
19
|
+
).join('');
|
|
20
|
+
// Cache only identities, never the large prepared buffers. The same face with
|
|
21
|
+
// no accessories tells us exactly which meshes belong to eyes and eyewear.
|
|
22
|
+
const faceIdentities = new Map();
|
|
23
|
+
async function accessoryTransforms(module, data, source) {
|
|
24
|
+
const appearance = decodeAppearance(data.appearance);
|
|
25
|
+
// The editor selects one accessory. Preserve any unknown multi-accessory
|
|
26
|
+
// state rather than guessing which of its pieces should move together.
|
|
27
|
+
if (appearance.accessories.length !== 1) return {};
|
|
28
|
+
const translate = legacyAttachmentOffset(data.points, appearance.accessories[0]);
|
|
29
|
+
if (!translate || translate.every(value => Math.abs(value) < 1e-6)) return {};
|
|
30
|
+
appearance.accessories = [];
|
|
31
|
+
appearance.accessoryColors = {};
|
|
32
|
+
if (appearance.model) appearance.model.accessories = {};
|
|
33
|
+
const bytes = encodeAppearance(appearance);
|
|
34
|
+
const key = `${await digest(bytes)}:${data.quality}:${data.activities}`;
|
|
35
|
+
let names = faceIdentities.get(key);
|
|
36
|
+
if (!names) {
|
|
37
|
+
const base = module.orbitPrepareAssembly(bytes, data.quality, `${data.key}:attachment-base`, data.activities);
|
|
38
|
+
if (!base.bytes) throw new Error(base.error || 'Accessory reference preparation failed');
|
|
39
|
+
names = new Set(inspectLegacyAssembly(base.bytes).parts.slice(1).map(part => part.name));
|
|
40
|
+
faceIdentities.set(key, names);
|
|
41
|
+
if (faceIdentities.size > 32) faceIdentities.delete(faceIdentities.keys().next().value);
|
|
42
|
+
}
|
|
43
|
+
// Do not move anything unless every original face mesh survives unchanged.
|
|
44
|
+
const current = new Set(source.parts.slice(1).map(part => part.name));
|
|
45
|
+
if ([...names].some(name => !current.has(name))) return {};
|
|
46
|
+
const attachments = source.parts.slice(1)
|
|
47
|
+
.filter(part => !names.has(part.name))
|
|
48
|
+
.map(part => ({ part: part.part, translate }));
|
|
49
|
+
const attachmentKeys = {};
|
|
50
|
+
for (const attachment of attachments) attachmentKeys[attachment.part] = await digest(
|
|
51
|
+
JSON.stringify([source.parts[attachment.part].name, translate]),
|
|
52
|
+
);
|
|
53
|
+
return { attachments, attachmentKeys };
|
|
54
|
+
}
|
|
55
|
+
let queue = Promise.resolve();
|
|
56
|
+
self.onmessage = ({ data }) => {
|
|
57
|
+
queue = queue.then(async () => {
|
|
58
|
+
try {
|
|
59
|
+
const module = await engine;
|
|
60
|
+
const result = module.orbitPrepareAssembly(
|
|
61
|
+
data.appearance,
|
|
62
|
+
data.quality,
|
|
63
|
+
data.key,
|
|
64
|
+
data.activities,
|
|
65
|
+
);
|
|
66
|
+
if (result.bytes) {
|
|
67
|
+
const source = inspectLegacyAssembly(result.bytes);
|
|
68
|
+
const geometryKey = await digest(
|
|
69
|
+
JSON.stringify([source.body.name, data.points]),
|
|
70
|
+
);
|
|
71
|
+
result.bytes = deformLegacyAssembly(result.bytes, {
|
|
72
|
+
points: data.points,
|
|
73
|
+
geometryKey,
|
|
74
|
+
...await accessoryTransforms(module, data, source),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
self.postMessage(
|
|
78
|
+
{ id: data.id, ...result },
|
|
79
|
+
result.bytes ? [result.bytes.buffer] : [],
|
|
80
|
+
);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
self.postMessage({ id: data.id, error: String(error), milliseconds: 0 });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
};
|