@buoy-gg/shared-ui 7.0.35 → 7.0.38
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/README.md +33 -26
- package/floating.d.ts +1 -0
- package/floating.js +2 -0
- package/lib/commonjs/JsModal.js +16 -1
- package/lib/commonjs/JsModal.web.js +16 -1
- package/lib/commonjs/dataViewer/CyberpunkInput.js +6 -1
- package/lib/commonjs/dataViewer/LiveExplorer.js +28 -16
- package/lib/commonjs/hooks/safe-area-impl.js +1 -1
- package/lib/commonjs/icons/ReactQueryIcon.js +9 -161
- package/lib/commonjs/icons/SentryBugIcon.js +9 -171
- package/lib/commonjs/icons/index.js +7 -0
- package/lib/commonjs/index.js +105 -6
- package/lib/commonjs/license/AccountSetup.js +56 -0
- package/lib/commonjs/license/AccountSetup.web.js +81 -0
- package/lib/commonjs/license/FeatureGate.js +10 -43
- package/lib/commonjs/license/FreeAccountPrompt.js +35 -12
- package/lib/commonjs/license/index.js +0 -6
- package/lib/commonjs/license/licenseModule.js +56 -36
- package/lib/commonjs/license/tierLimits.js +12 -63
- package/lib/commonjs/storage/devToolsStorageKeys.js +8 -1
- package/lib/commonjs/stores/BaseEventStore.js +21 -5
- package/lib/commonjs/stores/createToolStore.js +21 -3
- package/lib/commonjs/stores/floatingToolStore.js +71 -0
- package/lib/commonjs/stores/floatingToolStore.test.js +112 -0
- package/lib/commonjs/sync/keyedArrays.js +209 -0
- package/lib/commonjs/sync/toolActionRegistry.js +85 -2
- package/lib/commonjs/sync/toolAttention.test.js +51 -0
- package/lib/commonjs/sync/toolUiBridge.js +58 -0
- package/lib/commonjs/sync/typedEdit.js +228 -0
- package/lib/commonjs/sync/valuePath.js +337 -0
- package/lib/commonjs/sync/valueShape.js +161 -0
- package/lib/commonjs/ui/backgrounds/README.md +52 -0
- package/lib/commonjs/ui/backgrounds/ToolBackground.js +4 -2
- package/lib/commonjs/ui/backgrounds/index.js +8 -1
- package/lib/commonjs/ui/backgrounds/registry.js +8 -0
- package/lib/commonjs/ui/backgrounds/variants/wormhole/motion.js +48 -0
- package/lib/commonjs/ui/backgrounds/variants/wormhole/textures.js +3 -0
- package/lib/commonjs/ui/backgrounds/variants/wormhole.js +133 -0
- package/lib/commonjs/ui/components/ClipboardHintBanner.js +5 -6
- package/lib/commonjs/ui/components/CompactRow.js +94 -74
- package/lib/commonjs/ui/components/DraggableHeader.js +16 -1
- package/lib/commonjs/ui/components/ExpandablePopover.js +38 -6
- package/lib/commonjs/ui/components/HeaderSearchButton.js +17 -4
- package/lib/commonjs/ui/floating/FloatingTool.js +1010 -0
- package/lib/commonjs/ui/floating/FloatingTool.web.js +591 -0
- package/lib/commonjs/ui/floating/FloatingToolHost.js +32 -0
- package/lib/commonjs/ui/floating/FloatingToolHost.web.js +28 -0
- package/lib/commonjs/ui/floating/index.js +105 -0
- package/lib/commonjs/ui/floating/index.web.js +105 -0
- package/lib/commonjs/ui/floating/onboardingConstants.js +70 -0
- package/lib/commonjs/ui/floating/onboardingConstants.web.js +34 -0
- package/lib/commonjs/ui/gameUI/constants/gameUIColors.js +3 -1
- package/lib/commonjs/ui/index.js +118 -2
- package/lib/commonjs/ui/night/nightTheme.js +10 -0
- package/lib/commonjs/ui/night/primitives.js +22 -5
- package/lib/commonjs/ui/otto/OttoSceneView.js +69 -0
- package/lib/commonjs/ui/otto/index.js +22 -0
- package/lib/commonjs/ui/otto/ottoEngine.js +10 -7
- package/lib/commonjs/ui/otto/ottoScenes.js +949 -0
- package/lib/commonjs/utils/minimalSuperJSON.js +13 -3
- package/lib/module/JsModal.js +16 -1
- package/lib/module/JsModal.web.js +16 -1
- package/lib/module/dataViewer/CyberpunkInput.js +6 -1
- package/lib/module/dataViewer/LiveExplorer.js +28 -16
- package/lib/module/hooks/safe-area-impl.js +1 -1
- package/lib/module/icons/ReactQueryIcon.js +9 -161
- package/lib/module/icons/SentryBugIcon.js +9 -171
- package/lib/module/icons/index.js +3 -1
- package/lib/module/index.js +8 -1
- package/lib/module/license/AccountSetup.js +52 -0
- package/lib/module/license/AccountSetup.web.js +77 -0
- package/lib/module/license/FeatureGate.js +10 -43
- package/lib/module/license/FreeAccountPrompt.js +35 -12
- package/lib/module/license/index.js +1 -1
- package/lib/module/license/licenseModule.js +50 -35
- package/lib/module/license/tierLimits.js +13 -63
- package/lib/module/storage/devToolsStorageKeys.js +8 -1
- package/lib/module/stores/BaseEventStore.js +21 -5
- package/lib/module/stores/createToolStore.js +21 -3
- package/lib/module/stores/floatingToolStore.js +61 -0
- package/lib/module/stores/floatingToolStore.test.js +111 -0
- package/lib/module/sync/keyedArrays.js +204 -0
- package/lib/module/sync/toolActionRegistry.js +84 -2
- package/lib/module/sync/toolAttention.test.js +50 -0
- package/lib/module/sync/toolUiBridge.js +55 -0
- package/lib/module/sync/typedEdit.js +220 -0
- package/lib/module/sync/valuePath.js +330 -0
- package/lib/module/sync/valueShape.js +153 -0
- package/lib/module/ui/backgrounds/README.md +52 -0
- package/lib/module/ui/backgrounds/ToolBackground.js +4 -2
- package/lib/module/ui/backgrounds/index.js +2 -1
- package/lib/module/ui/backgrounds/registry.js +8 -0
- package/lib/module/ui/backgrounds/variants/wormhole/motion.js +44 -0
- package/lib/module/ui/backgrounds/variants/wormhole/textures.js +3 -0
- package/lib/module/ui/backgrounds/variants/wormhole.js +129 -0
- package/lib/module/ui/components/ClipboardHintBanner.js +5 -6
- package/lib/module/ui/components/CompactRow.js +94 -74
- package/lib/module/ui/components/DraggableHeader.js +16 -1
- package/lib/module/ui/components/ExpandablePopover.js +38 -6
- package/lib/module/ui/components/HeaderSearchButton.js +17 -4
- package/lib/module/ui/floating/FloatingTool.js +1003 -0
- package/lib/module/ui/floating/FloatingTool.web.js +590 -0
- package/lib/module/ui/floating/FloatingToolHost.js +29 -0
- package/lib/module/ui/floating/FloatingToolHost.web.js +25 -0
- package/lib/module/ui/floating/index.js +6 -0
- package/lib/module/ui/floating/index.web.js +6 -0
- package/lib/module/ui/floating/onboardingConstants.js +64 -0
- package/lib/module/ui/floating/onboardingConstants.web.js +27 -0
- package/lib/module/ui/gameUI/constants/gameUIColors.js +3 -1
- package/lib/module/ui/index.js +5 -1
- package/lib/module/ui/night/nightTheme.js +10 -0
- package/lib/module/ui/night/primitives.js +22 -5
- package/lib/module/ui/otto/OttoSceneView.js +64 -0
- package/lib/module/ui/otto/index.js +3 -1
- package/lib/module/ui/otto/ottoEngine.js +10 -7
- package/lib/module/ui/otto/ottoScenes.js +942 -0
- package/lib/module/utils/minimalSuperJSON.js +13 -3
- package/lib/typescript/commonjs/JsModal.d.ts +43 -2
- package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/JsModal.web.d.ts +5 -2
- package/lib/typescript/commonjs/JsModal.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/CyberpunkInput.d.ts.map +1 -1
- package/lib/typescript/commonjs/dataViewer/LiveExplorer.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/commonjs/icons/ReactQueryIcon.d.ts +1 -2
- package/lib/typescript/commonjs/icons/ReactQueryIcon.d.ts.map +1 -1
- package/lib/typescript/commonjs/icons/SentryBugIcon.d.ts +1 -2
- package/lib/typescript/commonjs/icons/SentryBugIcon.d.ts.map +1 -1
- package/lib/typescript/commonjs/icons/index.d.ts +1 -1
- package/lib/typescript/commonjs/icons/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +8 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/AccountSetup.d.ts +4 -0
- package/lib/typescript/commonjs/license/AccountSetup.d.ts.map +1 -0
- package/lib/typescript/commonjs/license/AccountSetup.web.d.ts +2 -0
- package/lib/typescript/commonjs/license/AccountSetup.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/license/FeatureGate.d.ts +3 -19
- package/lib/typescript/commonjs/license/FeatureGate.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/FreeAccountPrompt.d.ts +8 -11
- package/lib/typescript/commonjs/license/FreeAccountPrompt.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/index.d.ts +1 -1
- package/lib/typescript/commonjs/license/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/licenseModule.d.ts +18 -31
- package/lib/typescript/commonjs/license/licenseModule.d.ts.map +1 -1
- package/lib/typescript/commonjs/license/tierLimits.d.ts +9 -52
- package/lib/typescript/commonjs/license/tierLimits.d.ts.map +1 -1
- package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts +6 -0
- package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts.map +1 -1
- package/lib/typescript/commonjs/stores/BaseEventStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/stores/createToolStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/stores/floatingToolStore.d.ts +27 -0
- package/lib/typescript/commonjs/stores/floatingToolStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/stores/floatingToolStore.test.d.ts +2 -0
- package/lib/typescript/commonjs/stores/floatingToolStore.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/keyedArrays.d.ts +35 -0
- package/lib/typescript/commonjs/sync/keyedArrays.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/toolActionRegistry.d.ts +4 -32
- package/lib/typescript/commonjs/sync/toolActionRegistry.d.ts.map +1 -1
- package/lib/typescript/commonjs/sync/toolAttention.test.d.ts +2 -0
- package/lib/typescript/commonjs/sync/toolAttention.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/toolUiBridge.d.ts +25 -0
- package/lib/typescript/commonjs/sync/toolUiBridge.d.ts.map +1 -1
- package/lib/typescript/commonjs/sync/typedEdit.d.ts +70 -0
- package/lib/typescript/commonjs/sync/typedEdit.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/valuePath.d.ts +52 -0
- package/lib/typescript/commonjs/sync/valuePath.d.ts.map +1 -0
- package/lib/typescript/commonjs/sync/valueShape.d.ts +77 -0
- package/lib/typescript/commonjs/sync/valueShape.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/backgrounds/ToolBackground.d.ts +7 -1
- package/lib/typescript/commonjs/ui/backgrounds/ToolBackground.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/backgrounds/index.d.ts +2 -1
- package/lib/typescript/commonjs/ui/backgrounds/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/backgrounds/registry.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/backgrounds/types.d.ts +11 -1
- package/lib/typescript/commonjs/ui/backgrounds/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole/motion.d.ts +24 -0
- package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole/motion.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole/textures.d.ts +13 -0
- package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole/textures.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole.d.ts +3 -0
- package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/ClipboardHintBanner.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/CompactRow.d.ts +8 -1
- package/lib/typescript/commonjs/ui/components/CompactRow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/DraggableHeader.d.ts +4 -1
- package/lib/typescript/commonjs/ui/components/DraggableHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ExpandablePopover.d.ts +14 -1
- package/lib/typescript/commonjs/ui/components/ExpandablePopover.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/HeaderSearchButton.d.ts +7 -1
- package/lib/typescript/commonjs/ui/components/HeaderSearchButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/floating/FloatingTool.d.ts +79 -0
- package/lib/typescript/commonjs/ui/floating/FloatingTool.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/floating/FloatingTool.web.d.ts +64 -0
- package/lib/typescript/commonjs/ui/floating/FloatingTool.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/floating/FloatingToolHost.d.ts +3 -0
- package/lib/typescript/commonjs/ui/floating/FloatingToolHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/floating/FloatingToolHost.web.d.ts +3 -0
- package/lib/typescript/commonjs/ui/floating/FloatingToolHost.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/floating/index.d.ts +7 -0
- package/lib/typescript/commonjs/ui/floating/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/floating/index.web.d.ts +7 -0
- package/lib/typescript/commonjs/ui/floating/index.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/floating/onboardingConstants.d.ts +30 -0
- package/lib/typescript/commonjs/ui/floating/onboardingConstants.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/floating/onboardingConstants.web.d.ts +13 -0
- package/lib/typescript/commonjs/ui/floating/onboardingConstants.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/gameUI/constants/gameUIColors.d.ts +2 -0
- package/lib/typescript/commonjs/ui/gameUI/constants/gameUIColors.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts +6 -0
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/night/nightTheme.d.ts +10 -0
- package/lib/typescript/commonjs/ui/night/nightTheme.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/night/primitives.d.ts +10 -3
- package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/otto/OttoSceneView.d.ts +30 -0
- package/lib/typescript/commonjs/ui/otto/OttoSceneView.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/otto/index.d.ts +2 -0
- package/lib/typescript/commonjs/ui/otto/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts +1 -1
- package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/otto/ottoScenes.d.ts +75 -0
- package/lib/typescript/commonjs/ui/otto/ottoScenes.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/minimalSuperJSON.d.ts.map +1 -1
- package/lib/typescript/module/JsModal.d.ts +43 -2
- package/lib/typescript/module/JsModal.d.ts.map +1 -1
- package/lib/typescript/module/JsModal.web.d.ts +5 -2
- package/lib/typescript/module/JsModal.web.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/CyberpunkInput.d.ts.map +1 -1
- package/lib/typescript/module/dataViewer/LiveExplorer.d.ts.map +1 -1
- package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
- package/lib/typescript/module/icons/ReactQueryIcon.d.ts +1 -2
- package/lib/typescript/module/icons/ReactQueryIcon.d.ts.map +1 -1
- package/lib/typescript/module/icons/SentryBugIcon.d.ts +1 -2
- package/lib/typescript/module/icons/SentryBugIcon.d.ts.map +1 -1
- package/lib/typescript/module/icons/index.d.ts +1 -1
- package/lib/typescript/module/icons/index.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +8 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/license/AccountSetup.d.ts +4 -0
- package/lib/typescript/module/license/AccountSetup.d.ts.map +1 -0
- package/lib/typescript/module/license/AccountSetup.web.d.ts +2 -0
- package/lib/typescript/module/license/AccountSetup.web.d.ts.map +1 -0
- package/lib/typescript/module/license/FeatureGate.d.ts +3 -19
- package/lib/typescript/module/license/FeatureGate.d.ts.map +1 -1
- package/lib/typescript/module/license/FreeAccountPrompt.d.ts +8 -11
- package/lib/typescript/module/license/FreeAccountPrompt.d.ts.map +1 -1
- package/lib/typescript/module/license/index.d.ts +1 -1
- package/lib/typescript/module/license/index.d.ts.map +1 -1
- package/lib/typescript/module/license/licenseModule.d.ts +18 -31
- package/lib/typescript/module/license/licenseModule.d.ts.map +1 -1
- package/lib/typescript/module/license/tierLimits.d.ts +9 -52
- package/lib/typescript/module/license/tierLimits.d.ts.map +1 -1
- package/lib/typescript/module/storage/devToolsStorageKeys.d.ts +6 -0
- package/lib/typescript/module/storage/devToolsStorageKeys.d.ts.map +1 -1
- package/lib/typescript/module/stores/BaseEventStore.d.ts.map +1 -1
- package/lib/typescript/module/stores/createToolStore.d.ts.map +1 -1
- package/lib/typescript/module/stores/floatingToolStore.d.ts +27 -0
- package/lib/typescript/module/stores/floatingToolStore.d.ts.map +1 -0
- package/lib/typescript/module/stores/floatingToolStore.test.d.ts +2 -0
- package/lib/typescript/module/stores/floatingToolStore.test.d.ts.map +1 -0
- package/lib/typescript/module/sync/keyedArrays.d.ts +35 -0
- package/lib/typescript/module/sync/keyedArrays.d.ts.map +1 -0
- package/lib/typescript/module/sync/toolActionRegistry.d.ts +4 -32
- package/lib/typescript/module/sync/toolActionRegistry.d.ts.map +1 -1
- package/lib/typescript/module/sync/toolAttention.test.d.ts +2 -0
- package/lib/typescript/module/sync/toolAttention.test.d.ts.map +1 -0
- package/lib/typescript/module/sync/toolUiBridge.d.ts +25 -0
- package/lib/typescript/module/sync/toolUiBridge.d.ts.map +1 -1
- package/lib/typescript/module/sync/typedEdit.d.ts +70 -0
- package/lib/typescript/module/sync/typedEdit.d.ts.map +1 -0
- package/lib/typescript/module/sync/valuePath.d.ts +52 -0
- package/lib/typescript/module/sync/valuePath.d.ts.map +1 -0
- package/lib/typescript/module/sync/valueShape.d.ts +77 -0
- package/lib/typescript/module/sync/valueShape.d.ts.map +1 -0
- package/lib/typescript/module/ui/backgrounds/ToolBackground.d.ts +7 -1
- package/lib/typescript/module/ui/backgrounds/ToolBackground.d.ts.map +1 -1
- package/lib/typescript/module/ui/backgrounds/index.d.ts +2 -1
- package/lib/typescript/module/ui/backgrounds/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/backgrounds/registry.d.ts.map +1 -1
- package/lib/typescript/module/ui/backgrounds/types.d.ts +11 -1
- package/lib/typescript/module/ui/backgrounds/types.d.ts.map +1 -1
- package/lib/typescript/module/ui/backgrounds/variants/wormhole/motion.d.ts +24 -0
- package/lib/typescript/module/ui/backgrounds/variants/wormhole/motion.d.ts.map +1 -0
- package/lib/typescript/module/ui/backgrounds/variants/wormhole/textures.d.ts +13 -0
- package/lib/typescript/module/ui/backgrounds/variants/wormhole/textures.d.ts.map +1 -0
- package/lib/typescript/module/ui/backgrounds/variants/wormhole.d.ts +3 -0
- package/lib/typescript/module/ui/backgrounds/variants/wormhole.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/ClipboardHintBanner.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/CompactRow.d.ts +8 -1
- package/lib/typescript/module/ui/components/CompactRow.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/DraggableHeader.d.ts +4 -1
- package/lib/typescript/module/ui/components/DraggableHeader.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ExpandablePopover.d.ts +14 -1
- package/lib/typescript/module/ui/components/ExpandablePopover.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/HeaderSearchButton.d.ts +7 -1
- package/lib/typescript/module/ui/components/HeaderSearchButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/floating/FloatingTool.d.ts +79 -0
- package/lib/typescript/module/ui/floating/FloatingTool.d.ts.map +1 -0
- package/lib/typescript/module/ui/floating/FloatingTool.web.d.ts +64 -0
- package/lib/typescript/module/ui/floating/FloatingTool.web.d.ts.map +1 -0
- package/lib/typescript/module/ui/floating/FloatingToolHost.d.ts +3 -0
- package/lib/typescript/module/ui/floating/FloatingToolHost.d.ts.map +1 -0
- package/lib/typescript/module/ui/floating/FloatingToolHost.web.d.ts +3 -0
- package/lib/typescript/module/ui/floating/FloatingToolHost.web.d.ts.map +1 -0
- package/lib/typescript/module/ui/floating/index.d.ts +7 -0
- package/lib/typescript/module/ui/floating/index.d.ts.map +1 -0
- package/lib/typescript/module/ui/floating/index.web.d.ts +7 -0
- package/lib/typescript/module/ui/floating/index.web.d.ts.map +1 -0
- package/lib/typescript/module/ui/floating/onboardingConstants.d.ts +30 -0
- package/lib/typescript/module/ui/floating/onboardingConstants.d.ts.map +1 -0
- package/lib/typescript/module/ui/floating/onboardingConstants.web.d.ts +13 -0
- package/lib/typescript/module/ui/floating/onboardingConstants.web.d.ts.map +1 -0
- package/lib/typescript/module/ui/gameUI/constants/gameUIColors.d.ts +2 -0
- package/lib/typescript/module/ui/gameUI/constants/gameUIColors.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts +6 -0
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/night/nightTheme.d.ts +10 -0
- package/lib/typescript/module/ui/night/nightTheme.d.ts.map +1 -1
- package/lib/typescript/module/ui/night/primitives.d.ts +10 -3
- package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -1
- package/lib/typescript/module/ui/otto/OttoSceneView.d.ts +30 -0
- package/lib/typescript/module/ui/otto/OttoSceneView.d.ts.map +1 -0
- package/lib/typescript/module/ui/otto/index.d.ts +2 -0
- package/lib/typescript/module/ui/otto/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/otto/ottoEngine.d.ts +1 -1
- package/lib/typescript/module/ui/otto/ottoEngine.d.ts.map +1 -1
- package/lib/typescript/module/ui/otto/ottoScenes.d.ts +75 -0
- package/lib/typescript/module/ui/otto/ottoScenes.d.ts.map +1 -0
- package/lib/typescript/module/utils/minimalSuperJSON.d.ts.map +1 -1
- package/package.json +25 -5
- package/scripts/generate-wormhole-textures.cjs +261 -0
- package/scripts/test-wormhole-motion.cjs +59 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
// Generates src/ui/backgrounds/variants/wormhole/textures.ts.
|
|
2
|
+
// Usage (from packages/shared): node scripts/generate-wormhole-textures.cjs [--still scene.jpg] [--keep dir]
|
|
3
|
+
//
|
|
4
|
+
// The moving scene is a zoom, and a zoom only loops invisibly when the picture
|
|
5
|
+
// is self-similar under the handoff transform. So the cloud sheet is built by
|
|
6
|
+
// tiling ONE annulus of the real shader frame in log-polar space with the
|
|
7
|
+
// spiral symmetry sheet(K·ρ, φ+θ) = sheet(ρ, φ) (K, θ come from motion.ts).
|
|
8
|
+
// Two copies of the sheet, one K× larger and θ further round, are then the same
|
|
9
|
+
// picture, so the crossfade between them cannot be seen. The destination is
|
|
10
|
+
// cut from the same frame and drawn as a static layer above the sheets.
|
|
11
|
+
//
|
|
12
|
+
// Pipeline (all in memory, no image dependencies):
|
|
13
|
+
// 1. CPU port of apps/website vortexShader.ts renders the dark scene at u_t=4,
|
|
14
|
+
// framed so the destination sits at the centre, without the site vignette.
|
|
15
|
+
// 2. That frame is tiled into the sheet (opaque → JPEG via macOS `sips`).
|
|
16
|
+
// 3. The eye is cut with a feathered alpha (→ PNG, zlib only).
|
|
17
|
+
// 4. The reduced-motion still is kept from the existing module unless --still
|
|
18
|
+
// supplies a fresh WebGL capture (a centered 640px JPEG of the website).
|
|
19
|
+
const fs = require('node:fs'), path = require('node:path'), zlib = require('node:zlib'), os = require('node:os');
|
|
20
|
+
const { execFileSync } = require('node:child_process');
|
|
21
|
+
const ts = require('typescript');
|
|
22
|
+
const vm = require('node:vm');
|
|
23
|
+
|
|
24
|
+
const ROOT = path.join(__dirname, '..');
|
|
25
|
+
const MOTION = path.join(ROOT, 'src/ui/backgrounds/variants/wormhole/motion.ts');
|
|
26
|
+
const MODULE = path.join(ROOT, 'src/ui/backgrounds/variants/wormhole/textures.ts');
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
const flag = (name) => { const i = args.indexOf(name); return i >= 0 ? args[i + 1] : null; };
|
|
29
|
+
|
|
30
|
+
// The same numbers the animation uses — the sheet's symmetry MUST match them.
|
|
31
|
+
const motion = {};
|
|
32
|
+
vm.runInNewContext(ts.transpileModule(fs.readFileSync(MOTION, 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText, { exports: motion });
|
|
33
|
+
const K = motion.WORMHOLE_PERIOD, THETA = motion.WORMHOLE_TWIST * Math.PI / 180;
|
|
34
|
+
|
|
35
|
+
// Radii below are in STILL units: 1 = the edge of the shipped 640px still, which
|
|
36
|
+
// the plane stretches to its own radius. The source frame is rendered with a
|
|
37
|
+
// wider field (WIDE) so the whole tile annulus fits inside it.
|
|
38
|
+
const SOURCE_PX = 2560; // render size; every visible sheet period samples it at ≥ 1:1
|
|
39
|
+
const WIDE = 1.25; // still units per source-frame radius
|
|
40
|
+
const SHEET_PX = 1440; // opaque JPEG, stretched over the plane (≈ the old texel size at the shells' mean scale)
|
|
41
|
+
const CORE_PX = 384; // RGBA PNG, covers the centre half of the plane
|
|
42
|
+
const CORE_SPAN = 0.5; // still radii covered by the core image
|
|
43
|
+
const CORE_FEATHER = [0.12, 0.34]; // alpha 1→0 across these still radii
|
|
44
|
+
const BAND_INNER = 0.45; // the annulus [BAND_INNER, K·BAND_INNER] of the frame is the tile
|
|
45
|
+
const SEAM = 0.3; // fraction of a period crossfaded into the next tile
|
|
46
|
+
const JPEG_QUALITY = 88;
|
|
47
|
+
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// 1. Shader port (dark palette, u_t = 4, no pointer / ripple / copy scrim)
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
const fract = (x) => x - Math.floor(x);
|
|
52
|
+
const pmod = (x, m) => ((x % m) + m) % m;
|
|
53
|
+
const hash = (x, y) => fract(Math.sin(x * 127.1 + y * 311.7) * 43758.5453123);
|
|
54
|
+
const smooth = (a, b, x) => { const t = Math.max(0, Math.min(1, (x - a) / (b - a))); return t * t * (3 - 2 * t); };
|
|
55
|
+
const mix = (a, b, t) => a + (b - a) * t;
|
|
56
|
+
const TAU = Math.PI * 2;
|
|
57
|
+
function noise(x, y) {
|
|
58
|
+
const ix = Math.floor(x), iy = Math.floor(y); let fx = x - ix, fy = y - iy;
|
|
59
|
+
fx = fx * fx * (3 - 2 * fx); fy = fy * fy * (3 - 2 * fy);
|
|
60
|
+
return mix(mix(hash(ix, iy), hash(ix + 1, iy), fx), mix(hash(ix, iy + 1), hash(ix + 1, iy + 1), fx), fy);
|
|
61
|
+
}
|
|
62
|
+
function volumeNoise(x, y, z) {
|
|
63
|
+
const zi = Math.floor(z); let f = z - zi; f = f * f * (3 - 2 * f);
|
|
64
|
+
const a = pmod(zi, 256), b = pmod(zi + 1, 256);
|
|
65
|
+
return mix(noise(x + a * 17.1, y + a * 31.7), noise(x + b * 17.1, y + b * 31.7), f);
|
|
66
|
+
}
|
|
67
|
+
function vapor(x, y, z) {
|
|
68
|
+
let r = 0, w = 0.53;
|
|
69
|
+
for (let i = 0; i < 3; i++) { r += volumeNoise(x, y, z) * w; x = x * 2.03 + 2.1; y = y * 2.03 + 5.7; z = z * 2.03 + 9.3; w *= 0.48; }
|
|
70
|
+
return r;
|
|
71
|
+
}
|
|
72
|
+
const WALL = [0.06, 0.16, 0.48], LIGHT = [0.2, 0.62, 1.0], DEST = [1.0, 0.33, 0.1], DUST = [0.8, 0.95, 1.0], LIFT = [0.004, 0.008, 0.017];
|
|
73
|
+
const SPEED = 0.68, TWIST = 0.48, BEND = 0.32, T = 4, FOV = 1.55 * WIDE;
|
|
74
|
+
const flightCourse = (z) => [(Math.sin(z * 0.24) * 2.2 + Math.sin(z * 0.08) * 1.4) * BEND, Math.cos(z * 0.19) * 1.7 * BEND];
|
|
75
|
+
const camera = T * SPEED * 2.1;
|
|
76
|
+
const origin = flightCourse(camera);
|
|
77
|
+
const ahead = flightCourse(camera + 2.2);
|
|
78
|
+
const look = [(ahead[0] - origin[0]) / 2.2, (ahead[1] - origin[1]) / 2.2];
|
|
79
|
+
const passage = (z) => { const f = flightCourse(camera + z); return [f[0] - origin[0] - look[0] * z, f[1] - origin[1] - look[1] * z]; };
|
|
80
|
+
const roll = Math.sin(T * 0.13) * 0.055, cr = Math.cos(roll), sr = Math.sin(roll);
|
|
81
|
+
// Frame the destination at the centre: undo the roll on its p-space position.
|
|
82
|
+
const far = passage(14).map((v) => v / 14);
|
|
83
|
+
const FRAME = [0.5 - (Math.cos(-roll) * far[0] - Math.sin(-roll) * far[1]) / FOV, 0.5 - (Math.sin(-roll) * far[0] + Math.cos(-roll) * far[1]) / FOV];
|
|
84
|
+
|
|
85
|
+
function shade(uvx, uvy) {
|
|
86
|
+
let px = (uvx - FRAME[0]) * FOV, py = (uvy - FRAME[1]) * FOV;
|
|
87
|
+
[px, py] = [cr * px - sr * py, sr * px + cr * py];
|
|
88
|
+
let z = 0;
|
|
89
|
+
for (let i = 0; i < 48; i++) {
|
|
90
|
+
const pz = passage(z), qx = px * z - pz[0], qy = py * z - pz[1];
|
|
91
|
+
const a = Math.atan2(qy, qx + 1e-6);
|
|
92
|
+
const gap = 0.78 + 0.055 * Math.sin(a * 4 + (camera + z) * 0.7) - Math.hypot(qx, qy);
|
|
93
|
+
if (gap < 0.004 || z > 18) break;
|
|
94
|
+
z += Math.max(0.003, gap * 0.65 / Math.hypot(px, py, 1));
|
|
95
|
+
}
|
|
96
|
+
const pz = passage(z), wx = px * z - pz[0], wy = py * z - pz[1];
|
|
97
|
+
const angle = Math.atan2(wy, wx), textureZ = camera + z, twist = angle + textureZ * TWIST;
|
|
98
|
+
const sx = Math.cos(twist) * 2.6, sy = Math.sin(twist) * 2.6, sz = textureZ * 0.78;
|
|
99
|
+
const n = vapor(sx, sy, sz);
|
|
100
|
+
const detail = volumeNoise(sx * 3.2 + n * 1.7, sy * 3.2 + n * 1.7, sz * 3.2 + n * 1.7);
|
|
101
|
+
const depth = 1 - Math.exp(-z * 0.13), wallFade = 1 - smooth(10, 18, z);
|
|
102
|
+
const billow = smooth(0.18, 0.75, n);
|
|
103
|
+
const ridges = Math.pow(1 - Math.abs(detail * 2 - 1), 7);
|
|
104
|
+
const ribbons = Math.pow(0.5 + 0.5 * Math.sin(twist * 5 + n * 6 + textureZ * 2.6), 7);
|
|
105
|
+
const copper = smooth(2.5, 9, z), side = 0.55 + 0.45 * Math.sin(angle - 0.8 + n * 1.2);
|
|
106
|
+
const dx = px - far[0], dy = py - far[1], core = Math.hypot(dx, dy);
|
|
107
|
+
const glow = Math.exp(-core * 13) * (0.23 + 0.04 * Math.sin(T * 0.7)), haze = Math.exp(-core * 5) * 0.025;
|
|
108
|
+
const c = [0, 0, 0];
|
|
109
|
+
for (let i = 0; i < 3; i++) {
|
|
110
|
+
let v = WALL[i] * (0.2 + billow * 1.15) + LIGHT[i] * (ridges * 0.17 + ribbons * 0.4) * (0.3 + billow);
|
|
111
|
+
v = mix(v, DEST[i] * (billow * 0.55 + ribbons * 0.3), copper);
|
|
112
|
+
c[i] = v * side * (0.75 + depth * 0.55) * wallFade + DEST[i] * glow + LIGHT[i] * haze;
|
|
113
|
+
}
|
|
114
|
+
for (let layer = 0; layer < 3; layer++) {
|
|
115
|
+
const r = Math.max(core, 0.012), angular = (Math.atan2(dy, dx) / TAU + 0.5) * (85 + layer * 27);
|
|
116
|
+
const seed = hash(Math.floor(angular), layer + 5);
|
|
117
|
+
const along = fract(Math.log(r) * (2.3 + layer * 0.5) - camera * (0.75 + seed * 0.5) + seed * 13);
|
|
118
|
+
const across = (fract(angular) - 0.5) / ((0.045 + layer * 0.012) / (0.5 + r));
|
|
119
|
+
const streak = Math.exp(-across * across) * Math.exp(-along * 36) * (seed > 0.69 ? 1 : 0) * smooth(0.06, 0.25, r);
|
|
120
|
+
for (let i = 0; i < 3; i++) c[i] += mix(LIGHT[i], DUST[i], 0.6) * streak * 0.4;
|
|
121
|
+
}
|
|
122
|
+
for (let i = 0; i < 3; i++) c[i] = 1 - Math.exp(-(c[i] + LIFT[i]) * 1.3);
|
|
123
|
+
return c;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// 2–3. Tiling and the eye cut
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
function png(w, h, rgba) {
|
|
130
|
+
const crcTable = []; for (let n = 0; n < 256; n++) { let c = n; for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; crcTable[n] = c >>> 0; }
|
|
131
|
+
const crc = (buf) => { let c = 0xffffffff; for (const b of buf) c = crcTable[(c ^ b) & 0xff] ^ (c >>> 8); return (c ^ 0xffffffff) >>> 0; };
|
|
132
|
+
const chunk = (type, data) => { const t = Buffer.from(type), len = Buffer.alloc(4), sum = Buffer.alloc(4); len.writeUInt32BE(data.length); sum.writeUInt32BE(crc(Buffer.concat([t, data]))); return Buffer.concat([len, t, data, sum]); };
|
|
133
|
+
const header = Buffer.alloc(13); header.writeUInt32BE(w); header.writeUInt32BE(h, 4); header[8] = 8; header[9] = 6;
|
|
134
|
+
const rows = [];
|
|
135
|
+
for (let y = 0; y < h; y++) {
|
|
136
|
+
const row = Buffer.alloc(w * 4);
|
|
137
|
+
for (let x = 0; x < w * 4; x++) row[x] = (rgba[y * w * 4 + x] - (x >= 4 ? rgba[y * w * 4 + x - 4] : 0) + 256) % 256;
|
|
138
|
+
rows.push(Buffer.from([1]), row);
|
|
139
|
+
}
|
|
140
|
+
return Buffer.concat([Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]), chunk('IHDR', header), chunk('IDAT', zlib.deflateSync(Buffer.concat(rows), { level: 9 })), chunk('IEND', Buffer.alloc(0))]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
console.log(`rendering ${SOURCE_PX}px source frame…`);
|
|
144
|
+
let t0 = Date.now();
|
|
145
|
+
const source = new Float32Array(SOURCE_PX * SOURCE_PX * 3);
|
|
146
|
+
for (let y = 0; y < SOURCE_PX; y++) for (let x = 0; x < SOURCE_PX; x++) {
|
|
147
|
+
const c = shade((x + 0.5) / SOURCE_PX, (y + 0.5) / SOURCE_PX);
|
|
148
|
+
source.set(c, (y * SOURCE_PX + x) * 3);
|
|
149
|
+
}
|
|
150
|
+
console.log(` ${((Date.now() - t0) / 1000).toFixed(1)}s`);
|
|
151
|
+
|
|
152
|
+
// Bilinear sample at still radii (u, v).
|
|
153
|
+
function sample(u, v) {
|
|
154
|
+
u /= WIDE; v /= WIDE;
|
|
155
|
+
if (Math.max(Math.abs(u), Math.abs(v)) > 1) throw new Error(`sample outside the source frame (${u.toFixed(2)}, ${v.toFixed(2)}): raise WIDE`);
|
|
156
|
+
const x = Math.max(0, Math.min(SOURCE_PX - 1.001, (u + 1) / 2 * SOURCE_PX - 0.5)), y = Math.max(0, Math.min(SOURCE_PX - 1.001, (v + 1) / 2 * SOURCE_PX - 0.5));
|
|
157
|
+
const x0 = Math.floor(x), y0 = Math.floor(y), fx = x - x0, fy = y - y0;
|
|
158
|
+
const out = [0, 0, 0];
|
|
159
|
+
for (const [xx, yy, w] of [[x0, y0, (1 - fx) * (1 - fy)], [x0 + 1, y0, fx * (1 - fy)], [x0, y0 + 1, (1 - fx) * fy], [x0 + 1, y0 + 1, fx * fy]]) {
|
|
160
|
+
const i = (yy * SOURCE_PX + xx) * 3; out[0] += source[i] * w; out[1] += source[i + 1] * w; out[2] += source[i + 2] * w;
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
const polar = (rho, phi) => sample(rho * Math.cos(phi), rho * Math.sin(phi));
|
|
165
|
+
// One sheet sample: which period is this radius in, and where in the tile.
|
|
166
|
+
// A sheet radius is K still radii, so at the shells' mean scale (K) the sheet
|
|
167
|
+
// shows the still's features at their own size.
|
|
168
|
+
function tile(px, py) {
|
|
169
|
+
const rho = Math.max(Math.hypot(px, py) * K, 1e-9), phi = Math.atan2(py, px);
|
|
170
|
+
const u = Math.log(rho / BAND_INNER) / Math.log(K), m = Math.floor(u), f = u - m;
|
|
171
|
+
// Period m is the tile rotated m·θ further round (screen convention: positive = clockwise).
|
|
172
|
+
const c = polar(BAND_INNER * Math.pow(K, f), phi - m * THETA);
|
|
173
|
+
if (f > 1 - SEAM) {
|
|
174
|
+
const t = smooth(1 - SEAM, 1, f), d = polar(BAND_INNER * Math.pow(K, f - 1), phi - (m + 1) * THETA);
|
|
175
|
+
for (let i = 0; i < 3; i++) c[i] += (d[i] - c[i]) * t;
|
|
176
|
+
}
|
|
177
|
+
return c;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log(`tiling ${SHEET_PX}px sheet (K=${K.toFixed(4)}, θ=${motion.WORMHOLE_TWIST}°)…`);
|
|
181
|
+
t0 = Date.now();
|
|
182
|
+
const sheet = Buffer.alloc(SHEET_PX * SHEET_PX * 4);
|
|
183
|
+
for (let y = 0; y < SHEET_PX; y++) for (let x = 0; x < SHEET_PX; x++) {
|
|
184
|
+
const px = ((x + 0.5) / SHEET_PX) * 2 - 1, py = ((y + 0.5) / SHEET_PX) * 2 - 1;
|
|
185
|
+
// Periods shrink toward the centre, so supersample harder there.
|
|
186
|
+
const ss = Math.max(2, Math.min(12, Math.ceil(2 / Math.max(Math.hypot(px, py) * K, 0.02))));
|
|
187
|
+
const acc = [0, 0, 0];
|
|
188
|
+
for (let j = 0; j < ss; j++) for (let i = 0; i < ss; i++) {
|
|
189
|
+
const c = tile(px + ((i + 0.5) / ss - 0.5) * 2 / SHEET_PX, py + ((j + 0.5) / ss - 0.5) * 2 / SHEET_PX);
|
|
190
|
+
acc[0] += c[0]; acc[1] += c[1]; acc[2] += c[2];
|
|
191
|
+
}
|
|
192
|
+
const o = (y * SHEET_PX + x) * 4;
|
|
193
|
+
for (let i = 0; i < 3; i++) sheet[o + i] = Math.max(0, Math.min(255, Math.round(acc[i] / (ss * ss) * 255)));
|
|
194
|
+
sheet[o + 3] = 255;
|
|
195
|
+
}
|
|
196
|
+
console.log(` ${((Date.now() - t0) / 1000).toFixed(1)}s`);
|
|
197
|
+
|
|
198
|
+
// Self-check: the sheet drawn K× larger and θ further round must be the same
|
|
199
|
+
// picture. Compare against the 4px-neighbour difference so "similar" is
|
|
200
|
+
// relative to the sheet's own detail, not an absolute threshold.
|
|
201
|
+
{
|
|
202
|
+
const N = SHEET_PX, c = N / 2, at = (x, y) => { x = Math.round(x); y = Math.round(y); if (x < 0 || y < 0 || x >= N || y >= N) return null; const i = (y * N + x) * 4; return [sheet[i], sheet[i + 1], sheet[i + 2]]; };
|
|
203
|
+
let err = 0, base = 0, n = 0;
|
|
204
|
+
for (let y = 0; y < N; y += 5) for (let x = 0; x < N; x += 5) {
|
|
205
|
+
const dx = x - c, dy = y - c, r = Math.hypot(dx, dy); if (r > c * 0.45 || r < c * 0.08) continue;
|
|
206
|
+
const cs = Math.cos(-THETA), sn = Math.sin(-THETA);
|
|
207
|
+
const a = at(x, y), b = at((dx * cs - dy * sn) / K + c, (dx * sn + dy * cs) / K + c), d = at(x + 4, y); if (!a || !b || !d) continue;
|
|
208
|
+
for (let i = 0; i < 3; i++) { err += Math.abs(a[i] - b[i]); base += Math.abs(a[i] - d[i]); }
|
|
209
|
+
n++;
|
|
210
|
+
}
|
|
211
|
+
console.log(` symmetry residual ${(err / n / 3).toFixed(2)} vs neighbour difference ${(base / n / 3).toFixed(2)}`);
|
|
212
|
+
if (err > base) throw new Error('sheet is not self-similar under (K, θ) — the handoff would be visible');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
console.log(`cutting ${CORE_PX}px eye…`);
|
|
216
|
+
const core = Buffer.alloc(CORE_PX * CORE_PX * 4);
|
|
217
|
+
for (let y = 0; y < CORE_PX; y++) for (let x = 0; x < CORE_PX; x++) {
|
|
218
|
+
const u = (((x + 0.5) / CORE_PX) * 2 - 1) * CORE_SPAN, v = (((y + 0.5) / CORE_PX) * 2 - 1) * CORE_SPAN;
|
|
219
|
+
const ss = 3, acc = [0, 0, 0];
|
|
220
|
+
for (let j = 0; j < ss; j++) for (let i = 0; i < ss; i++) {
|
|
221
|
+
const c = sample(u + ((i + 0.5) / ss - 0.5) * 2 * CORE_SPAN / CORE_PX, v + ((j + 0.5) / ss - 0.5) * 2 * CORE_SPAN / CORE_PX);
|
|
222
|
+
acc[0] += c[0]; acc[1] += c[1]; acc[2] += c[2];
|
|
223
|
+
}
|
|
224
|
+
const o = (y * CORE_PX + x) * 4;
|
|
225
|
+
for (let i = 0; i < 3; i++) core[o + i] = Math.max(0, Math.min(255, Math.round(acc[i] / (ss * ss) * 255)));
|
|
226
|
+
core[o + 3] = Math.round(255 * (1 - smooth(CORE_FEATHER[0], CORE_FEATHER[1], Math.hypot(u, v))));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
// 4. Encode and emit
|
|
231
|
+
// ---------------------------------------------------------------------------
|
|
232
|
+
const keep = flag('--keep');
|
|
233
|
+
const work = keep ? path.resolve(keep) : fs.mkdtempSync(path.join(os.tmpdir(), 'wormhole-'));
|
|
234
|
+
fs.mkdirSync(work, { recursive: true });
|
|
235
|
+
const sheetPng = path.join(work, 'sheet.png'), sheetJpg = path.join(work, 'sheet.jpg'), corePng = path.join(work, 'core.png');
|
|
236
|
+
fs.writeFileSync(sheetPng, png(SHEET_PX, SHEET_PX, sheet));
|
|
237
|
+
fs.writeFileSync(corePng, png(CORE_PX, CORE_PX, core));
|
|
238
|
+
try {
|
|
239
|
+
execFileSync('sips', ['-s', 'format', 'jpeg', '-s', 'formatOptions', String(JPEG_QUALITY), sheetPng, '--out', sheetJpg], { stdio: 'ignore' });
|
|
240
|
+
} catch (error) {
|
|
241
|
+
throw new Error(`JPEG encoding needs macOS \`sips\` (${error.message}); the PNG is at ${sheetPng}`);
|
|
242
|
+
}
|
|
243
|
+
const stillArg = flag('--still');
|
|
244
|
+
const still = stillArg
|
|
245
|
+
? fs.readFileSync(stillArg).toString('base64')
|
|
246
|
+
: /WORMHOLE_STILL = \{ uri: "data:image\/jpeg;base64,([^"]+)"/.exec(fs.readFileSync(MODULE, 'utf8'))?.[1];
|
|
247
|
+
if (!still) throw new Error('No still: pass --still scene.jpg (a centered 640px WebGL capture of the website wormhole)');
|
|
248
|
+
const sheetB64 = fs.readFileSync(sheetJpg).toString('base64'), coreB64 = fs.readFileSync(corePng).toString('base64');
|
|
249
|
+
const module_ = '// Generated by scripts/generate-wormhole-textures.cjs — do not edit.\n'
|
|
250
|
+
+ '// Shared source objects reuse the decoded images across instances.\n'
|
|
251
|
+
+ '/** The website frame as captured (reduced motion / animation off). */\n'
|
|
252
|
+
+ `export const WORMHOLE_STILL = { uri: "data:image/jpeg;base64,${still}" };\n`
|
|
253
|
+
+ `/** Opaque cloud sheet, self-similar under scale ×${K.toFixed(4)} + rotate ${motion.WORMHOLE_TWIST}°; stretched over the plane. */\n`
|
|
254
|
+
+ `export const WORMHOLE_SHEET = { uri: "data:image/jpeg;base64,${sheetB64}" };\n`
|
|
255
|
+
+ `/** The destination, feathered; drawn static over the sheets at half the plane's size. */\n`
|
|
256
|
+
+ `export const WORMHOLE_CORE = { uri: "data:image/png;base64,${coreB64}" };\n`;
|
|
257
|
+
fs.writeFileSync(MODULE, module_);
|
|
258
|
+
const kib = (s) => Math.round(s / 1024);
|
|
259
|
+
console.log(`wrote ${path.relative(ROOT, MODULE)}: still ${kib(still.length * 0.75)} KiB, sheet ${kib(sheetB64.length * 0.75)} KiB, core ${kib(coreB64.length * 0.75)} KiB (module ${kib(module_.length)} KiB)`);
|
|
260
|
+
console.log(`decoded: sheet ${(SHEET_PX * SHEET_PX * 4 / 1048576).toFixed(1)} MiB + core ${(CORE_PX * CORE_PX * 4 / 1048576).toFixed(1)} MiB while moving; still ${(640 * 640 * 4 / 1048576).toFixed(1)} MiB otherwise`);
|
|
261
|
+
if (!keep) fs.rmSync(work, { recursive: true, force: true }); else console.log(`intermediates kept in ${work}`);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Run from packages/shared: node scripts/test-wormhole-motion.cjs
|
|
2
|
+
// Checks the keyframe math only. Whether the handoff is VISIBLE depends on the
|
|
3
|
+
// sheet texture being self-similar under (WORMHOLE_PERIOD, WORMHOLE_TWIST);
|
|
4
|
+
// generate-wormhole-textures.cjs checks that against the rendered pixels.
|
|
5
|
+
const fs = require('node:fs');
|
|
6
|
+
const vm = require('node:vm');
|
|
7
|
+
const assert = require('node:assert/strict');
|
|
8
|
+
const ts = require('typescript');
|
|
9
|
+
const e = {};
|
|
10
|
+
const source = fs.readFileSync('src/ui/backgrounds/variants/wormhole/motion.ts', 'utf8');
|
|
11
|
+
vm.runInNewContext(ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText, { exports: e });
|
|
12
|
+
const { WORMHOLE_INPUT: input, WORMHOLE_SHELLS: shells, WORMHOLE_PERIOD: K, WORMHOLE_TWIST: THETA } = e;
|
|
13
|
+
const passMs = e.WORMHOLE_CYCLE_MS / e.WORMHOLE_PASSES;
|
|
14
|
+
assert.equal(passMs, 6000);
|
|
15
|
+
assert.equal(shells.length, 2, 'reuse the existing two image layers');
|
|
16
|
+
const close = (a, b, tolerance = 1e-9) => Math.abs(a - b) < tolerance;
|
|
17
|
+
for (const shell of shells) {
|
|
18
|
+
for (const values of [shell.scale, shell.opacity, shell.rotate]) {
|
|
19
|
+
assert.equal(values.length, input.length);
|
|
20
|
+
assert.equal(values[0], values.at(-1), 'camera loop must be seamless');
|
|
21
|
+
}
|
|
22
|
+
for (let i = 1; i < input.length; i++) {
|
|
23
|
+
assert(input[i] > input[i - 1]);
|
|
24
|
+
assert(shell.scale[i] >= 1 - 1e-9 && shell.scale[i] <= K * K + 1e-9, 'the sheet covers the plane from scale 1 and a pass spans one K² zoom');
|
|
25
|
+
assert(shell.opacity[i] >= 0 && shell.opacity[i] <= 0.9200000001);
|
|
26
|
+
if (shell.scale[i] < shell.scale[i - 1]) {
|
|
27
|
+
assert.equal(shell.opacity[i - 1], 0, 'hide before reset');
|
|
28
|
+
assert.equal(shell.opacity[i], 0, 'hide during reset');
|
|
29
|
+
// The reset is itself a symmetry of the sheet: K² in scale and 2θ in
|
|
30
|
+
// rotation (the keyframe before the wrap sits one step short of both).
|
|
31
|
+
const step = shell.scale[1] / shell.scale[0], turn = parseFloat(shell.rotate[1]) - parseFloat(shell.rotate[0]);
|
|
32
|
+
assert(close(shell.scale[i - 1] / shell.scale[i] * step, K * K, 1e-6), 'reset jumps exactly two periods');
|
|
33
|
+
assert(close(parseFloat(shell.rotate[i - 1]) - parseFloat(shell.rotate[i]) + turn, 2 * THETA, 1e-6), 'reset unwinds exactly two twists');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (let i = 0; i < input.length; i++) {
|
|
38
|
+
const transmission = shells.reduce((total, shell) => total * (1 - shell.opacity[i]), 1);
|
|
39
|
+
assert(close(transmission, 0.08, 1e-10), 'handoff must not pulse its composited opacity');
|
|
40
|
+
// THE invariant that hides the handoff: whichever shell is larger is exactly
|
|
41
|
+
// the other one scaled by K and turned by θ, i.e. the same picture.
|
|
42
|
+
const [a, b] = shells[0].scale[i] < shells[1].scale[i] ? [shells[0], shells[1]] : [shells[1], shells[0]];
|
|
43
|
+
assert(close(b.scale[i] / a.scale[i], K, 1e-6), `shells must sit one period apart (index ${i})`);
|
|
44
|
+
assert(close(parseFloat(b.rotate[i]) - parseFloat(a.rotate[i]), THETA, 1e-6), `shells must sit one twist apart (index ${i})`);
|
|
45
|
+
}
|
|
46
|
+
for (const shell of shells) {
|
|
47
|
+
const ratios = [];
|
|
48
|
+
for (let i = 1; i < input.length; i++) {
|
|
49
|
+
if (shell.scale[i] > shell.scale[i - 1]) ratios.push(shell.scale[i] / shell.scale[i - 1]);
|
|
50
|
+
assert(Math.abs(shell.opacity[i] - shell.opacity[i - 1]) < 0.09, 'no abrupt opacity steps');
|
|
51
|
+
}
|
|
52
|
+
assert(Math.max(...ratios) - Math.min(...ratios) < 1e-10, 'consistent proportional forward speed');
|
|
53
|
+
}
|
|
54
|
+
const rotation = e.WORMHOLE_CAMERA_ROTATION.map(parseFloat);
|
|
55
|
+
const turnaround = (input.length - 1) / 2;
|
|
56
|
+
assert.equal(rotation[0], rotation.at(-1));
|
|
57
|
+
assert(Math.abs(rotation[1] - rotation[0]) < 0.002, 'camera eases through loop seam');
|
|
58
|
+
assert(Math.abs(rotation[turnaround + 1] - rotation[turnaround]) < 0.002, 'camera eases through turnaround');
|
|
59
|
+
console.log(`PASS: shells always one (×${K}, ${THETA}°) symmetry apart, resets are symmetries too, continuous optical density, steady forward expansion, sheet never shows an edge, smooth camera turns, same two layers.`);
|