lunchboxjs 0.1.4015 → 0.1.4016
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/dist/lunchboxjs.js +41 -7
- package/dist/lunchboxjs.min.js +1 -1
- package/dist/lunchboxjs.module.js +41 -7
- package/package.json +1 -1
- package/src/components/LunchboxWrapper/LunchboxWrapper.ts +5 -0
- package/src/components/LunchboxWrapper/prepCanvas.ts +2 -2
- package/src/components/catalogue.ts +1 -1
- package/src/core/instantiateThreeObject/processProps.ts +23 -6
- package/src/core/interaction/input.ts +1 -1
- package/src/core/interaction/setupAutoRaycaster.ts +12 -2
- package/src/core/update.ts +29 -3
- package/src/types.ts +3 -0
package/dist/lunchboxjs.js
CHANGED
|
@@ -119,6 +119,7 @@
|
|
|
119
119
|
shadow: [Boolean, Object],
|
|
120
120
|
transparent: Boolean,
|
|
121
121
|
zoom: Number,
|
|
122
|
+
updateSource: Object,
|
|
122
123
|
},
|
|
123
124
|
setup(props, context) {
|
|
124
125
|
const canvas = vue.ref();
|
|
@@ -298,12 +299,14 @@
|
|
|
298
299
|
camera: camera.instance,
|
|
299
300
|
renderer: renderer.instance,
|
|
300
301
|
scene: scene.instance,
|
|
302
|
+
updateSource: props.updateSource,
|
|
301
303
|
});
|
|
302
304
|
});
|
|
303
305
|
// UNMOUNT
|
|
304
306
|
// ====================
|
|
305
307
|
vue.onBeforeUnmount(() => {
|
|
306
308
|
cancelUpdate();
|
|
309
|
+
cancelUpdateSource();
|
|
307
310
|
});
|
|
308
311
|
// RENDER FUNCTION
|
|
309
312
|
// ====================
|
|
@@ -649,6 +652,7 @@
|
|
|
649
652
|
let mouseUpListener;
|
|
650
653
|
const mousePos = vue.ref({ x: Infinity, y: Infinity });
|
|
651
654
|
let autoRaycasterEventsInitialized = false;
|
|
655
|
+
let frameID$1;
|
|
652
656
|
const setupAutoRaycaster = (node) => {
|
|
653
657
|
const instance = node.instance;
|
|
654
658
|
if (!instance)
|
|
@@ -681,8 +685,14 @@
|
|
|
681
685
|
renderer.instance.domElement.addEventListener('mousedown', mouseDownListener);
|
|
682
686
|
renderer.instance.domElement.addEventListener('mouseup', mouseUpListener);
|
|
683
687
|
// TODO: add touch events
|
|
684
|
-
//
|
|
685
|
-
|
|
688
|
+
// process mouse events asynchronously, whenever the mouse state changes
|
|
689
|
+
vue.watch(() => [inputActive.value, mousePos.value.x, mousePos.value.y], () => {
|
|
690
|
+
if (frameID$1)
|
|
691
|
+
cancelAnimationFrame(frameID$1);
|
|
692
|
+
frameID$1 = requestAnimationFrame(() => {
|
|
693
|
+
autoRaycasterBeforeRender();
|
|
694
|
+
});
|
|
695
|
+
});
|
|
686
696
|
// mark complete
|
|
687
697
|
autoRaycasterEventsInitialized = true;
|
|
688
698
|
// cancel setup watcher
|
|
@@ -1011,7 +1021,7 @@
|
|
|
1011
1021
|
};
|
|
1012
1022
|
|
|
1013
1023
|
/** Process props into either themselves or the $attached value */
|
|
1014
|
-
function processProp({ node, prop }) {
|
|
1024
|
+
function processProp({ node, prop, }) {
|
|
1015
1025
|
// return $attachedArray value if needed
|
|
1016
1026
|
if (typeof prop === 'string' && prop.startsWith('$attachedArray')) {
|
|
1017
1027
|
return node.attachedArray[prop.replace('$attachedArray.', '')];
|
|
@@ -1023,10 +1033,12 @@
|
|
|
1023
1033
|
// otherwise, return plain value
|
|
1024
1034
|
return prop;
|
|
1025
1035
|
}
|
|
1026
|
-
function processPropAsArray({ node, prop }) {
|
|
1036
|
+
function processPropAsArray({ node, prop, }) {
|
|
1027
1037
|
const isAttachedArray = typeof prop === 'string' && prop.startsWith('$attachedArray');
|
|
1028
1038
|
const output = processProp({ node, prop });
|
|
1029
|
-
return Array.isArray(output) && isAttachedArray
|
|
1039
|
+
return Array.isArray(output) && isAttachedArray
|
|
1040
|
+
? output
|
|
1041
|
+
: [output];
|
|
1030
1042
|
}
|
|
1031
1043
|
|
|
1032
1044
|
function instantiateThreeObject(node) {
|
|
@@ -1325,16 +1337,34 @@
|
|
|
1325
1337
|
};
|
|
1326
1338
|
|
|
1327
1339
|
let frameID;
|
|
1340
|
+
let watchStopHandle;
|
|
1328
1341
|
const beforeRender = [];
|
|
1329
1342
|
const afterRender = [];
|
|
1330
|
-
const
|
|
1331
|
-
|
|
1343
|
+
const requestUpdate = (opts) => {
|
|
1344
|
+
cancelUpdate();
|
|
1332
1345
|
frameID = requestAnimationFrame(() => update({
|
|
1333
1346
|
app: opts.app,
|
|
1334
1347
|
renderer: ensureRenderer.value?.instance,
|
|
1335
1348
|
scene: ensuredScene.value.instance,
|
|
1336
1349
|
camera: ensuredCamera.value?.instance,
|
|
1350
|
+
updateSource: opts.updateSource,
|
|
1337
1351
|
}));
|
|
1352
|
+
};
|
|
1353
|
+
const update = (opts) => {
|
|
1354
|
+
if (opts.updateSource) {
|
|
1355
|
+
if (!watchStopHandle) {
|
|
1356
|
+
// request next frame only when state changes
|
|
1357
|
+
watchStopHandle = vue.watch(opts.updateSource, () => {
|
|
1358
|
+
requestUpdate(opts);
|
|
1359
|
+
}, {
|
|
1360
|
+
deep: true,
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
else {
|
|
1365
|
+
// request next frame on a continuous loop
|
|
1366
|
+
requestUpdate(opts);
|
|
1367
|
+
}
|
|
1338
1368
|
// prep options
|
|
1339
1369
|
const { app, renderer, scene, camera } = opts;
|
|
1340
1370
|
// BEFORE RENDER
|
|
@@ -1397,6 +1427,10 @@
|
|
|
1397
1427
|
if (frameID)
|
|
1398
1428
|
cancelAnimationFrame(frameID);
|
|
1399
1429
|
};
|
|
1430
|
+
const cancelUpdateSource = () => {
|
|
1431
|
+
if (watchStopHandle)
|
|
1432
|
+
watchStopHandle();
|
|
1433
|
+
};
|
|
1400
1434
|
|
|
1401
1435
|
/** Update a single prop on a given node. */
|
|
1402
1436
|
function updateObjectProp({ node, key, value, }) {
|
package/dist/lunchboxjs.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue"),require("three"),require("lodash")):"function"==typeof define&&define.amd?define(["exports","vue","three","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LunchboxRenderer={},e.vue,e.three,e.lodash)}(this,(function(e,t,n,r){"use strict";function o(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var a=o(n);const s=[],i=(e,n)=>{const r=W.value?.instance,o=I.value.instance,a=D.value;if(!r?.domElement||!o||!a)return;const s=(e=e??window.innerWidth)/(n=n??window.innerHeight);if("perspectivecamera"===a.type?.toLowerCase()){const e=a.instance;e.aspect=s,e.updateProjectionMatrix()}else if("orthographiccamera"===a.type?.toLowerCase()){const t=a.instance,r=n/e;t.top=10*r,t.bottom=10*-r,t.right=10,t.left=-10,t.updateProjectionMatrix()}else console.log("TODO: non-ortho or perspective camera");r.setSize(e,n),o&&a.instance&&r.render(t.toRaw(o),t.toRaw(a.instance))},c=e=>({position:e,top:0,right:0,bottom:0,left:0,width:"100%",height:"100%"}),d={name:"Lunchbox",props:{background:String,cameraArgs:Array,cameraLook:Array,cameraLookAt:Array,cameraPosition:Array,dpr:Number,ortho:Boolean,orthographic:Boolean,r3f:Boolean,rendererArguments:Object,rendererProperties:Object,shadow:[Boolean,Object],transparent:Boolean,zoom:Number},setup(e,n){const o=t.ref(),s=t.ref(!0),d=t.ref(e.dpr??-1),u=t.ref();let l,p,m;return e.r3f&&a?.ColorManagement&&(a.ColorManagement.legacyMode=!1),t.onMounted((()=>{if(!o.value)throw new Error("missing canvas");if(l=N(["WebGLRenderer"]),l)s.value=!1,U.value=!0;else{const t={alpha:e.transparent,antialias:!0,canvas:o.value.domElement,powerPreference:e.r3f?"high-performance":"default",...e.rendererArguments??{}};W.value=K({type:"WebGLRenderer",uuid:F,props:{args:[t]}}),U.value=!0;const n=W;e.r3f&&n.value.instance&&(n.value.instance.outputEncoding=a.sRGBEncoding,n.value.instance.toneMapping=a.ACESFilmicToneMapping);const s={shadow:e.shadow};n.value.instance&&s?.shadow&&(n.value.instance.shadowMap.enabled=!0,"object"==typeof s.shadow&&(n.value.instance.shadowMap.type=s.shadow.type)),e.rendererProperties&&Object.keys(e.rendererProperties).forEach((t=>{r.set(n.value,t,e.rendererProperties[t])})),l=n.value}if(p=N(["PerspectiveCamera","OrthographicCamera"]),p?S.value=!0:(e.ortho||e.orthographic?D.value=K({props:{args:e.cameraArgs??[]},type:"OrthographicCamera",uuid:j}):D.value=K({props:{args:e.cameraArgs??[e.r3f?75:45,.5625,1,1e3]},type:"PerspectiveCamera",uuid:j}),S.value=!0,p=D.value),!p.instance)throw new Error("Error creating camera.");if(p&&e.cameraPosition&&p.instance.position.set(...e.cameraPosition),p&&(e.cameraLookAt||e.cameraLook)){const t=e.cameraLookAt||e.cameraLook;p.instance.lookAt(...t)}if(p&&void 0!==e.zoom&&(p.instance.zoom=e.zoom),m=I.value,m&&m.instance&&e.background&&(m.instance.background=new a.Color(e.background)),-1===d.value&&(d.value=window.devicePixelRatio),!l?.instance)throw new Error("missing renderer");l.instance.setPixelRatio(d.value),he.dpr.value=d.value,((e,t,n)=>{const r=e.value?.domElement;if(!r)throw new Error("missing container");i();const o=new ResizeObserver((([e])=>{i()}));r&&o.observe(r),n((()=>{t&&o.unobserve(t)}))})(u,l.instance.domElement,t.onBeforeUnmount);const n=t.getCurrentInstance().appContext.app;for(let e of te)e({app:n,camera:p.instance,renderer:l.instance,scene:m.instance});ae({app:n,camera:p.instance,renderer:l.instance,scene:m.instance})})),t.onBeforeUnmount((()=>{ie()})),()=>[n.slots.default?.()??null,t.h("div",{style:c("absolute"),ref:u},[s.value?t.h("canvas",{style:c("fixed"),class:"lunchbox-canvas",ref:o}):null])]}},u={},l=["canvas","div","LunchboxWrapper"],p={...["mesh","instancedMesh","scene","sprite","object3D","instancedBufferGeometry","bufferGeometry","boxBufferGeometry","circleBufferGeometry","coneBufferGeometry","cylinderBufferGeometry","dodecahedronBufferGeometry","extrudeBufferGeometry","icosahedronBufferGeometry","latheBufferGeometry","octahedronBufferGeometry","parametricBufferGeometry","planeBufferGeometry","polyhedronBufferGeometry","ringBufferGeometry","shapeBufferGeometry","sphereBufferGeometry","tetrahedronBufferGeometry","textBufferGeometry","torusBufferGeometry","torusKnotBufferGeometry","tubeBufferGeometry","wireframeGeometry","parametricGeometry","tetrahedronGeometry","octahedronGeometry","icosahedronGeometry","dodecahedronGeometry","polyhedronGeometry","tubeGeometry","torusKnotGeometry","torusGeometry","sphereGeometry","ringGeometry","planeGeometry","latheGeometry","shapeGeometry","extrudeGeometry","edgesGeometry","coneGeometry","cylinderGeometry","circleGeometry","boxGeometry","material","shadowMaterial","spriteMaterial","rawShaderMaterial","shaderMaterial","pointsMaterial","meshPhysicalMaterial","meshStandardMaterial","meshPhongMaterial","meshToonMaterial","meshNormalMaterial","meshLambertMaterial","meshDepthMaterial","meshDistanceMaterial","meshBasicMaterial","meshMatcapMaterial","lineDashedMaterial","lineBasicMaterial","light","spotLightShadow","spotLight","pointLight","rectAreaLight","hemisphereLight","directionalLightShadow","directionalLight","ambientLight","lightShadow","ambientLightProbe","hemisphereLightProbe","lightProbe","texture","videoTexture","dataTexture","dataTexture3D","compressedTexture","cubeTexture","canvasTexture","depthTexture","textureLoader","group","catmullRomCurve3","points","cameraHelper","camera","perspectiveCamera","orthographicCamera","cubeCamera","arrayCamera","webGLRenderer"].map((e=>t.defineComponent({inheritAttrs:!1,name:e,setup:(n,r)=>()=>t.h(e,r.attrs,r.slots?.default?.()||[])}))).reduce(((e,t)=>(e[t.name]=t,e)),{}),Lunchbox:d};const m=e=>e?.$el&&e?.$el?.hasOwnProperty?.("instance"),h=e=>{if("domMeta"===e?.metaType)return!0;const t="string"==typeof e?e:e?.type;return l.includes(t??"")},f=e=>"standardMeta"===e?.metaType,y=e=>e.isLunchboxRootNode,v=[],g=t.ref(!1);function b({node:e,key:n,value:r}){var o;if(e.eventListeners[n]||(e.eventListeners[n]=[]),e.eventListenerRemoveFunctions[n]||(e.eventListenerRemoveFunctions[n]=[]),e.eventListeners[n].push(r),x.includes(n)&&(z.value,e.instance&&!v.includes(e)&&(o=e,v.push(o),e.eventListenerRemoveFunctions[n].push((()=>(e=>{const t=v.indexOf(e);-1!==t&&v.splice(t,1)})(e))))),"onClick"===n||"onPointerDown"===n||"onPointerUp"===n){const r=t.watch((()=>g.value),(t=>{const r=L.map((e=>e.element)).findIndex((t=>t.instance&&t.instance.uuid===e.instance?.uuid));-1!==r&&((!t||"onClick"!==n&&"onPointerDown"!==n)&&(t||"onPointerUp"!==n)||e.eventListeners[n].forEach((e=>{e({intersection:L[r].intersection})})))}));e.eventListenerRemoveFunctions[n].push(r)}return e}const x=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"];let R,w,A;const C=t.ref({x:1/0,y:1/0});let E=!1;let L=[];const P=()=>{const e=z.value?.instance,t=D.value?.instance;if(!e||!t)return;e.setFromCamera(he.mousePos.value,t);const n=e.intersectObjects(v.map((e=>e.instance)));let r=[],o=[],a=[];r=L.map((e=>e.intersection)),n?.forEach((e=>{if(-1===L.findIndex((t=>t.intersection.object===e.object))){const t=v.find((t=>t.instance?.uuid===e.object.uuid));t&&o.push({element:t,intersection:e})}else{const t=v.find((t=>t.instance?.uuid===e.object.uuid));t&&a.push({element:t,intersection:e})}const t=r.findIndex((t=>t.object.uuid===e.object.uuid));-1!==t&&r.splice(t,1)}));const s=r.map((e=>({element:v.find((t=>t.instance?.uuid===e.object.uuid)),intersection:e})));o.forEach((({element:e,intersection:t})=>{M({element:e,eventKeys:["onPointerEnter"],intersection:t})})),a.forEach((({element:e,intersection:t})=>{M({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),s.forEach((({element:e,intersection:t})=>{M({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),L=[].concat(o,a)},M=({element:e,eventKeys:t,intersection:n})=>{e&&t.forEach((t=>{e.eventListeners[t]&&e.eventListeners[t].forEach((e=>{e({intersection:n})}))}))};function B(t={}){return e.lunchboxTree||(e.lunchboxTree=new J.RendererRootNode(t)),e.lunchboxTree}function N(e){Array.isArray(e)||(e=[e]);for(let t of e)if(T[t])return T[t];for(let n of e){const e=G[n]||s.find((e=>e.type?.toLowerCase()===n.toLowerCase()));if(!(t=e,"RendererNode"!==t?.minidomType||!1!==e.props["is-default"]&&!1!=!e.props.isDefault))return null;if(e){const t=e;return G[n]=t,t}}var t;return null}e.lunchboxTree=void 0;const G=t.reactive({}),T=t.reactive({});function O(e,n,r={},o=null){Array.isArray(e)||(e=[e]);for(let t of e)G[t]||(G[t]=null),T[t]||(T[t]=null);return t.computed({get(){const t=N(e);if(t)return t;const a=B(),s=K({type:e[0],uuid:n,props:r});return a.addChild(s),G[e[0]]=s,o&&o(s),s},set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);T[n]=e}})}const j="FALLBACK_CAMERA",k=O(["PerspectiveCamera","OrthographicCamera"],j,{args:[45,.5625,1,1e3]}),S=t.ref(!1),D=t.computed({get:()=>S.value?k.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);T[n]=e}}),F="FALLBACK_RENDERER",$=O(["WebGLRenderer"],F,{}),U=t.ref(!1),W=t.computed({get:()=>U.value?$.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);T[n]=e}}),I=O("Scene","FALLBACK_SCENE"),z=O("Raycaster","AUTO_RAYCASTER",{},(e=>(e=>{if(!e.instance)return;let n=null;n=t.watch((()=>W.value),(e=>{e?.instance&&(E||(R=t=>{const n=(e.instance.domElement.width??1)/he.dpr.value,r=(e.instance.domElement.height??1)/he.dpr.value;C.value.x=t.offsetX/n*2-1,C.value.y=-t.offsetY/r*2+1},w=()=>g.value=!0,A=()=>g.value=!1,e.instance.domElement.addEventListener("mousemove",R),e.instance.domElement.addEventListener("mousedown",w),e.instance.domElement.addEventListener("mouseup",A),se(P),E=!0),n&&n())}),{immediate:!0})})(e)));function K(e={},t={}){const n={attached:e.attached??[],attachedArray:e.attachedArray??{},instance:e.instance??null},r=new J.RendererStandardNode({...e,...n,metaType:"standardMeta"});return!r.type||y(r)||r.instance||(r.instance=function(e){if(!e.type)return null;const t=e.type[0].toUpperCase()+e.type.slice(1),n=u[e.type]||a[t];if(!n)throw`${t} is not part of the THREE namespace! Did you forget to extend? import {extend} from 'lunchbox'; extend({app, YourComponent, ...})`;const r=(e.props.args??[]).map((t=>function({node:e,prop:t}){const n="string"==typeof t&&t.startsWith("$attachedArray"),r=function({node:e,prop:t}){if("string"==typeof t&&t.startsWith("$attachedArray"))return e.attachedArray[t.replace("$attachedArray.","")];if("string"==typeof t&&t.startsWith("$attached"))return e.attached[t.replace("$attached.","")];return t}({node:e,prop:t});return Array.isArray(r)&&n?r:[r]}({node:e,prop:t})));let o=[];r.forEach((e=>{o=o.concat(e)}));return new n(...o)}({...r,props:{...r.props,...t}})),"scene"===r.type?.toLowerCase()?I.value=r:r.type?.toLowerCase().endsWith("camera")&&(D.value=r),r}const _=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}});var V,q=new Uint8Array(16);function H(){if(!V&&!(V="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return V(q)}var Y=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function X(e){return"string"==typeof e&&Y.test(e)}for(var J,Q=[],Z=0;Z<256;++Z)Q.push((Z+256).toString(16).substr(1));function ee(e,t,n){var r=(e=e||{}).random||(e.rng||H)();if(r[6]=15&r[6]|64,r[8]=63&r[8]|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=r[o];return t}return function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=(Q[e[t+0]]+Q[e[t+1]]+Q[e[t+2]]+Q[e[t+3]]+"-"+Q[e[t+4]]+Q[e[t+5]]+"-"+Q[e[t+6]]+Q[e[t+7]]+"-"+Q[e[t+8]]+Q[e[t+9]]+"-"+Q[e[t+10]]+Q[e[t+11]]+Q[e[t+12]]+Q[e[t+13]]+Q[e[t+14]]+Q[e[t+15]]).toLowerCase();if(!X(n))throw TypeError("Stringified UUID is invalid");return n}(r)}!function(e){e.BaseNode=class{constructor(e={},t){this.parentNode=e?.parentNode??t??null,this.minidomType="MinidomBaseNode",this.uuid=e?.uuid??ee(),s.push(this)}uuid;parentNode;get nextSibling(){if(!this.parentNode)return null;const e=this.parentNode.children.findIndex((e=>e.uuid===this.uuid));return-1!==e&&e<this.parentNode.children.length-1?this.parentNode.children[e+1]:null}insertBefore(e,t){e.removeAsChildFromAnyParents(),e.parentNode=this;const n=this.children.findIndex((e=>e.uuid===t?.uuid));-1!==n?this.children.splice(n,0,e):this.children.push(e)}removeChild(e){const t=this.children.findIndex((t=>t?.uuid===e?.uuid));-1!==t&&this.children.splice(t,1)}children=[];addChild(e){return e&&(e.removeAsChildFromAnyParents(),e.parentNode=this,this.insertBefore(e,null)),this}getPath(){const e=[];let t=this;for(;t;)e.unshift(t),t=t.parentNode;return e}drop(){this.parentNode=null,this.removeAsChildFromAnyParents()}walk(e){const t=[this,...this.children],n=[];let r=!0;for(;t.length&&r;){const o=t.shift();if(o){if(n.includes(o))continue;n.push(o),t.push(...o.children.filter((e=>!n.includes(e)))),r=e(o)}else r=!1}}minidomType;removeAsChildFromAnyParents(){s.forEach((e=>e.removeChild(this)))}};class t extends e.BaseNode{constructor(e={},t){super(e,t),this.minidomType="RendererNode",this.eventListeners={},this.eventListenerRemoveFunctions={},this.name=e.name??"",this.metaType=e.metaType??"standardMeta",this.props=e.props??[],this.type=e.type??""}eventListeners;eventListenerRemoveFunctions;name;metaType;props;type;drop(){super.drop(),Object.keys(this.eventListenerRemoveFunctions).forEach((e=>{this.eventListenerRemoveFunctions[e].forEach((e=>e()))}))}}e.RendererBaseNode=t;class n extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement;isLunchboxRootNode=!0}e.RendererRootNode=n;class r extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererCommentNode=r;class o extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement}e.RendererDomNode=o;class a extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererTextNode=a;class i extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.attached=e.attached??[],this.attachedArray=e.attachedArray??{},this.instance=e.instance??null}attached;attachedArray;instance}e.RendererStandardNode=i}(J||(J={}));(new J.RendererRootNode).minidomType="RootNode";const te=[];let ne;const re=[],oe=[],ae=e=>{ne=requestAnimationFrame((()=>ae({app:e.app,renderer:W.value?.instance,scene:I.value.instance,camera:D.value?.instance})));const{app:n,renderer:r,scene:o,camera:a}=e;re.forEach((t=>{t&&t(e)})),r&&o&&a&&(n.customRender?n.customRender(e):r.render(t.toRaw(o),t.toRaw(a))),oe.forEach((t=>{t&&t(e)}))},se=(e,t=1/0)=>{t===1/0?re.push(e):re.splice(t,0,e)},ie=()=>{ne&&cancelAnimationFrame(ne)};const ce={x:"position.x",y:"position.y",z:"position.z"},de=["","parameters"],ue=["args","attach","attachArray","is.default","isDefault","key","onAdded","ref","src"],le=["geometry","material"];function pe(e,t,n,r){const o=r??e.instance,a=t.instance;e.props.attach===n&&(t.attached={[n]:o,...t.attached||{}},a[n]=r??e.instance),e.props.attachArray===n&&(t.attachedArray[e.props.attachArray]||(t.attachedArray[e.props.attachArray]=[]),t.attachedArray[e.props.attachArray].push(o),a[n]=[a[n]])}const me={createElement:(e,t,n,r)=>{const o={type:e};r&&(o.props=r);if(h(e)){const e=function(e={}){const t={domElement:document.createElement(e.type??"")};return new J.RendererDomNode({...t,...e,metaType:"domMeta"})}(o);return e}const a=K(o);return le.forEach((t=>{e.toLowerCase().endsWith(t)&&(a.props.attach=t)})),a},createText:e=>function(e={}){const t={text:e.text??""};return new J.RendererTextNode({...e,...t,metaType:"textMeta"})}({text:e}),createComment:e=>function(e={}){const t={text:e.text??""};return new J.RendererCommentNode({...t,...e,metaType:"commentMeta"})}({text:e}),insert:(e,t,n)=>{let r=t??B();if(r.insertBefore(e,n),"commentMeta"!==e.metaType&&"textMeta"!==e.metaType&&(h(e)&&(h(t)||y(t))&&t.domElement.appendChild(e.domElement),f(e))){let n=r.metaType;if("textMeta"===n||"commentMeta"===n){const e=r.getPath();for(let t=e.length-1;t>=0;t--)if("textMeta"!==e[t].metaType&&"commentMeta"!==e[t].metaType){r=e[t];break}}if("standardMeta"===e.metaType&&"scene"!==e.type&&y(r)){const t=I.value;t.instance&&e&&t.addChild(e),e.instance&&e.instance.isObject3D&&t.instance&&t!==e&&t.instance.add(e.instance)}else f(e)&&e.instance?.isObject3D&&f(r)&&r.instance?.isObject3D&&r.instance?.add?.(e.instance);if(e?.props?.attach&&f(t)&&t?.instance){e.type?.toLowerCase().endsWith("loader")&&e.props.src&&(e.props.attach||e.props.attachArray)?function(e,t){const n=e.instance;if(t.attached=t.attached||{},t.attachedArray=t.attachedArray||{},!e.props.attach)return;if("textureloader"===e.type?.toLowerCase()){const r=n.load(e.props.src);pe(e,t,e.props.attach,r)}else n.load(e.props.src,(n=>{pe(e,t,e.props.attach,n)}),null,(e=>{throw new Error(e)}))}(e,t):pe(e,t,e.props.attach)}e.props?.onAdded&&e.props.onAdded({instance:e.instance})}},nextSibling(e){const t=e.nextSibling;return t||null},parentNode(e){const t=e.parentNode;return t||null},patchProp(e,t,n,o){h(e)?"style"===t?Object.keys(o).forEach((t=>{e.domElement.style[t]=o[t]})):e.domElement.setAttribute(t,o):y(e)||t.startsWith("$")||function({node:e,key:t,value:n}){if((e=>["onClick","onContextMenu","onDoubleClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove","onWheel"].includes(e))(t))return b({node:e,key:t,value:n});const o=t.replace(/-/g,"."),a=ce[o]||o;if(ue.includes(t)||ue.includes(a))return e;if(!f(e))return e;if("string"==typeof n&&n.startsWith("$attached")){const t=n.replace("$attached.","");n=r.get(e.attached,t,null)}const s=e.instance;if(!s)return e;let i;for(let e=0;e<de.length&&!i;e++){const t=[de[e],a].filter(Boolean).join(".");i=i=r.get(s,t)}if(i&&r.isNumber(n)&&i.setScalar)i.setScalar(n);else if(i&&i.set){const e=Array.isArray(n)?n:[n];s[a].set(...e)}else"function"==typeof i?i.bind(e.instance)(...n):void 0!==r.get(s,a,void 0)?r.set(s,a,""===n||n):console.log(`No property ${a} found on ${s}`);const c=s?.texture?.type||s?.type;if("string"==typeof c){const e=c.toLowerCase();switch(!0){case e.includes("material"):s.needsUpdate=!0;break;case e.includes("camera")&&s.updateProjectionMatrix:s.updateProjectionMatrix()}}}({node:e,key:t,value:o})},remove:e=>{if(!e)return;const t=Object.keys(T),n=[];e.walk((e=>(n.push(e),!0))),n.forEach((e=>{const n=t.find((t=>T[t]?.uuid===e.uuid));if(n&&(T[n]=null),f(e)){e.instance?.removeFromParent?.();const t="scene"!==e.type&&e.instance?.dispose;t&&t.bind(e.instance)(),e.instance=null}e.drop();const r=s.findIndex((t=>t.uuid===e.uuid));-1!==r&&s.splice(r,1)}))},setElementText(){},setText(){}},he={dpr:t.ref(1),inputActive:g,mousePos:C},fe=t.computed((()=>D.value?.instance??null));const ye=t.computed((()=>W.value?.instance??null));const ve=t.computed((()=>I.value.instance));let ge=null,be=null;e.camera=fe,e.clearCustomRender=()=>{ge?ge.clearCustomRender():be=null},e.createApp=e=>{ge=t.createRenderer(me).createApp(e),Object.keys(p).forEach((e=>{ge?.component(e,p[e])}));const{mount:n}=ge;return ge.mount=(e,...t)=>{const r=B({domElement:"string"==typeof e?document.querySelector(e):e,isLunchboxRootNode:!0,name:"root",metaType:"rootMeta",type:"root",uuid:"LUNCHBOX_ROOT"});ge.rootNode=r;return n(r,...t)},ge.extend=e=>((({app:e,...t})=>{Object.keys(t).forEach((n=>{e.component(n,_(n)),u[n]=t[n]}))})({app:ge,...e}),ge),ge.setCustomRender=e=>{ge.customRender=e},be&&(ge.setCustomRender(be),be=null),ge.clearCustomRender=()=>{ge.customRender=null},ge},e.find=function(e){return e=t.isRef(e)?e.value:e,f(e)?e?.instance:m(e)?e?.$el?.instance:t.isVNode(e)?e.el?.instance:null},e.globals=he,e.offAfterRender=e=>{if(isFinite(e))oe.splice(e,1);else{const t=oe.findIndex((t=>t==e));oe.splice(t,1)}},e.offBeforeRender=e=>{if(isFinite(e))re.splice(e,1);else{const t=re.findIndex((t=>t==e));re.splice(t,1)}},e.onAfterRender=(e,t=1/0)=>{t===1/0?oe.push(e):oe.splice(t,0,e)},e.onBeforeRender=se,e.onStart=(e,t=1/0)=>{t===1/0?te.push(e):te.splice(t,0,e)},e.renderer=ye,e.scene=ve,e.setCustomRender=e=>{ge?ge.setCustomRender(e):be=e},e.useCamera=function(e){return t.watch(fe,(t=>{t&&e(t)}),{immediate:!0})},e.useRenderer=function(e){return t.watch(ye,(t=>{t&&e(t)}),{immediate:!0})},e.useScene=function(e){return t.watch(ve,(t=>{t&&e(t)}),{immediate:!0})},Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue"),require("three"),require("lodash")):"function"==typeof define&&define.amd?define(["exports","vue","three","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LunchboxRenderer={},e.vue,e.three,e.lodash)}(this,(function(e,t,n,r){"use strict";function o(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var a=o(n);const s=[],i=(e,n)=>{const r=I.value?.instance,o=z.value.instance,a=D.value;if(!r?.domElement||!o||!a)return;const s=(e=e??window.innerWidth)/(n=n??window.innerHeight);if("perspectivecamera"===a.type?.toLowerCase()){const e=a.instance;e.aspect=s,e.updateProjectionMatrix()}else if("orthographiccamera"===a.type?.toLowerCase()){const t=a.instance,r=n/e;t.top=10*r,t.bottom=10*-r,t.right=10,t.left=-10,t.updateProjectionMatrix()}else console.log("TODO: non-ortho or perspective camera");r.setSize(e,n),o&&a.instance&&r.render(t.toRaw(o),t.toRaw(a.instance))},c=e=>({position:e,top:0,right:0,bottom:0,left:0,width:"100%",height:"100%"}),u={name:"Lunchbox",props:{background:String,cameraArgs:Array,cameraLook:Array,cameraLookAt:Array,cameraPosition:Array,dpr:Number,ortho:Boolean,orthographic:Boolean,r3f:Boolean,rendererArguments:Object,rendererProperties:Object,shadow:[Boolean,Object],transparent:Boolean,zoom:Number,updateSource:Object},setup(e,n){const o=t.ref(),s=t.ref(!0),u=t.ref(e.dpr??-1),d=t.ref();let l,p,m;return e.r3f&&a?.ColorManagement&&(a.ColorManagement.legacyMode=!1),t.onMounted((()=>{if(!o.value)throw new Error("missing canvas");if(l=G(["WebGLRenderer"]),l)s.value=!1,W.value=!0;else{const t={alpha:e.transparent,antialias:!0,canvas:o.value.domElement,powerPreference:e.r3f?"high-performance":"default",...e.rendererArguments??{}};I.value=_({type:"WebGLRenderer",uuid:$,props:{args:[t]}}),W.value=!0;const n=I;e.r3f&&n.value.instance&&(n.value.instance.outputEncoding=a.sRGBEncoding,n.value.instance.toneMapping=a.ACESFilmicToneMapping);const s={shadow:e.shadow};n.value.instance&&s?.shadow&&(n.value.instance.shadowMap.enabled=!0,"object"==typeof s.shadow&&(n.value.instance.shadowMap.type=s.shadow.type)),e.rendererProperties&&Object.keys(e.rendererProperties).forEach((t=>{r.set(n.value,t,e.rendererProperties[t])})),l=n.value}if(p=G(["PerspectiveCamera","OrthographicCamera"]),p?F.value=!0:(e.ortho||e.orthographic?D.value=_({props:{args:e.cameraArgs??[]},type:"OrthographicCamera",uuid:k}):D.value=_({props:{args:e.cameraArgs??[e.r3f?75:45,.5625,1,1e3]},type:"PerspectiveCamera",uuid:k}),F.value=!0,p=D.value),!p.instance)throw new Error("Error creating camera.");if(p&&e.cameraPosition&&p.instance.position.set(...e.cameraPosition),p&&(e.cameraLookAt||e.cameraLook)){const t=e.cameraLookAt||e.cameraLook;p.instance.lookAt(...t)}if(p&&void 0!==e.zoom&&(p.instance.zoom=e.zoom),m=z.value,m&&m.instance&&e.background&&(m.instance.background=new a.Color(e.background)),-1===u.value&&(u.value=window.devicePixelRatio),!l?.instance)throw new Error("missing renderer");l.instance.setPixelRatio(u.value),ve.dpr.value=u.value,((e,t,n)=>{const r=e.value?.domElement;if(!r)throw new Error("missing container");i();const o=new ResizeObserver((([e])=>{i()}));r&&o.observe(r),n((()=>{t&&o.unobserve(t)}))})(d,l.instance.domElement,t.onBeforeUnmount);const n=t.getCurrentInstance().appContext.app;for(let e of ne)e({app:n,camera:p.instance,renderer:l.instance,scene:m.instance});ce({app:n,camera:p.instance,renderer:l.instance,scene:m.instance,updateSource:e.updateSource})})),t.onBeforeUnmount((()=>{ue(),de()})),()=>[n.slots.default?.()??null,t.h("div",{style:c("absolute"),ref:d},[s.value?t.h("canvas",{style:c("fixed"),class:"lunchbox-canvas",ref:o}):null])]}},d={},l=["canvas","div","LunchboxWrapper"],p={...["mesh","instancedMesh","scene","sprite","object3D","instancedBufferGeometry","bufferGeometry","boxBufferGeometry","circleBufferGeometry","coneBufferGeometry","cylinderBufferGeometry","dodecahedronBufferGeometry","extrudeBufferGeometry","icosahedronBufferGeometry","latheBufferGeometry","octahedronBufferGeometry","parametricBufferGeometry","planeBufferGeometry","polyhedronBufferGeometry","ringBufferGeometry","shapeBufferGeometry","sphereBufferGeometry","tetrahedronBufferGeometry","textBufferGeometry","torusBufferGeometry","torusKnotBufferGeometry","tubeBufferGeometry","wireframeGeometry","parametricGeometry","tetrahedronGeometry","octahedronGeometry","icosahedronGeometry","dodecahedronGeometry","polyhedronGeometry","tubeGeometry","torusKnotGeometry","torusGeometry","sphereGeometry","ringGeometry","planeGeometry","latheGeometry","shapeGeometry","extrudeGeometry","edgesGeometry","coneGeometry","cylinderGeometry","circleGeometry","boxGeometry","material","shadowMaterial","spriteMaterial","rawShaderMaterial","shaderMaterial","pointsMaterial","meshPhysicalMaterial","meshStandardMaterial","meshPhongMaterial","meshToonMaterial","meshNormalMaterial","meshLambertMaterial","meshDepthMaterial","meshDistanceMaterial","meshBasicMaterial","meshMatcapMaterial","lineDashedMaterial","lineBasicMaterial","light","spotLightShadow","spotLight","pointLight","rectAreaLight","hemisphereLight","directionalLightShadow","directionalLight","ambientLight","lightShadow","ambientLightProbe","hemisphereLightProbe","lightProbe","texture","videoTexture","dataTexture","dataTexture3D","compressedTexture","cubeTexture","canvasTexture","depthTexture","textureLoader","group","catmullRomCurve3","points","cameraHelper","camera","perspectiveCamera","orthographicCamera","cubeCamera","arrayCamera","webGLRenderer"].map((e=>t.defineComponent({inheritAttrs:!1,name:e,setup:(n,r)=>()=>t.h(e,r.attrs,r.slots?.default?.()||[])}))).reduce(((e,t)=>(e[t.name]=t,e)),{}),Lunchbox:u};const m=e=>e?.$el&&e?.$el?.hasOwnProperty?.("instance"),h=e=>{if("domMeta"===e?.metaType)return!0;const t="string"==typeof e?e:e?.type;return l.includes(t??"")},f=e=>"standardMeta"===e?.metaType,y=e=>e.isLunchboxRootNode,v=[],g=t.ref(!1);function b({node:e,key:n,value:r}){var o;if(e.eventListeners[n]||(e.eventListeners[n]=[]),e.eventListenerRemoveFunctions[n]||(e.eventListenerRemoveFunctions[n]=[]),e.eventListeners[n].push(r),x.includes(n)&&(K.value,e.instance&&!v.includes(e)&&(o=e,v.push(o),e.eventListenerRemoveFunctions[n].push((()=>(e=>{const t=v.indexOf(e);-1!==t&&v.splice(t,1)})(e))))),"onClick"===n||"onPointerDown"===n||"onPointerUp"===n){const r=t.watch((()=>g.value),(t=>{const r=P.map((e=>e.element)).findIndex((t=>t.instance&&t.instance.uuid===e.instance?.uuid));-1!==r&&((!t||"onClick"!==n&&"onPointerDown"!==n)&&(t||"onPointerUp"!==n)||e.eventListeners[n].forEach((e=>{e({intersection:P[r].intersection})})))}));e.eventListenerRemoveFunctions[n].push(r)}return e}const x=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"];let w,R,A;const C=t.ref({x:1/0,y:1/0});let E,L=!1;let P=[];const M=()=>{const e=K.value?.instance,t=D.value?.instance;if(!e||!t)return;e.setFromCamera(ve.mousePos.value,t);const n=e.intersectObjects(v.map((e=>e.instance)));let r=[],o=[],a=[];r=P.map((e=>e.intersection)),n?.forEach((e=>{if(-1===P.findIndex((t=>t.intersection.object===e.object))){const t=v.find((t=>t.instance?.uuid===e.object.uuid));t&&o.push({element:t,intersection:e})}else{const t=v.find((t=>t.instance?.uuid===e.object.uuid));t&&a.push({element:t,intersection:e})}const t=r.findIndex((t=>t.object.uuid===e.object.uuid));-1!==t&&r.splice(t,1)}));const s=r.map((e=>({element:v.find((t=>t.instance?.uuid===e.object.uuid)),intersection:e})));o.forEach((({element:e,intersection:t})=>{B({element:e,eventKeys:["onPointerEnter"],intersection:t})})),a.forEach((({element:e,intersection:t})=>{B({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),s.forEach((({element:e,intersection:t})=>{B({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),P=[].concat(o,a)},B=({element:e,eventKeys:t,intersection:n})=>{e&&t.forEach((t=>{e.eventListeners[t]&&e.eventListeners[t].forEach((e=>{e({intersection:n})}))}))};function N(t={}){return e.lunchboxTree||(e.lunchboxTree=new Q.RendererRootNode(t)),e.lunchboxTree}function G(e){Array.isArray(e)||(e=[e]);for(let t of e)if(O[t])return O[t];for(let n of e){const e=T[n]||s.find((e=>e.type?.toLowerCase()===n.toLowerCase()));if(!(t=e,"RendererNode"!==t?.minidomType||!1!==e.props["is-default"]&&!1!=!e.props.isDefault))return null;if(e){const t=e;return T[n]=t,t}}var t;return null}e.lunchboxTree=void 0;const T=t.reactive({}),O=t.reactive({});function j(e,n,r={},o=null){Array.isArray(e)||(e=[e]);for(let t of e)T[t]||(T[t]=null),O[t]||(O[t]=null);return t.computed({get(){const t=G(e);if(t)return t;const a=N(),s=_({type:e[0],uuid:n,props:r});return a.addChild(s),T[e[0]]=s,o&&o(s),s},set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);O[n]=e}})}const k="FALLBACK_CAMERA",S=j(["PerspectiveCamera","OrthographicCamera"],k,{args:[45,.5625,1,1e3]}),F=t.ref(!1),D=t.computed({get:()=>F.value?S.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);O[n]=e}}),$="FALLBACK_RENDERER",U=j(["WebGLRenderer"],$,{}),W=t.ref(!1),I=t.computed({get:()=>W.value?U.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);O[n]=e}}),z=j("Scene","FALLBACK_SCENE"),K=j("Raycaster","AUTO_RAYCASTER",{},(e=>(e=>{if(!e.instance)return;let n=null;n=t.watch((()=>I.value),(e=>{e?.instance&&(L||(w=t=>{const n=(e.instance.domElement.width??1)/ve.dpr.value,r=(e.instance.domElement.height??1)/ve.dpr.value;C.value.x=t.offsetX/n*2-1,C.value.y=-t.offsetY/r*2+1},R=()=>g.value=!0,A=()=>g.value=!1,e.instance.domElement.addEventListener("mousemove",w),e.instance.domElement.addEventListener("mousedown",R),e.instance.domElement.addEventListener("mouseup",A),t.watch((()=>[g.value,C.value.x,C.value.y]),(()=>{E&&cancelAnimationFrame(E),E=requestAnimationFrame((()=>{M()}))})),L=!0),n&&n())}),{immediate:!0})})(e)));function _(e={},t={}){const n={attached:e.attached??[],attachedArray:e.attachedArray??{},instance:e.instance??null},r=new Q.RendererStandardNode({...e,...n,metaType:"standardMeta"});return!r.type||y(r)||r.instance||(r.instance=function(e){if(!e.type)return null;const t=e.type[0].toUpperCase()+e.type.slice(1),n=d[e.type]||a[t];if(!n)throw`${t} is not part of the THREE namespace! Did you forget to extend? import {extend} from 'lunchbox'; extend({app, YourComponent, ...})`;const r=(e.props.args??[]).map((t=>function({node:e,prop:t}){const n="string"==typeof t&&t.startsWith("$attachedArray"),r=function({node:e,prop:t}){if("string"==typeof t&&t.startsWith("$attachedArray"))return e.attachedArray[t.replace("$attachedArray.","")];if("string"==typeof t&&t.startsWith("$attached"))return e.attached[t.replace("$attached.","")];return t}({node:e,prop:t});return Array.isArray(r)&&n?r:[r]}({node:e,prop:t})));let o=[];r.forEach((e=>{o=o.concat(e)}));return new n(...o)}({...r,props:{...r.props,...t}})),"scene"===r.type?.toLowerCase()?z.value=r:r.type?.toLowerCase().endsWith("camera")&&(D.value=r),r}const q=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}});var V,H=new Uint8Array(16);function Y(){if(!V&&!(V="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return V(H)}var X=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function J(e){return"string"==typeof e&&X.test(e)}for(var Q,Z=[],ee=0;ee<256;++ee)Z.push((ee+256).toString(16).substr(1));function te(e,t,n){var r=(e=e||{}).random||(e.rng||Y)();if(r[6]=15&r[6]|64,r[8]=63&r[8]|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=r[o];return t}return function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=(Z[e[t+0]]+Z[e[t+1]]+Z[e[t+2]]+Z[e[t+3]]+"-"+Z[e[t+4]]+Z[e[t+5]]+"-"+Z[e[t+6]]+Z[e[t+7]]+"-"+Z[e[t+8]]+Z[e[t+9]]+"-"+Z[e[t+10]]+Z[e[t+11]]+Z[e[t+12]]+Z[e[t+13]]+Z[e[t+14]]+Z[e[t+15]]).toLowerCase();if(!J(n))throw TypeError("Stringified UUID is invalid");return n}(r)}!function(e){e.BaseNode=class{constructor(e={},t){this.parentNode=e?.parentNode??t??null,this.minidomType="MinidomBaseNode",this.uuid=e?.uuid??te(),s.push(this)}uuid;parentNode;get nextSibling(){if(!this.parentNode)return null;const e=this.parentNode.children.findIndex((e=>e.uuid===this.uuid));return-1!==e&&e<this.parentNode.children.length-1?this.parentNode.children[e+1]:null}insertBefore(e,t){e.removeAsChildFromAnyParents(),e.parentNode=this;const n=this.children.findIndex((e=>e.uuid===t?.uuid));-1!==n?this.children.splice(n,0,e):this.children.push(e)}removeChild(e){const t=this.children.findIndex((t=>t?.uuid===e?.uuid));-1!==t&&this.children.splice(t,1)}children=[];addChild(e){return e&&(e.removeAsChildFromAnyParents(),e.parentNode=this,this.insertBefore(e,null)),this}getPath(){const e=[];let t=this;for(;t;)e.unshift(t),t=t.parentNode;return e}drop(){this.parentNode=null,this.removeAsChildFromAnyParents()}walk(e){const t=[this,...this.children],n=[];let r=!0;for(;t.length&&r;){const o=t.shift();if(o){if(n.includes(o))continue;n.push(o),t.push(...o.children.filter((e=>!n.includes(e)))),r=e(o)}else r=!1}}minidomType;removeAsChildFromAnyParents(){s.forEach((e=>e.removeChild(this)))}};class t extends e.BaseNode{constructor(e={},t){super(e,t),this.minidomType="RendererNode",this.eventListeners={},this.eventListenerRemoveFunctions={},this.name=e.name??"",this.metaType=e.metaType??"standardMeta",this.props=e.props??[],this.type=e.type??""}eventListeners;eventListenerRemoveFunctions;name;metaType;props;type;drop(){super.drop(),Object.keys(this.eventListenerRemoveFunctions).forEach((e=>{this.eventListenerRemoveFunctions[e].forEach((e=>e()))}))}}e.RendererBaseNode=t;class n extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement;isLunchboxRootNode=!0}e.RendererRootNode=n;class r extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererCommentNode=r;class o extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement}e.RendererDomNode=o;class a extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererTextNode=a;class i extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.attached=e.attached??[],this.attachedArray=e.attachedArray??{},this.instance=e.instance??null}attached;attachedArray;instance}e.RendererStandardNode=i}(Q||(Q={}));(new Q.RendererRootNode).minidomType="RootNode";const ne=[];let re,oe;const ae=[],se=[],ie=e=>{ue(),re=requestAnimationFrame((()=>ce({app:e.app,renderer:I.value?.instance,scene:z.value.instance,camera:D.value?.instance,updateSource:e.updateSource})))},ce=e=>{e.updateSource?oe||(oe=t.watch(e.updateSource,(()=>{ie(e)}),{deep:!0})):ie(e);const{app:n,renderer:r,scene:o,camera:a}=e;ae.forEach((t=>{t&&t(e)})),r&&o&&a&&(n.customRender?n.customRender(e):r.render(t.toRaw(o),t.toRaw(a))),se.forEach((t=>{t&&t(e)}))},ue=()=>{re&&cancelAnimationFrame(re)},de=()=>{oe&&oe()};const le={x:"position.x",y:"position.y",z:"position.z"},pe=["","parameters"],me=["args","attach","attachArray","is.default","isDefault","key","onAdded","ref","src"],he=["geometry","material"];function fe(e,t,n,r){const o=r??e.instance,a=t.instance;e.props.attach===n&&(t.attached={[n]:o,...t.attached||{}},a[n]=r??e.instance),e.props.attachArray===n&&(t.attachedArray[e.props.attachArray]||(t.attachedArray[e.props.attachArray]=[]),t.attachedArray[e.props.attachArray].push(o),a[n]=[a[n]])}const ye={createElement:(e,t,n,r)=>{const o={type:e};r&&(o.props=r);if(h(e)){const e=function(e={}){const t={domElement:document.createElement(e.type??"")};return new Q.RendererDomNode({...t,...e,metaType:"domMeta"})}(o);return e}const a=_(o);return he.forEach((t=>{e.toLowerCase().endsWith(t)&&(a.props.attach=t)})),a},createText:e=>function(e={}){const t={text:e.text??""};return new Q.RendererTextNode({...e,...t,metaType:"textMeta"})}({text:e}),createComment:e=>function(e={}){const t={text:e.text??""};return new Q.RendererCommentNode({...t,...e,metaType:"commentMeta"})}({text:e}),insert:(e,t,n)=>{let r=t??N();if(r.insertBefore(e,n),"commentMeta"!==e.metaType&&"textMeta"!==e.metaType&&(h(e)&&(h(t)||y(t))&&t.domElement.appendChild(e.domElement),f(e))){let n=r.metaType;if("textMeta"===n||"commentMeta"===n){const e=r.getPath();for(let t=e.length-1;t>=0;t--)if("textMeta"!==e[t].metaType&&"commentMeta"!==e[t].metaType){r=e[t];break}}if("standardMeta"===e.metaType&&"scene"!==e.type&&y(r)){const t=z.value;t.instance&&e&&t.addChild(e),e.instance&&e.instance.isObject3D&&t.instance&&t!==e&&t.instance.add(e.instance)}else f(e)&&e.instance?.isObject3D&&f(r)&&r.instance?.isObject3D&&r.instance?.add?.(e.instance);if(e?.props?.attach&&f(t)&&t?.instance){e.type?.toLowerCase().endsWith("loader")&&e.props.src&&(e.props.attach||e.props.attachArray)?function(e,t){const n=e.instance;if(t.attached=t.attached||{},t.attachedArray=t.attachedArray||{},!e.props.attach)return;if("textureloader"===e.type?.toLowerCase()){const r=n.load(e.props.src);fe(e,t,e.props.attach,r)}else n.load(e.props.src,(n=>{fe(e,t,e.props.attach,n)}),null,(e=>{throw new Error(e)}))}(e,t):fe(e,t,e.props.attach)}e.props?.onAdded&&e.props.onAdded({instance:e.instance})}},nextSibling(e){const t=e.nextSibling;return t||null},parentNode(e){const t=e.parentNode;return t||null},patchProp(e,t,n,o){h(e)?"style"===t?Object.keys(o).forEach((t=>{e.domElement.style[t]=o[t]})):e.domElement.setAttribute(t,o):y(e)||t.startsWith("$")||function({node:e,key:t,value:n}){if((e=>["onClick","onContextMenu","onDoubleClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove","onWheel"].includes(e))(t))return b({node:e,key:t,value:n});const o=t.replace(/-/g,"."),a=le[o]||o;if(me.includes(t)||me.includes(a))return e;if(!f(e))return e;if("string"==typeof n&&n.startsWith("$attached")){const t=n.replace("$attached.","");n=r.get(e.attached,t,null)}const s=e.instance;if(!s)return e;let i;for(let e=0;e<pe.length&&!i;e++){const t=[pe[e],a].filter(Boolean).join(".");i=i=r.get(s,t)}if(i&&r.isNumber(n)&&i.setScalar)i.setScalar(n);else if(i&&i.set){const e=Array.isArray(n)?n:[n];s[a].set(...e)}else"function"==typeof i?i.bind(e.instance)(...n):void 0!==r.get(s,a,void 0)?r.set(s,a,""===n||n):console.log(`No property ${a} found on ${s}`);const c=s?.texture?.type||s?.type;if("string"==typeof c){const e=c.toLowerCase();switch(!0){case e.includes("material"):s.needsUpdate=!0;break;case e.includes("camera")&&s.updateProjectionMatrix:s.updateProjectionMatrix()}}}({node:e,key:t,value:o})},remove:e=>{if(!e)return;const t=Object.keys(O),n=[];e.walk((e=>(n.push(e),!0))),n.forEach((e=>{const n=t.find((t=>O[t]?.uuid===e.uuid));if(n&&(O[n]=null),f(e)){e.instance?.removeFromParent?.();const t="scene"!==e.type&&e.instance?.dispose;t&&t.bind(e.instance)(),e.instance=null}e.drop();const r=s.findIndex((t=>t.uuid===e.uuid));-1!==r&&s.splice(r,1)}))},setElementText(){},setText(){}},ve={dpr:t.ref(1),inputActive:g,mousePos:C},ge=t.computed((()=>D.value?.instance??null));const be=t.computed((()=>I.value?.instance??null));const xe=t.computed((()=>z.value.instance));let we=null,Re=null;e.camera=ge,e.clearCustomRender=()=>{we?we.clearCustomRender():Re=null},e.createApp=e=>{we=t.createRenderer(ye).createApp(e),Object.keys(p).forEach((e=>{we?.component(e,p[e])}));const{mount:n}=we;return we.mount=(e,...t)=>{const r=N({domElement:"string"==typeof e?document.querySelector(e):e,isLunchboxRootNode:!0,name:"root",metaType:"rootMeta",type:"root",uuid:"LUNCHBOX_ROOT"});we.rootNode=r;return n(r,...t)},we.extend=e=>((({app:e,...t})=>{Object.keys(t).forEach((n=>{e.component(n,q(n)),d[n]=t[n]}))})({app:we,...e}),we),we.setCustomRender=e=>{we.customRender=e},Re&&(we.setCustomRender(Re),Re=null),we.clearCustomRender=()=>{we.customRender=null},we},e.find=function(e){return e=t.isRef(e)?e.value:e,f(e)?e?.instance:m(e)?e?.$el?.instance:t.isVNode(e)?e.el?.instance:null},e.globals=ve,e.offAfterRender=e=>{if(isFinite(e))se.splice(e,1);else{const t=se.findIndex((t=>t==e));se.splice(t,1)}},e.offBeforeRender=e=>{if(isFinite(e))ae.splice(e,1);else{const t=ae.findIndex((t=>t==e));ae.splice(t,1)}},e.onAfterRender=(e,t=1/0)=>{t===1/0?se.push(e):se.splice(t,0,e)},e.onBeforeRender=(e,t=1/0)=>{t===1/0?ae.push(e):ae.splice(t,0,e)},e.onStart=(e,t=1/0)=>{t===1/0?ne.push(e):ne.splice(t,0,e)},e.renderer=be,e.scene=xe,e.setCustomRender=e=>{we?we.setCustomRender(e):Re=e},e.useCamera=function(e){return t.watch(ge,(t=>{t&&e(t)}),{immediate:!0})},e.useRenderer=function(e){return t.watch(be,(t=>{t&&e(t)}),{immediate:!0})},e.useScene=function(e){return t.watch(xe,(t=>{t&&e(t)}),{immediate:!0})},Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
@@ -97,6 +97,7 @@ const LunchboxWrapper = {
|
|
|
97
97
|
shadow: [Boolean, Object],
|
|
98
98
|
transparent: Boolean,
|
|
99
99
|
zoom: Number,
|
|
100
|
+
updateSource: Object,
|
|
100
101
|
},
|
|
101
102
|
setup(props, context) {
|
|
102
103
|
const canvas = ref();
|
|
@@ -276,12 +277,14 @@ const LunchboxWrapper = {
|
|
|
276
277
|
camera: camera.instance,
|
|
277
278
|
renderer: renderer.instance,
|
|
278
279
|
scene: scene.instance,
|
|
280
|
+
updateSource: props.updateSource,
|
|
279
281
|
});
|
|
280
282
|
});
|
|
281
283
|
// UNMOUNT
|
|
282
284
|
// ====================
|
|
283
285
|
onBeforeUnmount(() => {
|
|
284
286
|
cancelUpdate();
|
|
287
|
+
cancelUpdateSource();
|
|
285
288
|
});
|
|
286
289
|
// RENDER FUNCTION
|
|
287
290
|
// ====================
|
|
@@ -627,6 +630,7 @@ let mouseDownListener;
|
|
|
627
630
|
let mouseUpListener;
|
|
628
631
|
const mousePos = ref({ x: Infinity, y: Infinity });
|
|
629
632
|
let autoRaycasterEventsInitialized = false;
|
|
633
|
+
let frameID$1;
|
|
630
634
|
const setupAutoRaycaster = (node) => {
|
|
631
635
|
const instance = node.instance;
|
|
632
636
|
if (!instance)
|
|
@@ -659,8 +663,14 @@ const setupAutoRaycaster = (node) => {
|
|
|
659
663
|
renderer.instance.domElement.addEventListener('mousedown', mouseDownListener);
|
|
660
664
|
renderer.instance.domElement.addEventListener('mouseup', mouseUpListener);
|
|
661
665
|
// TODO: add touch events
|
|
662
|
-
//
|
|
663
|
-
|
|
666
|
+
// process mouse events asynchronously, whenever the mouse state changes
|
|
667
|
+
watch(() => [inputActive.value, mousePos.value.x, mousePos.value.y], () => {
|
|
668
|
+
if (frameID$1)
|
|
669
|
+
cancelAnimationFrame(frameID$1);
|
|
670
|
+
frameID$1 = requestAnimationFrame(() => {
|
|
671
|
+
autoRaycasterBeforeRender();
|
|
672
|
+
});
|
|
673
|
+
});
|
|
664
674
|
// mark complete
|
|
665
675
|
autoRaycasterEventsInitialized = true;
|
|
666
676
|
// cancel setup watcher
|
|
@@ -989,7 +999,7 @@ const extend = ({ app, ...targets }) => {
|
|
|
989
999
|
};
|
|
990
1000
|
|
|
991
1001
|
/** Process props into either themselves or the $attached value */
|
|
992
|
-
function processProp({ node, prop }) {
|
|
1002
|
+
function processProp({ node, prop, }) {
|
|
993
1003
|
// return $attachedArray value if needed
|
|
994
1004
|
if (typeof prop === 'string' && prop.startsWith('$attachedArray')) {
|
|
995
1005
|
return node.attachedArray[prop.replace('$attachedArray.', '')];
|
|
@@ -1001,10 +1011,12 @@ function processProp({ node, prop }) {
|
|
|
1001
1011
|
// otherwise, return plain value
|
|
1002
1012
|
return prop;
|
|
1003
1013
|
}
|
|
1004
|
-
function processPropAsArray({ node, prop }) {
|
|
1014
|
+
function processPropAsArray({ node, prop, }) {
|
|
1005
1015
|
const isAttachedArray = typeof prop === 'string' && prop.startsWith('$attachedArray');
|
|
1006
1016
|
const output = processProp({ node, prop });
|
|
1007
|
-
return Array.isArray(output) && isAttachedArray
|
|
1017
|
+
return Array.isArray(output) && isAttachedArray
|
|
1018
|
+
? output
|
|
1019
|
+
: [output];
|
|
1008
1020
|
}
|
|
1009
1021
|
|
|
1010
1022
|
function instantiateThreeObject(node) {
|
|
@@ -1303,16 +1315,34 @@ const onStart = (cb, index = Infinity) => {
|
|
|
1303
1315
|
};
|
|
1304
1316
|
|
|
1305
1317
|
let frameID;
|
|
1318
|
+
let watchStopHandle;
|
|
1306
1319
|
const beforeRender = [];
|
|
1307
1320
|
const afterRender = [];
|
|
1308
|
-
const
|
|
1309
|
-
|
|
1321
|
+
const requestUpdate = (opts) => {
|
|
1322
|
+
cancelUpdate();
|
|
1310
1323
|
frameID = requestAnimationFrame(() => update({
|
|
1311
1324
|
app: opts.app,
|
|
1312
1325
|
renderer: ensureRenderer.value?.instance,
|
|
1313
1326
|
scene: ensuredScene.value.instance,
|
|
1314
1327
|
camera: ensuredCamera.value?.instance,
|
|
1328
|
+
updateSource: opts.updateSource,
|
|
1315
1329
|
}));
|
|
1330
|
+
};
|
|
1331
|
+
const update = (opts) => {
|
|
1332
|
+
if (opts.updateSource) {
|
|
1333
|
+
if (!watchStopHandle) {
|
|
1334
|
+
// request next frame only when state changes
|
|
1335
|
+
watchStopHandle = watch(opts.updateSource, () => {
|
|
1336
|
+
requestUpdate(opts);
|
|
1337
|
+
}, {
|
|
1338
|
+
deep: true,
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
else {
|
|
1343
|
+
// request next frame on a continuous loop
|
|
1344
|
+
requestUpdate(opts);
|
|
1345
|
+
}
|
|
1316
1346
|
// prep options
|
|
1317
1347
|
const { app, renderer, scene, camera } = opts;
|
|
1318
1348
|
// BEFORE RENDER
|
|
@@ -1375,6 +1405,10 @@ const cancelUpdate = () => {
|
|
|
1375
1405
|
if (frameID)
|
|
1376
1406
|
cancelAnimationFrame(frameID);
|
|
1377
1407
|
};
|
|
1408
|
+
const cancelUpdateSource = () => {
|
|
1409
|
+
if (watchStopHandle)
|
|
1410
|
+
watchStopHandle();
|
|
1411
|
+
};
|
|
1378
1412
|
|
|
1379
1413
|
/** Update a single prop on a given node. */
|
|
1380
1414
|
function updateObjectProp({ node, key, value, }) {
|
package/package.json
CHANGED
|
@@ -5,11 +5,13 @@ import {
|
|
|
5
5
|
onBeforeUnmount,
|
|
6
6
|
onMounted,
|
|
7
7
|
ref,
|
|
8
|
+
WatchSource,
|
|
8
9
|
WritableComputedRef,
|
|
9
10
|
} from 'vue'
|
|
10
11
|
import {
|
|
11
12
|
cameraReady,
|
|
12
13
|
cancelUpdate,
|
|
14
|
+
cancelUpdateSource,
|
|
13
15
|
createNode,
|
|
14
16
|
ensuredCamera,
|
|
15
17
|
ensureRenderer,
|
|
@@ -62,6 +64,7 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
62
64
|
shadow: [Boolean, Object],
|
|
63
65
|
transparent: Boolean,
|
|
64
66
|
zoom: Number,
|
|
67
|
+
updateSource: Object,
|
|
65
68
|
},
|
|
66
69
|
setup(props: Lunch.WrapperProps, context) {
|
|
67
70
|
const canvas = ref<MiniDom.RendererDomNode>()
|
|
@@ -267,6 +270,7 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
267
270
|
camera: camera.instance,
|
|
268
271
|
renderer: renderer.instance,
|
|
269
272
|
scene: scene.instance,
|
|
273
|
+
updateSource: props.updateSource,
|
|
270
274
|
})
|
|
271
275
|
})
|
|
272
276
|
|
|
@@ -274,6 +278,7 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
274
278
|
// ====================
|
|
275
279
|
onBeforeUnmount(() => {
|
|
276
280
|
cancelUpdate()
|
|
281
|
+
cancelUpdateSource()
|
|
277
282
|
})
|
|
278
283
|
|
|
279
284
|
// RENDER FUNCTION
|
|
@@ -5,7 +5,7 @@ import { resizeCanvas } from './resizeCanvas'
|
|
|
5
5
|
export const prepCanvas = (
|
|
6
6
|
container: Ref<MiniDom.RendererDomNode | undefined>,
|
|
7
7
|
canvasElement: HTMLCanvasElement,
|
|
8
|
-
onBeforeUnmount: Function
|
|
8
|
+
onBeforeUnmount: Function
|
|
9
9
|
) => {
|
|
10
10
|
const containerElement = container.value?.domElement
|
|
11
11
|
if (!containerElement) throw new Error('missing container')
|
|
@@ -29,4 +29,4 @@ export const prepCanvas = (
|
|
|
29
29
|
observer.unobserve(canvasElement)
|
|
30
30
|
}
|
|
31
31
|
})
|
|
32
|
-
}
|
|
32
|
+
}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { Lunch } from '../..'
|
|
2
2
|
|
|
3
3
|
/** Process props into either themselves or the $attached value */
|
|
4
|
-
export function processProp<T, U = THREE.Object3D>({
|
|
4
|
+
export function processProp<T, U = THREE.Object3D>({
|
|
5
|
+
node,
|
|
6
|
+
prop,
|
|
7
|
+
}: {
|
|
8
|
+
node: Lunch.StandardMeta<U>
|
|
9
|
+
prop: any
|
|
10
|
+
}) {
|
|
5
11
|
// return $attachedArray value if needed
|
|
6
12
|
if (typeof prop === 'string' && prop.startsWith('$attachedArray')) {
|
|
7
|
-
return node.attachedArray[
|
|
13
|
+
return node.attachedArray[
|
|
14
|
+
prop.replace('$attachedArray.', '')
|
|
15
|
+
] as any as T
|
|
8
16
|
}
|
|
9
17
|
|
|
10
18
|
// return $attached value if needed
|
|
@@ -16,8 +24,17 @@ export function processProp<T, U = THREE.Object3D>({ node, prop }: { node: Lunch
|
|
|
16
24
|
return prop as T
|
|
17
25
|
}
|
|
18
26
|
|
|
19
|
-
export function processPropAsArray<T, U = THREE.Object3D>({
|
|
20
|
-
|
|
27
|
+
export function processPropAsArray<T, U = THREE.Object3D>({
|
|
28
|
+
node,
|
|
29
|
+
prop,
|
|
30
|
+
}: {
|
|
31
|
+
node: Lunch.StandardMeta<U>
|
|
32
|
+
prop: any
|
|
33
|
+
}) {
|
|
34
|
+
const isAttachedArray =
|
|
35
|
+
typeof prop === 'string' && prop.startsWith('$attachedArray')
|
|
21
36
|
const output = processProp<T, U>({ node, prop })
|
|
22
|
-
return Array.isArray(output) && isAttachedArray
|
|
23
|
-
|
|
37
|
+
return Array.isArray(output) && isAttachedArray
|
|
38
|
+
? (output as Array<T>)
|
|
39
|
+
: [output]
|
|
40
|
+
}
|
|
@@ -17,6 +17,8 @@ let mouseUpListener: (event: MouseEvent) => void
|
|
|
17
17
|
export const mousePos = ref({ x: Infinity, y: Infinity })
|
|
18
18
|
let autoRaycasterEventsInitialized = false
|
|
19
19
|
|
|
20
|
+
let frameID: number
|
|
21
|
+
|
|
20
22
|
export const setupAutoRaycaster = (node: Lunch.Node<THREE.Raycaster>) => {
|
|
21
23
|
const instance = node.instance
|
|
22
24
|
|
|
@@ -67,8 +69,16 @@ export const setupAutoRaycaster = (node: Lunch.Node<THREE.Raycaster>) => {
|
|
|
67
69
|
|
|
68
70
|
// TODO: add touch events
|
|
69
71
|
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
+
// process mouse events asynchronously, whenever the mouse state changes
|
|
73
|
+
watch(
|
|
74
|
+
() => [inputActive.value, mousePos.value.x, mousePos.value.y],
|
|
75
|
+
() => {
|
|
76
|
+
if (frameID) cancelAnimationFrame(frameID)
|
|
77
|
+
frameID = requestAnimationFrame(() => {
|
|
78
|
+
autoRaycasterBeforeRender()
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
)
|
|
72
82
|
|
|
73
83
|
// mark complete
|
|
74
84
|
autoRaycasterEventsInitialized = true
|
package/src/core/update.ts
CHANGED
|
@@ -1,22 +1,44 @@
|
|
|
1
1
|
import { ensureRenderer, ensuredScene, ensuredCamera } from '.'
|
|
2
2
|
import { Lunch } from '..'
|
|
3
|
-
import { toRaw } from 'vue'
|
|
3
|
+
import { toRaw, watch, WatchStopHandle } from 'vue'
|
|
4
4
|
|
|
5
5
|
let frameID: number
|
|
6
|
+
let watchStopHandle: WatchStopHandle
|
|
6
7
|
|
|
7
8
|
export const beforeRender = [] as Lunch.UpdateCallback[]
|
|
8
9
|
export const afterRender = [] as Lunch.UpdateCallback[]
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
const requestUpdate = (opts: Lunch.UpdateCallbackProperties) => {
|
|
12
|
+
cancelUpdate()
|
|
12
13
|
frameID = requestAnimationFrame(() =>
|
|
13
14
|
update({
|
|
14
15
|
app: opts.app,
|
|
15
16
|
renderer: ensureRenderer.value?.instance,
|
|
16
17
|
scene: ensuredScene.value.instance,
|
|
17
18
|
camera: ensuredCamera.value?.instance,
|
|
19
|
+
updateSource: opts.updateSource,
|
|
18
20
|
})
|
|
19
21
|
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const update: Lunch.UpdateCallback = (opts) => {
|
|
25
|
+
if (opts.updateSource) {
|
|
26
|
+
if (!watchStopHandle) {
|
|
27
|
+
// request next frame only when state changes
|
|
28
|
+
watchStopHandle = watch(
|
|
29
|
+
opts.updateSource,
|
|
30
|
+
() => {
|
|
31
|
+
requestUpdate(opts)
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
deep: true,
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
// request next frame on a continuous loop
|
|
40
|
+
requestUpdate(opts)
|
|
41
|
+
}
|
|
20
42
|
|
|
21
43
|
// prep options
|
|
22
44
|
const { app, renderer, scene, camera } = opts
|
|
@@ -82,3 +104,7 @@ export const offAfterRender = (cb: Lunch.UpdateCallback | number) => {
|
|
|
82
104
|
export const cancelUpdate = () => {
|
|
83
105
|
if (frameID) cancelAnimationFrame(frameID)
|
|
84
106
|
}
|
|
107
|
+
|
|
108
|
+
export const cancelUpdateSource = () => {
|
|
109
|
+
if (watchStopHandle) watchStopHandle()
|
|
110
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
type RootNode = import('./core/minidom').MiniDom.RendererRootNode
|
|
2
2
|
type VNodeProps = import('vue').VNodeProps
|
|
3
3
|
type VueApp<T> = import('vue').App<T>
|
|
4
|
+
type WatchSource = import('vue').WatchSource
|
|
4
5
|
type RendererStandardNode<T = THREE.Object3D> =
|
|
5
6
|
import('./core').MiniDom.RendererStandardNode<T>
|
|
6
7
|
|
|
@@ -127,6 +128,7 @@ export declare namespace Lunch {
|
|
|
127
128
|
scene?: THREE.Scene | null
|
|
128
129
|
renderer?: THREE.Renderer | null
|
|
129
130
|
camera?: THREE.Camera | null
|
|
131
|
+
updateSource?: WatchSource | null
|
|
130
132
|
|
|
131
133
|
// sceneNode: Node<THREE.Scene> | null
|
|
132
134
|
// rendererNode: Node<THREE.Renderer> | null
|
|
@@ -152,5 +154,6 @@ export declare namespace Lunch {
|
|
|
152
154
|
shadow?: ShadowSugar
|
|
153
155
|
transparent?: boolean
|
|
154
156
|
zoom?: number
|
|
157
|
+
updateSource?: WatchSource | null
|
|
155
158
|
}
|
|
156
159
|
}
|