chore: multi-stage Docker Needle build and trim MenuScene dist assets

Build MenuScene in Docker; ignore dist in context; remove bundled dist chunks;
update MenuScene index and MenuController bob defaults.

Made-with: Cursor
This commit is contained in:
pelpanagiotis
2026-04-20 07:46:34 +03:00
parent e2e5e47077
commit 3499f8257a
87 changed files with 24 additions and 45697 deletions

View File

@@ -14,9 +14,12 @@ MemoryCaptures/
Recordings/
obj/
# Host-side Node (not needed when image serves pre-built dist)
# Host-side Node (fresh install in the builder stage)
**/node_modules/
# Rebuilt inside the Docker builder; omit from context for smaller/faster uploads
Needle/*/dist/
# OS
.DS_Store
Thumbs.db

View File

@@ -13,9 +13,9 @@ namespace Needle.Typescript.GeneratedComponents
public UnityEngine.Transform[] @dishes;
public UnityEngine.Transform @webXROrigin;
[UnityEngine.Tooltip("Local-space vertical bob amplitude (meters). Set to 0 to disable.")]
public float @dishBobAmplitude = 0.05f;
public float @dishBobAmplitude = 0.004f;
[UnityEngine.Tooltip("Bob angular speed (radians per second).")]
public float @dishBobSpeed = 2.5f;
public float @dishBobSpeed = 1f;
public float @selectedDishIndex = 0f;
public void OnEnable() {}
public void onEnterXR(object @args) {}

View File

@@ -1,13 +1,26 @@
# Serves pre-built Needle/Vite output from the repo (Needle/<app>/dist).
# Build locally first: cd Needle/MenuScene && npm run build
# Optional: Needle/SampleScene && npm run build (for compose profile "sample")
# Multi-stage: Vite production build runs during `docker build` / `docker compose build` —
# no `npm run build` on the host first. The final image is nginx + freshly built `dist/`.
#
# Unity still exports into Needle/<app>/assets/ on your machine; include that folder in the
# build context when it exists (it is not listed in .dockerignore). Clones without `assets/`
# need a Unity export (or committed assets) before the image can bundle a valid scene.
ARG NEEDLE_APP=MenuScene
FROM node:22-alpine AS builder
ARG NEEDLE_APP
WORKDIR /src
COPY Needle/${NEEDLE_APP}/package.json Needle/${NEEDLE_APP}/package-lock.json ./
RUN npm ci
COPY Needle/${NEEDLE_APP}/ ./
RUN npm run build
FROM nginx:1.27-alpine
ARG NEEDLE_APP
COPY Needle/${NEEDLE_APP}/dist /usr/share/nginx/html
COPY --from=builder /src/dist /usr/share/nginx/html
COPY docker/nginx-default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

View File

@@ -1 +0,0 @@
import{t as e}from"./needle-engine@5.0.3.js";export{e as GenerateMeshBVHWorker};

View File

@@ -1 +0,0 @@
import{u as e}from"./materialx.CnHmG--Y.js";export{e as default};

View File

@@ -1 +0,0 @@
import{c as e}from"./materialx.CnHmG--Y.js";export{e as default};

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
import{l as e}from"./materialx.CnHmG--Y.js";export{e as default};

View File

@@ -1 +0,0 @@
import{n as e,r as t,t as n}from"./postprocessing.ao.BRYreHJS.js";export{e as DepthType,n as N8AOPass,t as N8AOPostPass};

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +0,0 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./register_types.C6IEiUJa.js","./needle-engine-webxr.DiiWSXeh.js","./materialx.CnHmG--Y.js","./rolldown-runtime.CYVBeYYp.js","./three@0.169.19.js","./needle-engine-ui.D3ZoIJG5.js","./gltf-progressive.BBJGcb3s.js","./three-examples@0.169.19.js","./three-mesh-ui.CgGzZ3ml.js","./needle-engine@5.0.3.js","./needle-engine.extras.B9pwA3ET.js","./needle-engine-particles.Ce6eiXqY.js","./three-quarks.DALdLWPD.js","./needle-engine.extras.dI9yZHT7.js","./postprocessing.Wy71DpiM.js","./three-mesh-bvh.B-oXEGo2.js","./needle-engine.DZYzd-GQ.js"])))=>i.map(i=>d[i]);
import{d as e}from"./materialx.CnHmG--Y.js";import{_t as t,fn as n,wi as r}from"./needle-engine-ui.D3ZoIJG5.js";import{A as i}from"./three-examples@0.169.19.js";import"./needle-engine@5.0.3.js";import{x as a}from"./needle-engine-webxr.DiiWSXeh.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})(),globalThis[`needle:dependencies:ready`]=e(()=>import(`./register_types.C6IEiUJa.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]),import.meta.url);var o=[];globalThis[`needle:codegen_files`]=o,o.push(`./assets/MenuScene.glb`),document.addEventListener(`DOMContentLoaded`,()=>{let e=document.querySelector(`needle-engine`);e&&e.getAttribute(`src`)===null&&(e.setAttribute(`hash`,`1776632959714`),e.setAttribute(`src`,JSON.stringify(o)))}),console.log(`Made with ♥ by 🌵 Needle - https://needle.tools — Version 5.0.3`);var s={"cc0_-_pizza_salami":`include/dishes/cc0_-_pizza_salami.glb`};function c(e){let t=0;return e.traverse(e=>{e.isMesh&&(t+=1)}),t}function l(e){let t=`./`.endsWith(`/`)?`./`:`.//`;return new URL(e,new URL(t,window.location.href)).href}async function u(e){let t=new i;for(let n of e.dishes){if(!n)continue;let e=s[n.name];if(!e||c(n)>0)continue;let r=l(e),i=await t.loadAsync(r);i.scene.name=`${n.name}_mesh`,n.add(i.scene)}}function d(){let e=document.querySelector(`needle-engine`);if(!e)return;let n=async()=>{try{let n=await e.getContext(),r=t(MenuController,n);r&&await u(r)}catch(e){console.warn(`[dishMeshFallback] Could not inject dish meshes:`,e)}};e.addEventListener(`loadfinished`,()=>void n())}d(),r(e=>{let t=e.scene.getComponentInChildren(a);t||(t=e.scene.addComponent(a),t.createARButton=!0,t.createVRButton=!0),t.autoPlace=!0,t.autoCenter=!0,t.arScale=1});function f(e){document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,()=>e(),{once:!0}):e()}function p(){let e=document.querySelector(`needle-engine`),r=document.querySelector(`#asset-picker-prev`),i=document.querySelector(`#asset-picker-next`),a=document.querySelector(`#asset-picker-ar`),o=document.querySelector(`#asset-picker-label`),s=document.querySelector(`#asset-picker-index`);if(!e||!r||!i||!a||!o||!s)return;let c=null,l=!1,u=!1,d=!1,p=()=>{c&&c.getDishSlotCount()>0?(o.textContent=c.getPickerLabel(),s.textContent=``):c?(o.textContent=`Menu (assign dishes in Unity)`,s.textContent=``):(o.textContent=`Menu scene`,s.textContent=``);let e=c!==null&&c.getDishSlotCount()>1;r.disabled=!e,i.disabled=!e,a.disabled=!u||d||l},m=async()=>{try{let n=await e.getContext();c=t(MenuController,n)}catch{c=null}p()};n.isARSupported().then(e=>{u=e,p()});let h=e=>{!c||c.getDishSlotCount()<=1||(e<0?c.selectPreviousDish():c.selectNextDish(),p())},g=async()=>{if(!(!u||d||l)){d=!0,p();try{let t=await e.getContext();await n.start(`immersive-ar`,void 0,t)}catch(e){console.warn(`[assetPicker] Failed to start AR session:`,e)}finally{d=!1,p()}}};r.addEventListener(`click`,()=>h(-1)),i.addEventListener(`click`,()=>h(1)),a.addEventListener(`click`,()=>void g()),e.addEventListener(`enter-ar`,()=>{l=!0,p()}),e.addEventListener(`exit-ar`,()=>{l=!1,p()}),e.addEventListener(`enter-vr`,()=>{l=!0,p()}),e.addEventListener(`exit-vr`,()=>{l=!1,p()}),e.addEventListener(`loadfinished`,()=>void m()),f(()=>{requestAnimationFrame(()=>void m())})}p(),e(()=>import(`./needle-engine.DZYzd-GQ.js`),__vite__mapDeps([16,10,2,3,4,1,5,6,7,8,11,12,13,14,9,15]),import.meta.url);

Binary file not shown.

View File

@@ -1 +0,0 @@
html{height:-webkit-fill-available}body{margin:0;padding:0}needle-engine{width:100%;height:100%;position:absolute;top:0;left:0}#asset-picker{left:0;right:0;bottom:calc(4.75rem + env(safe-area-inset-bottom,0px));z-index:600;pointer-events:auto;box-sizing:border-box;justify-content:center;padding:12px;display:flex;position:fixed}#asset-picker .asset-picker__inner{color:#f2f2f7;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background:#0f0f14d1;border-radius:12px;flex-wrap:wrap;align-items:center;gap:12px;max-width:min(100%,36rem);padding:10px 14px;font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:.95rem;display:flex;box-shadow:0 4px 24px #00000059}#asset-picker button{pointer-events:auto;touch-action:manipulation;cursor:pointer;font:inherit;color:#0f0f14;background:#e8e8ed;border:none;border-radius:8px;padding:8px 14px;font-weight:600}#asset-picker button:disabled{opacity:.45;cursor:not-allowed}#asset-picker #asset-picker-ar{color:#0a0a0c;background:#34c759}#asset-picker #asset-picker-ar:disabled{color:#ffffff80;background:#3a3a3e}#asset-picker .asset-picker__label{text-overflow:ellipsis;white-space:nowrap;text-align:center;flex:1;min-width:0;overflow:hidden}#asset-picker .asset-picker__index{opacity:.85;font-variant-numeric:tabular-nums;flex-shrink:0;font-size:.85rem}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./materialx.CnHmG--Y.js";export{o as Experimental_API,e as MaterialXEnvironment,n as MaterialXLoader,t as MaterialXMaterial,r as preloadWasm,a as ready,i as useNeedleMaterialX};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{u as e}from"./needle-engine@5.0.3.js";export{e as NeedleEngineWebComponent};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{a as e,i as t,n,r}from"./three-mesh-bvh.B-oXEGo2.js";export{e as MeshBVH,n as StaticGeometryGenerator,r as acceleratedRaycast,t as computeBoundsTree};

View File

@@ -1 +0,0 @@
import{t as e}from"./needle-engine.D6xdy26G.js";export{e as GLTFAnimationPointerExtension};

View File

@@ -1 +0,0 @@
import{$ as ee,$t as te,A as ne,At as e,B as t,Bt as n,C as r,Ct as re,D as ie,Dt as ae,E as oe,Et as i,F as a,Ft as o,G as s,Gt as c,H as l,Ht as u,I as d,It as f,J as p,Jt as m,K as h,Kt as g,L as _,Lt as v,M as y,Mt as b,N as x,Nt as S,O as C,Ot as w,P as T,Pt as E,Q as D,Qt as O,R as k,Rt as A,S as j,St as M,T as N,Tt as P,U as F,Ut as I,V as L,Vt as R,W as z,Wt as B,X as V,Xt as H,Y as U,Yt as W,Z as G,Zt as K,_ as q,_t as se,a as ce,an as le,at as J,b as ue,bt as Y,c as de,cn as fe,ct as pe,d as me,dt as he,en as ge,et as _e,f as ve,ft as ye,g as be,gt as xe,h as Se,ht as X,i as Ce,in as we,it as Te,j as Ee,jt as De,k as Oe,kt as ke,l as Ae,ln as je,lt as Z,m as Me,mt as Ne,n as Pe,nn as Fe,nt as Ie,o as Le,on as Re,ot as Q,p as ze,pt as Be,q as Ve,qt as He,r as Ue,rn as We,rt as Ge,s as Ke,sn as qe,st as Je,t as Ye,tn as Xe,tt as Ze,u as Qe,ut as $e,v as et,vt as tt,w as nt,wt as rt,x as $,xt as it,y as at,yt as ot,z as st,zt as ct}from"./postprocessing.Wy71DpiM.js";export{Ye as ASCIIEffect,Pe as ASCIITexture,Ue as AdaptiveLuminanceMaterial,Ce as AdaptiveLuminancePass,ce as BlendFunction,Le as BlendMode,Ke as BloomEffect,Q as BlurPass,Q as KawaseBlurPass,de as BokehEffect,Ae as BokehMaterial,Qe as BoxBlurMaterial,me as BoxBlurPass,ve as BrightnessContrastEffect,ze as ChromaticAberrationEffect,Me as CircleOfConfusionMaterial,Se as ClearMaskPass,be as ClearPass,q as ColorAverageEffect,et as ColorChannel,at as ColorDepthEffect,_ as ColorEdgesMaterial,_ as EdgeDetectionMaterial,J as ConvolutionMaterial,J as KawaseBlurMaterial,ue as CopyMaterial,$ as CopyPass,$ as SavePass,j as DepthComparisonMaterial,r as DepthCopyMaterial,nt as DepthCopyMode,N as DepthCopyPass,N as DepthSavePass,oe as DepthDownsamplingMaterial,ie as DepthDownsamplingPass,C as DepthEffect,Oe as DepthMaskMaterial,ne as DepthOfFieldEffect,Ee as DepthPass,y as DepthPickingPass,x as DepthTestStrategy,T as Disposable,a as DotScreenEffect,d as DownsamplingMaterial,k as EdgeDetectionMode,st as Effect,t as EffectAttribute,L as EffectComposer,l as EffectMaterial,F as EffectPass,z as EffectShaderData,s as EffectShaderSection,s as Section,h as FXAAEffect,Ve as GammaCorrectionEffect,p as GaussKernel,U as GaussianBlurMaterial,V as GaussianBlurPass,G as GlitchEffect,D as GlitchMode,ee as GodRaysEffect,_e as GodRaysMaterial,Ze as GridEffect,Ie as HueSaturationEffect,Ge as ImmutableTimer,Te as Initializable,Je as KernelSize,pe as LUT1DEffect,Z as LUT3DEffect,Z as LUTEffect,$e as LUT3dlLoader,he as LUTCubeLoader,ye as LUTOperation,Be as LambdaPass,Ne as LensDistortionEffect,X as LookupTexture,X as LookupTexture3D,xe as LuminanceMaterial,se as LuminancePass,tt as MaskFunction,ot as MaskMaterial,Y as MaskPass,it as MipmapBlurPass,M as NoiseEffect,re as NoiseTexture,rt as NormalPass,i as OutlineEdgesMaterial,i as OutlineMaterial,P as OutlineEffect,ae as OverrideMaterialManager,w as Pass,ke as PixelationEffect,e as PredicationMode,De as RawImageData,b as RealisticBokehEffect,S as RenderPass,E as Resizable,o as Resizer,o as Resolution,f as SMAAAreaImageData,v as SMAAEffect,A as SMAAImageGenerator,ct as SMAAImageLoader,n as SMAAPreset,R as SMAASearchImageData,u as SMAAWeightsMaterial,I as SSAOEffect,B as SSAOMaterial,c as ScanlineEffect,g as Selection,He as SelectiveBloomEffect,m as SepiaEffect,W as ShaderPass,H as ShockWaveEffect,K as TetrahedralUpscaler,O as TextureEffect,te as TiltShiftBlurMaterial,ge as TiltShiftBlurPass,Xe as TiltShiftEffect,Fe as Timer,We as ToneMappingEffect,we as ToneMappingMode,le as UpsamplingMaterial,Re as VignetteEffect,qe as VignetteTechnique,fe as WebGLExtension,je as version};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,41 +0,0 @@
import{Ar as e,Kn as t,_n as n,fn as r,kr as i}from"./three@0.169.19.js";import{$i as a,Xi as o,ct as s,eo as c,ot as l}from"./needle-engine-ui.D3ZoIJG5.js";import"./needle-engine@5.0.3.js";import{m as u}from"./needle-engine-webxr.DiiWSXeh.js";import{m as d,t as f}from"./needle-engine.extras.dI9yZHT7.js";var p=class extends l{raycaster=new t;touchPos=new i;plane=new n(new e(0,1,0),0);initialPinchDistance=0;initialScale=new e;isScaling=!1;onEnable(){let e=this.context.renderer.domElement;e.addEventListener(`touchstart`,this.onTouchStart),e.addEventListener(`touchmove`,this.onTouchMove),e.addEventListener(`touchend`,this.onTouchEnd)}onDisable(){let e=this.context.renderer.domElement;e.removeEventListener(`touchstart`,this.onTouchStart),e.removeEventListener(`touchmove`,this.onTouchMove),e.removeEventListener(`touchend`,this.onTouchEnd)}onTouchStart=e=>{if(e.touches.length===2){this.isScaling=!0;let t=e.touches[0],n=e.touches[1];this.initialPinchDistance=Math.hypot(n.clientX-t.clientX,n.clientY-t.clientY),this.initialScale.copy(this.gameObject.scale)}};onTouchMove=t=>{if(t.preventDefault(),this.isScaling&&t.touches.length===2){let e=t.touches[0],n=t.touches[1],r=Math.hypot(n.clientX-e.clientX,n.clientY-e.clientY)/this.initialPinchDistance,i=this.initialScale.clone().multiplyScalar(r);this.gameObject.scale.copy(i)}else if(t.touches.length===1&&!this.isScaling){let n=t.touches[0],r=this.context.renderer.domElement.getBoundingClientRect();this.touchPos.set((n.clientX-r.left)/r.width*2-1,-((n.clientY-r.top)/r.height)*2+1),this.raycaster.setFromCamera(this.touchPos,this.context.mainCamera);let i=new e;this.raycaster.ray.intersectPlane(this.plane,i)&&this.gameObject.position.copy(i)}};onTouchEnd=e=>{e.touches.length<2&&(this.isScaling=!1)}};function m(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var h=new WeakMap,g=class extends l{isMobile=!1;isDesktop=!1;isXR=!1;dishName=``;dishes=[];webXROrigin;dishBobAmplitude=.05;dishBobSpeed=2.5;usdzExporter;arSessionBobPaused=!1;selectedDishIndex=0;onEnable(){if(this.dishName=new URLSearchParams(window.location.search).get(`dishName`)??``,this.webXROrigin&&(this.usdzExporter=this.webXROrigin.getComponent(u)??void 0),this.dishName){let e=!1;this.dishes.forEach((t,n)=>{t&&t.name===this.dishName&&(this.selectedDishIndex=n,e=!0)}),this.dishes.forEach(t=>{if(!t)return;let n=e&&t.name===this.dishName;n||this.restoreDishBaseY(t),s.setActive(t,n)}),e||this.ensureOnlySelectedDishVisible()}else this.ensureOnlySelectedDishVisible();this.updateUSDZExporterTarget(),this.checkForDeviceType().then(()=>{this.isMobile?console.log(`[MenuController] isMobile`):this.isDesktop?this.setupDesktopControls():this.isXR}),this.setupMobileControls(),this.disableDoubleTapZoom()}onEnterXR(e){e.xr.mode===`immersive-ar`&&(this.arSessionBobPaused=!0,this.snapActiveDishToBaseY())}onLeaveXR(e){this.arSessionBobPaused=!1}update(){if(this.arSessionBobPaused||this.dishBobAmplitude<=0||this.getValidDishIndices().length===0)return;let e=this.dishes[this.selectedDishIndex];if(!e)return;let t=h.get(e);t===void 0&&(t=e.position.y,h.set(e,t));let n=this.context.time.time;e.position.y=t+Math.sin(n*this.dishBobSpeed)*this.dishBobAmplitude}async checkForDeviceType(){await this.isXRDevice()?this.isXR=!0:(console.log(`DeviceUtilities.isMobileDevice()`,c.isMobileDevice()),this.isMobile=c.isMobileDevice(),this.isMobile||(this.isDesktop=c.isDesktop()))}async isXRDevice(){if(navigator.xr)try{return await navigator.xr.isSessionSupported(`immersive-vr`)}catch{return console.log(`XR check error!`),!1}return!1}setupMobileControls(){typeof document<`u`&&document.querySelector(`#asset-picker`)||this.createMenuMobileControls()}setupDesktopControls(){}createMenuMobileControls(){let e=document.createElement(`div`);e.id=`menuControlsZone`,e.style.cssText=`
position: absolute;
display: flex;
justify-content: space-between;
bottom: 10%;
left: 10%;
right: 10%;
height: 150px;
`,document.body.appendChild(e);let t=document.createElement(`button`);t.id=`previousButton`,t.style.cssText=`
height: 100px;
width: 100px;
background-color: #ffffff;
color: #111111;
border: none;
border-radius: 50px;
box-shadow: 0 8px 24px rgba(0,0,0,0.25);
display: flex;
align-items: center;
justify-content: center;
touch-action: manipulation;
`,t.setAttribute(`aria-label`,`Previous`),t.innerHTML=`
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
`,t.onclick=this.selectPreviousDish.bind(this);let n=document.createElement(`button`);n.id=`nextButton`,n.style.cssText=`
height: 100px;
width: 100px;
background-color: #ffffff;
color: #111111;
border: none;
border-radius: 50px;
box-shadow: 0 8px 24px rgba(0,0,0,0.25);
display: flex;
align-items: center;
justify-content: center;
touch-action: manipulation;
`,n.setAttribute(`aria-label`,`Next`),n.innerHTML=`
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 6L15 12L9 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
`,n.onclick=this.selectNextDish.bind(this),this.dishName&&(t.disabled=!0,t.style.display=`none`,n.disabled=!0,n.style.display=`none`),e.appendChild(t),e.appendChild(n)}disableDoubleTapZoom(){let e=0;document.addEventListener(`touchend`,t=>{let n=Date.now();n-e<=300&&t.preventDefault(),e=n},{passive:!1})}getValidDishIndices(){return this.dishes.map((e,t)=>e==null?-1:t).filter(e=>e>=0)}ensureOnlySelectedDishVisible(){let e=this.getValidDishIndices();if(e.length===0)return;let t=this.selectedDishIndex;e.indexOf(t)<0&&(t=e[0],this.selectedDishIndex=t),e.forEach(e=>{let t=e===this.selectedDishIndex,n=this.dishes[e];t||this.restoreDishBaseY(n),s.setActive(this.dishes[e],t)})}restoreDishBaseY(e){if(!e)return;let t=h.get(e);t!==void 0&&(e.position.y=t)}snapActiveDishToBaseY(){this.restoreDishBaseY(this.dishes[this.selectedDishIndex])}getDishSlotCount(){return this.getValidDishIndices().length}getPickerLabel(){let e=this.getValidDishIndices();if(e.length===0)return`Menu`;let t=Math.max(0,e.indexOf(this.selectedDishIndex)),n=this.dishes[this.selectedDishIndex]?.name?.trim();return n?`${n} (${t+1}/${e.length})`:`Dish ${t+1} / ${e.length}`}selectPreviousDish(){let e=this.getValidDishIndices();if(e.length===0)return;let t=e.indexOf(this.selectedDishIndex);t<0&&(t=0),this.restoreDishBaseY(this.dishes[e[t]]),s.setActive(this.dishes[e[t]],!1),t=(t-1+e.length)%e.length,this.selectedDishIndex=e[t],s.setActive(this.dishes[this.selectedDishIndex],!0),this.updateUSDZExporterTarget()}selectNextDish(){let e=this.getValidDishIndices();if(e.length===0)return;let t=e.indexOf(this.selectedDishIndex);t<0&&(t=0),this.restoreDishBaseY(this.dishes[e[t]]),s.setActive(this.dishes[e[t]],!1),t=(t+1)%e.length,this.selectedDishIndex=e[t],s.setActive(this.dishes[this.selectedDishIndex],!0),this.updateUSDZExporterTarget()}updateUSDZExporterTarget(){let e=this.dishes[this.selectedDishIndex];this.usdzExporter&&e&&(this.usdzExporter.objectToExport=e)}getUrlParameter(e){return new URLSearchParams(window.location.search).get(e)}};m([o(r)],g.prototype,`dishes`,void 0),m([o(r)],g.prototype,`webXROrigin`,void 0),m([o()],g.prototype,`dishBobAmplitude`,void 0),m([o()],g.prototype,`dishBobSpeed`,void 0);var _=class extends l{volume;start(){if(!this.volume){console.warn(`No PostProcessVolume assigned`);return}this.volume.addEffect(new d({intensity:3,luminanceThreshold:.2}))}};m([o(f)],_.prototype,`volume`,void 0);function v(){a.add(`ARObjectController`,p),a.add(`MenuController`,g),a.add(`PostProcessingVolumeController`,_)}v();export{v as registerTypes};

View File

@@ -1 +0,0 @@
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));export{s as n,l as r,o as t};

View File

@@ -1 +0,0 @@
import{S as e,at as t,mn as n}from"./three@0.169.19.js";var r=class{constructor(){this.isPass=!0,this.enabled=!0,this.needsSwap=!0,this.clear=!1,this.renderToScreen=!1}setSize(){}render(){console.error(`THREE.Pass: .render() must be implemented in derived pass.`)}dispose(){}};new n(-1,1,1,-1,0,1),new class extends e{constructor(){super(),this.setAttribute(`position`,new t([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute(`uv`,new t([0,2,0,0,2,0],2))}};export{r as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -20,14 +20,13 @@
<body>
<script type="module" src="./src/generated/gen.js"></script>
<script type="module" src="./src/main.ts"></script>
<needle-engine>
<needle-engine camera-controls="false">
<div id="asset-picker" class="ar desktop">
<div class="asset-picker__inner">
<button type="button" id="asset-picker-prev" aria-label="Previous model">Previous</button>
<span id="asset-picker-label" class="asset-picker__label"></span>
<span id="asset-picker-index" class="asset-picker__index" aria-live="polite"></span>
<button type="button" id="asset-picker-next" aria-label="Next model">Next</button>
<button type="button" id="asset-picker-ar" aria-label="Start augmented reality">View in AR</button>
</div>
</div>
</needle-engine>