lunchboxjs 0.1.4006 → 0.1.4010
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 +78 -9
- package/dist/lunchboxjs.min.js +1 -1
- package/dist/lunchboxjs.module.js +75 -10
- package/package.json +1 -1
- package/src/components/LunchboxWrapper/LunchboxWrapper.ts +25 -8
- package/src/core/index.ts +2 -1
- package/src/core/interaction/index.ts +0 -1
- package/src/core/start.ts +11 -0
- package/src/index.ts +75 -2
- package/src/types.ts +2 -0
package/dist/lunchboxjs.js
CHANGED
|
@@ -111,6 +111,7 @@
|
|
|
111
111
|
dpr: Number,
|
|
112
112
|
ortho: Boolean,
|
|
113
113
|
orthographic: Boolean,
|
|
114
|
+
rendererArguments: Object,
|
|
114
115
|
rendererProperties: Object,
|
|
115
116
|
shadow: [Boolean, Object],
|
|
116
117
|
transparent: Boolean,
|
|
@@ -140,12 +141,11 @@
|
|
|
140
141
|
if (!renderer) {
|
|
141
142
|
// build renderer args
|
|
142
143
|
const rendererArgs = {
|
|
144
|
+
alpha: props.transparent,
|
|
143
145
|
antialias: true,
|
|
144
146
|
canvas: canvas.value.domElement,
|
|
147
|
+
...(props.rendererArguments ?? {}),
|
|
145
148
|
};
|
|
146
|
-
if (props.transparent) {
|
|
147
|
-
rendererArgs.alpha = true;
|
|
148
|
-
}
|
|
149
149
|
// create new renderer
|
|
150
150
|
ensureRenderer.value = createNode({
|
|
151
151
|
type: 'WebGLRenderer',
|
|
@@ -183,7 +183,6 @@
|
|
|
183
183
|
// the user has initialized the renderer, so anything depending
|
|
184
184
|
// on the renderer can execute
|
|
185
185
|
rendererReady.value = true;
|
|
186
|
-
return;
|
|
187
186
|
}
|
|
188
187
|
// CAMERA
|
|
189
188
|
// ====================
|
|
@@ -217,14 +216,17 @@
|
|
|
217
216
|
else {
|
|
218
217
|
cameraReady.value = true;
|
|
219
218
|
}
|
|
219
|
+
if (!camera.instance) {
|
|
220
|
+
throw new Error('Error creating camera.');
|
|
221
|
+
}
|
|
220
222
|
// move camera if needed
|
|
221
223
|
if (camera && props.cameraPosition) {
|
|
222
|
-
camera.instance
|
|
224
|
+
camera.instance.position.set(...props.cameraPosition);
|
|
223
225
|
}
|
|
224
226
|
// angle camera if needed
|
|
225
227
|
if (camera && (props.cameraLookAt || props.cameraLook)) {
|
|
226
228
|
const source = (props.cameraLookAt || props.cameraLook);
|
|
227
|
-
camera.instance
|
|
229
|
+
camera.instance.lookAt(...source);
|
|
228
230
|
}
|
|
229
231
|
// SCENE
|
|
230
232
|
// ====================
|
|
@@ -247,11 +249,23 @@
|
|
|
247
249
|
else {
|
|
248
250
|
throw new Error('missing renderer');
|
|
249
251
|
}
|
|
252
|
+
// CALLBACK PREP
|
|
253
|
+
// ====================
|
|
254
|
+
const app = vue.getCurrentInstance().appContext.app;
|
|
255
|
+
// START
|
|
256
|
+
// ====================
|
|
257
|
+
for (let startCallback of startCallbacks) {
|
|
258
|
+
startCallback({
|
|
259
|
+
app,
|
|
260
|
+
camera: camera.instance,
|
|
261
|
+
renderer: renderer.instance,
|
|
262
|
+
scene: scene.instance,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
250
265
|
// KICK UPDATE
|
|
251
266
|
// ====================
|
|
252
|
-
// console.log(scene)
|
|
253
267
|
update({
|
|
254
|
-
app
|
|
268
|
+
app,
|
|
255
269
|
camera: camera.instance,
|
|
256
270
|
renderer: renderer.instance,
|
|
257
271
|
scene: scene.instance,
|
|
@@ -628,7 +642,6 @@
|
|
|
628
642
|
// register click, pointerdown, pointerup
|
|
629
643
|
if (key === 'onClick' || key === 'onPointerDown' || key === 'onPointerUp') {
|
|
630
644
|
const stop = vue.watch(() => inputActive.value, (isDown) => {
|
|
631
|
-
console.log(isDown, currentIntersections);
|
|
632
645
|
const idx = currentIntersections
|
|
633
646
|
.map((v) => v.element)
|
|
634
647
|
.findIndex((v) => v.instance &&
|
|
@@ -1261,6 +1274,16 @@
|
|
|
1261
1274
|
const rootNode = new MiniDom.RendererRootNode();
|
|
1262
1275
|
rootNode.minidomType = 'RootNode';
|
|
1263
1276
|
|
|
1277
|
+
const startCallbacks = [];
|
|
1278
|
+
const onStart = (cb, index = Infinity) => {
|
|
1279
|
+
if (index === Infinity) {
|
|
1280
|
+
startCallbacks.push(cb);
|
|
1281
|
+
}
|
|
1282
|
+
else {
|
|
1283
|
+
startCallbacks.splice(index, 0, cb);
|
|
1284
|
+
}
|
|
1285
|
+
};
|
|
1286
|
+
|
|
1264
1287
|
let frameID;
|
|
1265
1288
|
const beforeRender = [];
|
|
1266
1289
|
const afterRender = [];
|
|
@@ -1683,9 +1706,51 @@
|
|
|
1683
1706
|
inputActive,
|
|
1684
1707
|
mousePos,
|
|
1685
1708
|
};
|
|
1709
|
+
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
1686
1710
|
const camera = vue.computed(() => ensuredCamera.value?.instance ?? null);
|
|
1711
|
+
/** Run a function using the current camera when it's present. */
|
|
1712
|
+
function useCamera(callback, once = true) {
|
|
1713
|
+
let destroy;
|
|
1714
|
+
destroy = vue.watch(camera, (newVal) => {
|
|
1715
|
+
if (!newVal)
|
|
1716
|
+
return;
|
|
1717
|
+
// TODO: better fix than `any`?
|
|
1718
|
+
callback(newVal);
|
|
1719
|
+
if (once) {
|
|
1720
|
+
destroy?.();
|
|
1721
|
+
}
|
|
1722
|
+
}, { immediate: true });
|
|
1723
|
+
}
|
|
1724
|
+
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
1687
1725
|
const renderer = vue.computed(() => ensureRenderer.value?.instance ?? null);
|
|
1726
|
+
/** Run a function using the current renderer when it's present. */
|
|
1727
|
+
function useRenderer(callback, once = true) {
|
|
1728
|
+
let destroy;
|
|
1729
|
+
destroy = vue.watch(renderer, (newVal) => {
|
|
1730
|
+
if (!newVal)
|
|
1731
|
+
return;
|
|
1732
|
+
// TODO: better fix than `any`?
|
|
1733
|
+
callback(newVal);
|
|
1734
|
+
if (once) {
|
|
1735
|
+
destroy?.();
|
|
1736
|
+
}
|
|
1737
|
+
}, { immediate: true });
|
|
1738
|
+
}
|
|
1739
|
+
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
1688
1740
|
const scene = vue.computed(() => ensuredScene.value.instance);
|
|
1741
|
+
/** Run a function using the current scene when it's present. */
|
|
1742
|
+
function useScene(callback, once = true) {
|
|
1743
|
+
let destroy;
|
|
1744
|
+
destroy = vue.watch(scene, (newVal) => {
|
|
1745
|
+
if (!newVal)
|
|
1746
|
+
return;
|
|
1747
|
+
// TODO: better fix than `any`?
|
|
1748
|
+
callback(newVal);
|
|
1749
|
+
if (once) {
|
|
1750
|
+
destroy?.();
|
|
1751
|
+
}
|
|
1752
|
+
}, { immediate: true });
|
|
1753
|
+
}
|
|
1689
1754
|
// CUSTOM RENDER SUPPORT
|
|
1690
1755
|
// ====================
|
|
1691
1756
|
let app = null;
|
|
@@ -1761,9 +1826,13 @@
|
|
|
1761
1826
|
exports.offBeforeRender = offBeforeRender;
|
|
1762
1827
|
exports.onAfterRender = onAfterRender;
|
|
1763
1828
|
exports.onBeforeRender = onBeforeRender;
|
|
1829
|
+
exports.onStart = onStart;
|
|
1764
1830
|
exports.renderer = renderer;
|
|
1765
1831
|
exports.scene = scene;
|
|
1766
1832
|
exports.setCustomRender = setCustomRender;
|
|
1833
|
+
exports.useCamera = useCamera;
|
|
1834
|
+
exports.useRenderer = useRenderer;
|
|
1835
|
+
exports.useScene = useScene;
|
|
1767
1836
|
|
|
1768
1837
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1769
1838
|
|
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=K.value?.instance,o=_.value.instance,a=$.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,rendererProperties:Object,shadow:[Boolean,Object],transparent:Boolean},setup(e,o){const a=t.ref(),s=t.ref(!0),d=t.ref(e.dpr??-1),u=t.ref();let l,p,m;return t.onMounted((()=>{if(!a.value)throw new Error("missing canvas");if(l=T(["WebGLRenderer"]),l)return s.value=!1,void(I.value=!0);{const t={antialias:!0,canvas:a.value.domElement};e.transparent&&(t.alpha=!0),K.value=g({type:"WebGLRenderer",uuid:U,props:{args:[t]}}),I.value=!0;const n=K,o={shadow:e.shadow};n.value.instance&&o?.shadow&&(n.value.instance.shadowMap.enabled=!0,"object"==typeof o.shadow&&(n.value.instance.shadowMap.type=o.shadow.type)),e.rendererProperties&&Object.keys(e.rendererProperties).forEach((t=>{r.set(n.value,t,e.rendererProperties[t])})),l=n.value}if(p=T(["PerspectiveCamera","OrthographicCamera"]),p?D.value=!0:(e.ortho||e.orthographic?$.value=g({props:{args:e.cameraArgs??[]},type:"OrthographicCamera",uuid:F}):$.value=g({props:{args:e.cameraArgs??[45,.5625,1,1e3]},type:"PerspectiveCamera",uuid:F}),D.value=!0,p=$.value),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(m=_.value,m&&m.instance&&e.background&&(m.instance.background=new n.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),ae({app:t.getCurrentInstance().appContext.app,camera:p.instance,renderer:l.instance,scene:m.instance})})),t.onBeforeUnmount((()=>{ie()})),()=>[o.slots.default?.()??null,t.h("div",{style:c("absolute"),ref:u},[s.value?t.h("canvas",{style:c("fixed"),class:"lunchbox-canvas",ref:a}):null])]}},u=["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"],l={},p=["canvas","div","LunchboxWrapper"];u.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)));const m={...u,Lunchbox:d};const h=e=>e?.$el&&e?.$el?.hasOwnProperty?.("instance"),f=e=>{if("domMeta"===e?.metaType)return!0;const t="string"==typeof e?e:e?.type;return p.includes(t??"")},y=e=>"standardMeta"===e?.metaType,v=e=>e.isLunchboxRootNode;function g(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||v(r)||r.instance||(r.instance=function(e){if(!e.type)return null;const t=e.type[0].toUpperCase()+e.type.slice(1),n=l[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&&(_.value=r),r}const b=[],x=t.ref(!1);function R({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),A.includes(n)&&(V.value,e.instance&&!b.includes(e)&&(o=e,b.push(o),e.eventListenerRemoveFunctions[n].push((()=>(e=>{const t=b.indexOf(e);-1!==t&&b.splice(t,1)})(e))))),"onClick"===n||"onPointerDown"===n||"onPointerUp"===n){const r=t.watch((()=>x.value),(t=>{console.log(t,M);const r=M.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:M[r].intersection})})))}));e.eventListenerRemoveFunctions[n].push(r)}return e}const A=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"];let w,C,E;const L=t.ref({x:1/0,y:1/0});let P=!1;let M=[];const B=()=>{const e=V.value?.instance,t=$.value?.instance;if(!e||!t)return;e.setFromCamera(he.mousePos.value,t);const n=e.intersectObjects(b.map((e=>e.instance)));let r=[],o=[],a=[];r=M.map((e=>e.intersection)),n?.forEach((e=>{const t=M.findIndex((t=>t.intersection.object===e.object));if(-1===t){const t=b.find((t=>t.instance?.uuid===e.object.uuid));t&&o.push({element:t,intersection:e})}else{const t=b.find((t=>t.instance?.uuid===e.object.uuid));t&&a.push({element:t,intersection:e})}const n=r.findIndex((t=>t.object.uuid===e.object.uuid));-1!==n&&r.splice(n,1)}));const s=r.map((e=>({element:b.find((t=>t.instance?.uuid===e.object.uuid)),intersection:e})));o.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerEnter"],intersection:t})})),a.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),s.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),M=[].concat(o,a)},G=({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 T(e){Array.isArray(e)||(e=[e]);for(let t of e)if(j[t])return j[t];for(let t of e){const e=O[t]||s.find((e=>e.type?.toLowerCase()===t.toLowerCase()));if(e){const n=e;return O[t]=n,n}}return null}e.lunchboxTree=void 0;const O=t.reactive({}),j=t.reactive({});function k(e,n,r={},o=null){Array.isArray(e)||(e=[e]);for(let t of e)O[t]||(O[t]=null),j[t]||(j[t]=null);return t.computed({get(){const t=T(e);if(t)return t;const a=N(),s=g({type:e[0],uuid:n,props:r});return a.addChild(s),O[e[0]]=s,o&&o(s),s},set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}})}const F="FALLBACK_CAMERA",S=k(["PerspectiveCamera","OrthographicCamera"],F,{args:[45,.5625,1,1e3]}),D=t.ref(!1),$=t.computed({get:()=>D.value?S.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}}),U="FALLBACK_RENDERER",W=k(["WebGLRenderer"],U,{}),I=t.ref(!1),K=t.computed({get:()=>I.value?W.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}}),_=k("Scene","FALLBACK_SCENE"),V=k("Raycaster","AUTO_RAYCASTER",{},(e=>(e=>{if(!e.instance)return;let n=null;n=t.watch((()=>K.value),(e=>{e?.instance&&(P||(w=t=>{const n=(e.instance.domElement.width??1)/he.dpr.value,r=(e.instance.domElement.height??1)/he.dpr.value;L.value.x=t.offsetX/n*2-1,L.value.y=-t.offsetY/r*2+1},C=()=>x.value=!0,E=()=>x.value=!1,e.instance.domElement.addEventListener("mousemove",w),e.instance.domElement.addEventListener("mousedown",C),e.instance.domElement.addEventListener("mouseup",E),se(B),P=!0),n&&n())}),{immediate:!0})})(e))),q=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}});var z,H=new Uint8Array(16);function Y(){if(!z&&!(z="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 z(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={}));let ne;(new Q.RendererRootNode).minidomType="RootNode";const re=[],oe=[],ae=e=>{ne=requestAnimationFrame((()=>ae({app:e.app,renderer:K.value?.instance,scene:_.value.instance,camera:$.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","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(f(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=g(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 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&&(f(e)&&(f(t)||v(t))&&t.domElement.appendChild(e.domElement),y(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&&v(r)){const t=_.value;t.instance&&e&&t.addChild(e),e.instance&&e.instance.isObject3D&&t.instance&&t!==e&&t.instance.add(e.instance)}else y(e)&&e.instance?.isObject3D&&y(r)&&r.instance?.isObject3D&&r.instance?.add?.(e.instance);if(e?.props?.attach&&y(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){f(e)?"style"===t?Object.keys(o).forEach((t=>{e.domElement.style[t]=o[t]})):e.domElement.setAttribute(t,o):v(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 R({node:e,key:t,value:n});if(ue.includes(t))return e;if(!y(e))return e;if("string"==typeof n&&n.startsWith("$attached")){const t=n.replace("$attached.","");n=r.get(e.attached,t,null)}const o=e.instance;if(!o)return e;const a=t.replace(/-/g,".");let s,i=ce[a]||a;for(let e=0;e<de.length&&!s;e++){const t=[de[e],i].filter(Boolean).join(".");s=s=r.get(o,t)}if(s&&r.isNumber(n)&&s.setScalar)s.setScalar(n);else if(s&&s.set){const e=Array.isArray(n)?n:[n];o[i].set(...e)}else"function"==typeof s?s.bind(e.instance)(...n):void 0!==r.get(o,i,void 0)?r.set(o,i,""===n||n):console.log(`No property ${i} found on ${o}`);const c=o?.texture?.type||o?.type;if("string"==typeof c){const e=c.toLowerCase();switch(!0){case e.includes("material"):o.needsUpdate=!0;break;case e.includes("camera")&&o.updateProjectionMatrix:o.updateProjectionMatrix()}}}({node:e,key:t,value:o})},remove:e=>{if(!e)return;const t=Object.keys(j),n=[];e.walk((e=>(n.push(e),!0))),n.forEach((e=>{const n=t.find((t=>j[t]?.uuid===e.uuid));if(n&&(j[n]=null),y(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:x,mousePos:L},fe=t.computed((()=>$.value?.instance??null)),ye=t.computed((()=>K.value?.instance??null)),ve=t.computed((()=>_.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(m).forEach((e=>{ge.component(e,m[e])}));const{mount:n}=ge;return ge.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"});ge.rootNode=r;return n(r,...t)},ge.extend=e=>((({app:e,...t})=>{Object.keys(t).forEach((n=>{e.component(n,q(n)),l[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,y(e)?e?.instance:h(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.renderer=ye,e.scene=ve,e.setCustomRender=e=>{ge?ge.setCustomRender(e):be=e},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=K.value?.instance,o=_.value.instance,a=$.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,rendererArguments:Object,rendererProperties:Object,shadow:[Boolean,Object],transparent:Boolean},setup(e,o){const a=t.ref(),s=t.ref(!0),d=t.ref(e.dpr??-1),u=t.ref();let l,p,m;return t.onMounted((()=>{if(!a.value)throw new Error("missing canvas");if(l=T(["WebGLRenderer"]),l)s.value=!1,I.value=!0;else{const t={alpha:e.transparent,antialias:!0,canvas:a.value.domElement,...e.rendererArguments??{}};K.value=g({type:"WebGLRenderer",uuid:U,props:{args:[t]}}),I.value=!0;const n=K,o={shadow:e.shadow};n.value.instance&&o?.shadow&&(n.value.instance.shadowMap.enabled=!0,"object"==typeof o.shadow&&(n.value.instance.shadowMap.type=o.shadow.type)),e.rendererProperties&&Object.keys(e.rendererProperties).forEach((t=>{r.set(n.value,t,e.rendererProperties[t])})),l=n.value}if(p=T(["PerspectiveCamera","OrthographicCamera"]),p?D.value=!0:(e.ortho||e.orthographic?$.value=g({props:{args:e.cameraArgs??[]},type:"OrthographicCamera",uuid:S}):$.value=g({props:{args:e.cameraArgs??[45,.5625,1,1e3]},type:"PerspectiveCamera",uuid:S}),D.value=!0,p=$.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(m=_.value,m&&m.instance&&e.background&&(m.instance.background=new n.Color(e.background)),-1===d.value&&(d.value=window.devicePixelRatio),!l?.instance)throw new Error("missing renderer");l.instance.setPixelRatio(d.value),fe.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 o=t.getCurrentInstance().appContext.app;for(let e of ne)e({app:o,camera:p.instance,renderer:l.instance,scene:m.instance});se({app:o,camera:p.instance,renderer:l.instance,scene:m.instance})})),t.onBeforeUnmount((()=>{ce()})),()=>[o.slots.default?.()??null,t.h("div",{style:c("absolute"),ref:u},[s.value?t.h("canvas",{style:c("fixed"),class:"lunchbox-canvas",ref:a}):null])]}},u=["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"],l={},p=["canvas","div","LunchboxWrapper"];u.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)));const m={...u,Lunchbox:d};const h=e=>e?.$el&&e?.$el?.hasOwnProperty?.("instance"),f=e=>{if("domMeta"===e?.metaType)return!0;const t="string"==typeof e?e:e?.type;return p.includes(t??"")},y=e=>"standardMeta"===e?.metaType,v=e=>e.isLunchboxRootNode;function g(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||v(r)||r.instance||(r.instance=function(e){if(!e.type)return null;const t=e.type[0].toUpperCase()+e.type.slice(1),n=l[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&&(_.value=r),r}const b=[],x=t.ref(!1);function R({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),w.includes(n)&&(V.value,e.instance&&!b.includes(e)&&(o=e,b.push(o),e.eventListenerRemoveFunctions[n].push((()=>(e=>{const t=b.indexOf(e);-1!==t&&b.splice(t,1)})(e))))),"onClick"===n||"onPointerDown"===n||"onPointerUp"===n){const r=t.watch((()=>x.value),(t=>{const r=M.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:M[r].intersection})})))}));e.eventListenerRemoveFunctions[n].push(r)}return e}const w=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"];let A,C,E;const L=t.ref({x:1/0,y:1/0});let P=!1;let M=[];const B=()=>{const e=V.value?.instance,t=$.value?.instance;if(!e||!t)return;e.setFromCamera(fe.mousePos.value,t);const n=e.intersectObjects(b.map((e=>e.instance)));let r=[],o=[],a=[];r=M.map((e=>e.intersection)),n?.forEach((e=>{const t=M.findIndex((t=>t.intersection.object===e.object));if(-1===t){const t=b.find((t=>t.instance?.uuid===e.object.uuid));t&&o.push({element:t,intersection:e})}else{const t=b.find((t=>t.instance?.uuid===e.object.uuid));t&&a.push({element:t,intersection:e})}const n=r.findIndex((t=>t.object.uuid===e.object.uuid));-1!==n&&r.splice(n,1)}));const s=r.map((e=>({element:b.find((t=>t.instance?.uuid===e.object.uuid)),intersection:e})));o.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerEnter"],intersection:t})})),a.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),s.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),M=[].concat(o,a)},G=({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 T(e){Array.isArray(e)||(e=[e]);for(let t of e)if(j[t])return j[t];for(let t of e){const e=O[t]||s.find((e=>e.type?.toLowerCase()===t.toLowerCase()));if(e){const n=e;return O[t]=n,n}}return null}e.lunchboxTree=void 0;const O=t.reactive({}),j=t.reactive({});function k(e,n,r={},o=null){Array.isArray(e)||(e=[e]);for(let t of e)O[t]||(O[t]=null),j[t]||(j[t]=null);return t.computed({get(){const t=T(e);if(t)return t;const a=N(),s=g({type:e[0],uuid:n,props:r});return a.addChild(s),O[e[0]]=s,o&&o(s),s},set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}})}const S="FALLBACK_CAMERA",F=k(["PerspectiveCamera","OrthographicCamera"],S,{args:[45,.5625,1,1e3]}),D=t.ref(!1),$=t.computed({get:()=>D.value?F.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}}),U="FALLBACK_RENDERER",W=k(["WebGLRenderer"],U,{}),I=t.ref(!1),K=t.computed({get:()=>I.value?W.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}}),_=k("Scene","FALLBACK_SCENE"),V=k("Raycaster","AUTO_RAYCASTER",{},(e=>(e=>{if(!e.instance)return;let n=null;n=t.watch((()=>K.value),(e=>{e?.instance&&(P||(A=t=>{const n=(e.instance.domElement.width??1)/fe.dpr.value,r=(e.instance.domElement.height??1)/fe.dpr.value;L.value.x=t.offsetX/n*2-1,L.value.y=-t.offsetY/r*2+1},C=()=>x.value=!0,E=()=>x.value=!1,e.instance.domElement.addEventListener("mousemove",A),e.instance.domElement.addEventListener("mousedown",C),e.instance.domElement.addEventListener("mouseup",E),ie(B),P=!0),n&&n())}),{immediate:!0})})(e))),q=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}});var z,H=new Uint8Array(16);function Y(){if(!z&&!(z="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 z(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;const oe=[],ae=[],se=e=>{re=requestAnimationFrame((()=>se({app:e.app,renderer:K.value?.instance,scene:_.value.instance,camera:$.value?.instance})));const{app:n,renderer:r,scene:o,camera:a}=e;oe.forEach((t=>{t&&t(e)})),r&&o&&a&&(n.customRender?n.customRender(e):r.render(t.toRaw(o),t.toRaw(a))),ae.forEach((t=>{t&&t(e)}))},ie=(e,t=1/0)=>{t===1/0?oe.push(e):oe.splice(t,0,e)},ce=()=>{re&&cancelAnimationFrame(re)};const de={x:"position.x",y:"position.y",z:"position.z"},ue=["","parameters"],le=["args","attach","attachArray","key","onAdded","ref","src"],pe=["geometry","material"];function me(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 he={createElement:(e,t,n,r)=>{const o={type:e};r&&(o.props=r);if(f(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=g(o);return pe.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&&(f(e)&&(f(t)||v(t))&&t.domElement.appendChild(e.domElement),y(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&&v(r)){const t=_.value;t.instance&&e&&t.addChild(e),e.instance&&e.instance.isObject3D&&t.instance&&t!==e&&t.instance.add(e.instance)}else y(e)&&e.instance?.isObject3D&&y(r)&&r.instance?.isObject3D&&r.instance?.add?.(e.instance);if(e?.props?.attach&&y(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);me(e,t,e.props.attach,r)}else n.load(e.props.src,(n=>{me(e,t,e.props.attach,n)}),null,(e=>{throw new Error(e)}))}(e,t):me(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){f(e)?"style"===t?Object.keys(o).forEach((t=>{e.domElement.style[t]=o[t]})):e.domElement.setAttribute(t,o):v(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 R({node:e,key:t,value:n});if(le.includes(t))return e;if(!y(e))return e;if("string"==typeof n&&n.startsWith("$attached")){const t=n.replace("$attached.","");n=r.get(e.attached,t,null)}const o=e.instance;if(!o)return e;const a=t.replace(/-/g,".");let s,i=de[a]||a;for(let e=0;e<ue.length&&!s;e++){const t=[ue[e],i].filter(Boolean).join(".");s=s=r.get(o,t)}if(s&&r.isNumber(n)&&s.setScalar)s.setScalar(n);else if(s&&s.set){const e=Array.isArray(n)?n:[n];o[i].set(...e)}else"function"==typeof s?s.bind(e.instance)(...n):void 0!==r.get(o,i,void 0)?r.set(o,i,""===n||n):console.log(`No property ${i} found on ${o}`);const c=o?.texture?.type||o?.type;if("string"==typeof c){const e=c.toLowerCase();switch(!0){case e.includes("material"):o.needsUpdate=!0;break;case e.includes("camera")&&o.updateProjectionMatrix:o.updateProjectionMatrix()}}}({node:e,key:t,value:o})},remove:e=>{if(!e)return;const t=Object.keys(j),n=[];e.walk((e=>(n.push(e),!0))),n.forEach((e=>{const n=t.find((t=>j[t]?.uuid===e.uuid));if(n&&(j[n]=null),y(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(){}},fe={dpr:t.ref(1),inputActive:x,mousePos:L},ye=t.computed((()=>$.value?.instance??null));const ve=t.computed((()=>K.value?.instance??null));const ge=t.computed((()=>_.value.instance));let be=null,xe=null;e.camera=ye,e.clearCustomRender=()=>{be?be.clearCustomRender():xe=null},e.createApp=e=>{be=t.createRenderer(he).createApp(e),Object.keys(m).forEach((e=>{be.component(e,m[e])}));const{mount:n}=be;return be.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"});be.rootNode=r;return n(r,...t)},be.extend=e=>((({app:e,...t})=>{Object.keys(t).forEach((n=>{e.component(n,q(n)),l[n]=t[n]}))})({app:be,...e}),be),be.setCustomRender=e=>{be.customRender=e},xe&&(be.setCustomRender(xe),xe=null),be.clearCustomRender=()=>{be.customRender=null},be},e.find=function(e){return e=t.isRef(e)?e.value:e,y(e)?e?.instance:h(e)?e?.$el?.instance:t.isVNode(e)?e.el?.instance:null},e.globals=fe,e.offAfterRender=e=>{if(isFinite(e))ae.splice(e,1);else{const t=ae.findIndex((t=>t==e));ae.splice(t,1)}},e.offBeforeRender=e=>{if(isFinite(e))oe.splice(e,1);else{const t=oe.findIndex((t=>t==e));oe.splice(t,1)}},e.onAfterRender=(e,t=1/0)=>{t===1/0?ae.push(e):ae.splice(t,0,e)},e.onBeforeRender=ie,e.onStart=(e,t=1/0)=>{t===1/0?ne.push(e):ne.splice(t,0,e)},e.renderer=ve,e.scene=ge,e.setCustomRender=e=>{be?be.setCustomRender(e):xe=e},e.useCamera=function(e,n=!0){let r;r=t.watch(ye,(t=>{t&&(e(t),n&&r?.())}),{immediate:!0})},e.useRenderer=function(e,n=!0){let r;r=t.watch(ve,(t=>{t&&(e(t),n&&r?.())}),{immediate:!0})},e.useScene=function(e,n=!0){let r;r=t.watch(ge,(t=>{t&&(e(t),n&&r?.())}),{immediate:!0})},Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
@@ -90,6 +90,7 @@ const LunchboxWrapper = {
|
|
|
90
90
|
dpr: Number,
|
|
91
91
|
ortho: Boolean,
|
|
92
92
|
orthographic: Boolean,
|
|
93
|
+
rendererArguments: Object,
|
|
93
94
|
rendererProperties: Object,
|
|
94
95
|
shadow: [Boolean, Object],
|
|
95
96
|
transparent: Boolean,
|
|
@@ -119,12 +120,11 @@ const LunchboxWrapper = {
|
|
|
119
120
|
if (!renderer) {
|
|
120
121
|
// build renderer args
|
|
121
122
|
const rendererArgs = {
|
|
123
|
+
alpha: props.transparent,
|
|
122
124
|
antialias: true,
|
|
123
125
|
canvas: canvas.value.domElement,
|
|
126
|
+
...(props.rendererArguments ?? {}),
|
|
124
127
|
};
|
|
125
|
-
if (props.transparent) {
|
|
126
|
-
rendererArgs.alpha = true;
|
|
127
|
-
}
|
|
128
128
|
// create new renderer
|
|
129
129
|
ensureRenderer.value = createNode({
|
|
130
130
|
type: 'WebGLRenderer',
|
|
@@ -162,7 +162,6 @@ const LunchboxWrapper = {
|
|
|
162
162
|
// the user has initialized the renderer, so anything depending
|
|
163
163
|
// on the renderer can execute
|
|
164
164
|
rendererReady.value = true;
|
|
165
|
-
return;
|
|
166
165
|
}
|
|
167
166
|
// CAMERA
|
|
168
167
|
// ====================
|
|
@@ -196,14 +195,17 @@ const LunchboxWrapper = {
|
|
|
196
195
|
else {
|
|
197
196
|
cameraReady.value = true;
|
|
198
197
|
}
|
|
198
|
+
if (!camera.instance) {
|
|
199
|
+
throw new Error('Error creating camera.');
|
|
200
|
+
}
|
|
199
201
|
// move camera if needed
|
|
200
202
|
if (camera && props.cameraPosition) {
|
|
201
|
-
camera.instance
|
|
203
|
+
camera.instance.position.set(...props.cameraPosition);
|
|
202
204
|
}
|
|
203
205
|
// angle camera if needed
|
|
204
206
|
if (camera && (props.cameraLookAt || props.cameraLook)) {
|
|
205
207
|
const source = (props.cameraLookAt || props.cameraLook);
|
|
206
|
-
camera.instance
|
|
208
|
+
camera.instance.lookAt(...source);
|
|
207
209
|
}
|
|
208
210
|
// SCENE
|
|
209
211
|
// ====================
|
|
@@ -226,11 +228,23 @@ const LunchboxWrapper = {
|
|
|
226
228
|
else {
|
|
227
229
|
throw new Error('missing renderer');
|
|
228
230
|
}
|
|
231
|
+
// CALLBACK PREP
|
|
232
|
+
// ====================
|
|
233
|
+
const app = getCurrentInstance().appContext.app;
|
|
234
|
+
// START
|
|
235
|
+
// ====================
|
|
236
|
+
for (let startCallback of startCallbacks) {
|
|
237
|
+
startCallback({
|
|
238
|
+
app,
|
|
239
|
+
camera: camera.instance,
|
|
240
|
+
renderer: renderer.instance,
|
|
241
|
+
scene: scene.instance,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
229
244
|
// KICK UPDATE
|
|
230
245
|
// ====================
|
|
231
|
-
// console.log(scene)
|
|
232
246
|
update({
|
|
233
|
-
app
|
|
247
|
+
app,
|
|
234
248
|
camera: camera.instance,
|
|
235
249
|
renderer: renderer.instance,
|
|
236
250
|
scene: scene.instance,
|
|
@@ -607,7 +621,6 @@ function addEventListener({ node, key, value, }) {
|
|
|
607
621
|
// register click, pointerdown, pointerup
|
|
608
622
|
if (key === 'onClick' || key === 'onPointerDown' || key === 'onPointerUp') {
|
|
609
623
|
const stop = watch(() => inputActive.value, (isDown) => {
|
|
610
|
-
console.log(isDown, currentIntersections);
|
|
611
624
|
const idx = currentIntersections
|
|
612
625
|
.map((v) => v.element)
|
|
613
626
|
.findIndex((v) => v.instance &&
|
|
@@ -1240,6 +1253,16 @@ var MiniDom;
|
|
|
1240
1253
|
const rootNode = new MiniDom.RendererRootNode();
|
|
1241
1254
|
rootNode.minidomType = 'RootNode';
|
|
1242
1255
|
|
|
1256
|
+
const startCallbacks = [];
|
|
1257
|
+
const onStart = (cb, index = Infinity) => {
|
|
1258
|
+
if (index === Infinity) {
|
|
1259
|
+
startCallbacks.push(cb);
|
|
1260
|
+
}
|
|
1261
|
+
else {
|
|
1262
|
+
startCallbacks.splice(index, 0, cb);
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
|
|
1243
1266
|
let frameID;
|
|
1244
1267
|
const beforeRender = [];
|
|
1245
1268
|
const afterRender = [];
|
|
@@ -1662,9 +1685,51 @@ const globals = {
|
|
|
1662
1685
|
inputActive,
|
|
1663
1686
|
mousePos,
|
|
1664
1687
|
};
|
|
1688
|
+
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
1665
1689
|
const camera = computed(() => ensuredCamera.value?.instance ?? null);
|
|
1690
|
+
/** Run a function using the current camera when it's present. */
|
|
1691
|
+
function useCamera(callback, once = true) {
|
|
1692
|
+
let destroy;
|
|
1693
|
+
destroy = watch(camera, (newVal) => {
|
|
1694
|
+
if (!newVal)
|
|
1695
|
+
return;
|
|
1696
|
+
// TODO: better fix than `any`?
|
|
1697
|
+
callback(newVal);
|
|
1698
|
+
if (once) {
|
|
1699
|
+
destroy?.();
|
|
1700
|
+
}
|
|
1701
|
+
}, { immediate: true });
|
|
1702
|
+
}
|
|
1703
|
+
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
1666
1704
|
const renderer = computed(() => ensureRenderer.value?.instance ?? null);
|
|
1705
|
+
/** Run a function using the current renderer when it's present. */
|
|
1706
|
+
function useRenderer(callback, once = true) {
|
|
1707
|
+
let destroy;
|
|
1708
|
+
destroy = watch(renderer, (newVal) => {
|
|
1709
|
+
if (!newVal)
|
|
1710
|
+
return;
|
|
1711
|
+
// TODO: better fix than `any`?
|
|
1712
|
+
callback(newVal);
|
|
1713
|
+
if (once) {
|
|
1714
|
+
destroy?.();
|
|
1715
|
+
}
|
|
1716
|
+
}, { immediate: true });
|
|
1717
|
+
}
|
|
1718
|
+
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
1667
1719
|
const scene = computed(() => ensuredScene.value.instance);
|
|
1720
|
+
/** Run a function using the current scene when it's present. */
|
|
1721
|
+
function useScene(callback, once = true) {
|
|
1722
|
+
let destroy;
|
|
1723
|
+
destroy = watch(scene, (newVal) => {
|
|
1724
|
+
if (!newVal)
|
|
1725
|
+
return;
|
|
1726
|
+
// TODO: better fix than `any`?
|
|
1727
|
+
callback(newVal);
|
|
1728
|
+
if (once) {
|
|
1729
|
+
destroy?.();
|
|
1730
|
+
}
|
|
1731
|
+
}, { immediate: true });
|
|
1732
|
+
}
|
|
1668
1733
|
// CUSTOM RENDER SUPPORT
|
|
1669
1734
|
// ====================
|
|
1670
1735
|
let app = null;
|
|
@@ -1731,4 +1796,4 @@ const createApp = (root) => {
|
|
|
1731
1796
|
return app;
|
|
1732
1797
|
};
|
|
1733
1798
|
|
|
1734
|
-
export { camera, clearCustomRender, createApp, find, globals, lunchboxRootNode as lunchboxTree, offAfterRender, offBeforeRender, onAfterRender, onBeforeRender, renderer, scene, setCustomRender };
|
|
1799
|
+
export { camera, clearCustomRender, createApp, find, globals, lunchboxRootNode as lunchboxTree, offAfterRender, offBeforeRender, onAfterRender, onBeforeRender, onStart, renderer, scene, setCustomRender, useCamera, useRenderer, useScene };
|
package/package.json
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
fallbackRendererUuid,
|
|
19
19
|
MiniDom,
|
|
20
20
|
rendererReady,
|
|
21
|
+
startCallbacks,
|
|
21
22
|
tryGetNodeWithInstanceType,
|
|
22
23
|
update,
|
|
23
24
|
} from '../../core'
|
|
@@ -51,6 +52,7 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
51
52
|
dpr: Number,
|
|
52
53
|
ortho: Boolean,
|
|
53
54
|
orthographic: Boolean,
|
|
55
|
+
rendererArguments: Object,
|
|
54
56
|
rendererProperties: Object,
|
|
55
57
|
shadow: [Boolean, Object],
|
|
56
58
|
transparent: Boolean,
|
|
@@ -82,11 +84,10 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
82
84
|
if (!renderer) {
|
|
83
85
|
// build renderer args
|
|
84
86
|
const rendererArgs: THREE.WebGLRendererParameters = {
|
|
87
|
+
alpha: props.transparent,
|
|
85
88
|
antialias: true,
|
|
86
89
|
canvas: canvas.value.domElement,
|
|
87
|
-
|
|
88
|
-
if (props.transparent) {
|
|
89
|
-
rendererArgs.alpha = true
|
|
90
|
+
...(props.rendererArguments ?? {}),
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
// create new renderer
|
|
@@ -137,7 +138,6 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
137
138
|
// the user has initialized the renderer, so anything depending
|
|
138
139
|
// on the renderer can execute
|
|
139
140
|
rendererReady.value = true
|
|
140
|
-
return
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
// CAMERA
|
|
@@ -172,14 +172,17 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
172
172
|
} else {
|
|
173
173
|
cameraReady.value = true
|
|
174
174
|
}
|
|
175
|
+
if (!camera.instance) {
|
|
176
|
+
throw new Error('Error creating camera.')
|
|
177
|
+
}
|
|
175
178
|
// move camera if needed
|
|
176
179
|
if (camera && props.cameraPosition) {
|
|
177
|
-
camera.instance
|
|
180
|
+
camera.instance.position.set(...props.cameraPosition)
|
|
178
181
|
}
|
|
179
182
|
// angle camera if needed
|
|
180
183
|
if (camera && (props.cameraLookAt || props.cameraLook)) {
|
|
181
184
|
const source = (props.cameraLookAt || props.cameraLook)!
|
|
182
|
-
camera.instance
|
|
185
|
+
camera.instance.lookAt(...source)
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
// SCENE
|
|
@@ -209,11 +212,25 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
209
212
|
throw new Error('missing renderer')
|
|
210
213
|
}
|
|
211
214
|
|
|
215
|
+
// CALLBACK PREP
|
|
216
|
+
// ====================
|
|
217
|
+
const app = getCurrentInstance()!.appContext.app as Lunch.App
|
|
218
|
+
|
|
219
|
+
// START
|
|
220
|
+
// ====================
|
|
221
|
+
for (let startCallback of startCallbacks) {
|
|
222
|
+
startCallback({
|
|
223
|
+
app,
|
|
224
|
+
camera: camera.instance,
|
|
225
|
+
renderer: renderer.instance,
|
|
226
|
+
scene: scene.instance,
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
|
|
212
230
|
// KICK UPDATE
|
|
213
231
|
// ====================
|
|
214
|
-
// console.log(scene)
|
|
215
232
|
update({
|
|
216
|
-
app
|
|
233
|
+
app,
|
|
217
234
|
camera: camera.instance,
|
|
218
235
|
renderer: renderer.instance,
|
|
219
236
|
scene: scene.instance,
|
package/src/core/index.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Lunch } from '..'
|
|
2
|
+
|
|
3
|
+
export const startCallbacks = [] as Lunch.UpdateCallback[]
|
|
4
|
+
|
|
5
|
+
export const onStart = (cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
6
|
+
if (index === Infinity) {
|
|
7
|
+
startCallbacks.push(cb)
|
|
8
|
+
} else {
|
|
9
|
+
startCallbacks.splice(index, 0, cb)
|
|
10
|
+
}
|
|
11
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
createRenderer,
|
|
4
|
+
Component,
|
|
5
|
+
ref,
|
|
6
|
+
watch,
|
|
7
|
+
WatchStopHandle,
|
|
8
|
+
} from 'vue'
|
|
2
9
|
import { nodeOps } from './nodeOps'
|
|
3
10
|
import {
|
|
4
11
|
// createdCamera,
|
|
@@ -20,8 +27,9 @@ export { lunchboxRootNode as lunchboxTree } from './core'
|
|
|
20
27
|
export {
|
|
21
28
|
offAfterRender,
|
|
22
29
|
offBeforeRender,
|
|
23
|
-
onBeforeRender,
|
|
24
30
|
onAfterRender,
|
|
31
|
+
onBeforeRender,
|
|
32
|
+
onStart,
|
|
25
33
|
} from './core'
|
|
26
34
|
export * from './types'
|
|
27
35
|
|
|
@@ -35,9 +43,74 @@ export const globals = {
|
|
|
35
43
|
mousePos,
|
|
36
44
|
}
|
|
37
45
|
|
|
46
|
+
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
38
47
|
export const camera = computed(() => ensuredCamera.value?.instance ?? null)
|
|
48
|
+
/** Run a function using the current camera when it's present. */
|
|
49
|
+
export function useCamera<T extends THREE.Camera = THREE.PerspectiveCamera>(
|
|
50
|
+
callback: (cam: T) => void,
|
|
51
|
+
once = true
|
|
52
|
+
) {
|
|
53
|
+
let destroy: WatchStopHandle
|
|
54
|
+
destroy = watch(
|
|
55
|
+
camera,
|
|
56
|
+
(newVal) => {
|
|
57
|
+
if (!newVal) return
|
|
58
|
+
|
|
59
|
+
// TODO: better fix than `any`?
|
|
60
|
+
callback(newVal as any)
|
|
61
|
+
if (once) {
|
|
62
|
+
destroy?.()
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{ immediate: true }
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
39
70
|
export const renderer = computed(() => ensureRenderer.value?.instance ?? null)
|
|
71
|
+
/** Run a function using the current renderer when it's present. */
|
|
72
|
+
export function useRenderer<T extends THREE.Renderer = THREE.WebGLRenderer>(
|
|
73
|
+
callback: (rend: T) => void,
|
|
74
|
+
once = true
|
|
75
|
+
) {
|
|
76
|
+
let destroy: WatchStopHandle
|
|
77
|
+
destroy = watch(
|
|
78
|
+
renderer,
|
|
79
|
+
(newVal) => {
|
|
80
|
+
if (!newVal) return
|
|
81
|
+
|
|
82
|
+
// TODO: better fix than `any`?
|
|
83
|
+
callback(newVal as any)
|
|
84
|
+
if (once) {
|
|
85
|
+
destroy?.()
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{ immediate: true }
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
40
93
|
export const scene = computed(() => ensuredScene.value.instance)
|
|
94
|
+
/** Run a function using the current scene when it's present. */
|
|
95
|
+
export function useScene(
|
|
96
|
+
callback: (newScene: THREE.Scene) => void,
|
|
97
|
+
once = true
|
|
98
|
+
) {
|
|
99
|
+
let destroy: WatchStopHandle
|
|
100
|
+
destroy = watch(
|
|
101
|
+
scene,
|
|
102
|
+
(newVal) => {
|
|
103
|
+
if (!newVal) return
|
|
104
|
+
|
|
105
|
+
// TODO: better fix than `any`?
|
|
106
|
+
callback(newVal as any)
|
|
107
|
+
if (once) {
|
|
108
|
+
destroy?.()
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{ immediate: true }
|
|
112
|
+
)
|
|
113
|
+
}
|
|
41
114
|
|
|
42
115
|
// CUSTOM RENDER SUPPORT
|
|
43
116
|
// ====================
|
package/src/types.ts
CHANGED
|
@@ -145,6 +145,8 @@ export declare namespace Lunch {
|
|
|
145
145
|
dpr?: number
|
|
146
146
|
ortho?: boolean
|
|
147
147
|
orthographic?: boolean
|
|
148
|
+
// TODO: Why doesn't ConstructorParameters<THREE.WebGLRenderer> work here?
|
|
149
|
+
rendererArguments?: object
|
|
148
150
|
rendererProperties?: Partial<THREE.WebGLRenderer>
|
|
149
151
|
shadow?: ShadowSugar
|
|
150
152
|
transparent?: boolean
|