lunchboxjs 0.1.4005 → 0.1.4011
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 +106 -20
- package/dist/lunchboxjs.min.js +1 -1
- package/dist/lunchboxjs.module.js +103 -21
- package/package.json +1 -1
- package/src/components/LunchboxWrapper/LunchboxWrapper.ts +25 -8
- package/src/components/index.ts +11 -6
- package/src/core/ensure.ts +9 -1
- package/src/core/extend.ts +10 -4
- package/src/core/index.ts +2 -1
- package/src/core/start.ts +11 -0
- package/src/core/updateObjectProp.ts +13 -6
- package/src/index.ts +75 -2
- package/src/types.ts +2 -0
- package/src/utils/index.ts +7 -3
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,
|
|
@@ -456,15 +470,20 @@
|
|
|
456
470
|
inheritAttrs: false,
|
|
457
471
|
name: tag,
|
|
458
472
|
setup(props, context) {
|
|
459
|
-
return () =>
|
|
473
|
+
return () => {
|
|
474
|
+
return vue.h(tag, context.attrs, context.slots?.default?.() || []);
|
|
475
|
+
};
|
|
460
476
|
},
|
|
461
477
|
});
|
|
462
|
-
|
|
478
|
+
// turn components into registered map
|
|
479
|
+
const processed = autoGeneratedComponents
|
|
480
|
+
.map(createComponent$1)
|
|
481
|
+
.reduce((acc, curr) => {
|
|
463
482
|
acc[curr.name] = curr;
|
|
464
483
|
return acc;
|
|
465
|
-
});
|
|
484
|
+
}, {});
|
|
466
485
|
const components = {
|
|
467
|
-
...
|
|
486
|
+
...processed,
|
|
468
487
|
Lunchbox: LunchboxWrapper,
|
|
469
488
|
};
|
|
470
489
|
|
|
@@ -819,6 +838,11 @@
|
|
|
819
838
|
const found = autoCreated[singleType] ||
|
|
820
839
|
allNodes.find((node) => node.type?.toLowerCase() ===
|
|
821
840
|
singleType.toLowerCase());
|
|
841
|
+
// cancel if found example is marked !isDefault
|
|
842
|
+
if (isMinidomNode(found) &&
|
|
843
|
+
(!found.props['is-default'] || !found.props['isDefault'])) {
|
|
844
|
+
return null;
|
|
845
|
+
}
|
|
822
846
|
// if we have one, save and return
|
|
823
847
|
if (found) {
|
|
824
848
|
const createdAsNode = found;
|
|
@@ -950,10 +974,10 @@
|
|
|
950
974
|
name: tag,
|
|
951
975
|
render() {
|
|
952
976
|
return vue.h(tag, this.$attrs, this.$slots?.default?.() || []);
|
|
953
|
-
}
|
|
977
|
+
},
|
|
954
978
|
});
|
|
955
979
|
const extend = ({ app, ...targets }) => {
|
|
956
|
-
Object.keys(targets).forEach(key => {
|
|
980
|
+
Object.keys(targets).forEach((key) => {
|
|
957
981
|
app.component(key, createComponent(key));
|
|
958
982
|
catalogue[key] = targets[key];
|
|
959
983
|
});
|
|
@@ -1257,9 +1281,22 @@
|
|
|
1257
1281
|
}
|
|
1258
1282
|
MiniDom.RendererStandardNode = RendererStandardNode;
|
|
1259
1283
|
})(MiniDom || (MiniDom = {}));
|
|
1284
|
+
function isMinidomNode(item) {
|
|
1285
|
+
return item?.minidomType === 'RendererNode';
|
|
1286
|
+
}
|
|
1260
1287
|
const rootNode = new MiniDom.RendererRootNode();
|
|
1261
1288
|
rootNode.minidomType = 'RootNode';
|
|
1262
1289
|
|
|
1290
|
+
const startCallbacks = [];
|
|
1291
|
+
const onStart = (cb, index = Infinity) => {
|
|
1292
|
+
if (index === Infinity) {
|
|
1293
|
+
startCallbacks.push(cb);
|
|
1294
|
+
}
|
|
1295
|
+
else {
|
|
1296
|
+
startCallbacks.splice(index, 0, cb);
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
|
|
1263
1300
|
let frameID;
|
|
1264
1301
|
const beforeRender = [];
|
|
1265
1302
|
const afterRender = [];
|
|
@@ -1341,8 +1378,13 @@
|
|
|
1341
1378
|
if (isEventKey(key)) {
|
|
1342
1379
|
return addEventListener({ node, key, value });
|
|
1343
1380
|
}
|
|
1381
|
+
// update THREE property
|
|
1382
|
+
// get final key
|
|
1383
|
+
const camelKey = key.replace(/-/g, '.');
|
|
1384
|
+
const finalKey = propertyShortcuts[camelKey] || camelKey;
|
|
1344
1385
|
// handle and return early if prop is specific to Vue/Lunchbox
|
|
1345
|
-
if (internalLunchboxVueKeys.includes(key)
|
|
1386
|
+
if (internalLunchboxVueKeys.includes(key) ||
|
|
1387
|
+
internalLunchboxVueKeys.includes(finalKey))
|
|
1346
1388
|
return node;
|
|
1347
1389
|
// everything else should be Three-specific, so let's cancel if this isn't a standard node
|
|
1348
1390
|
if (!isLunchboxStandardNode(node))
|
|
@@ -1357,12 +1399,8 @@
|
|
|
1357
1399
|
// cancel if no target
|
|
1358
1400
|
if (!target)
|
|
1359
1401
|
return node;
|
|
1360
|
-
// update THREE property
|
|
1361
|
-
// get final key
|
|
1362
|
-
const camelKey = key.replace(/-/g, '.');
|
|
1363
|
-
let finalKey = propertyShortcuts[camelKey] || camelKey;
|
|
1364
|
-
let liveProperty;
|
|
1365
1402
|
// burrow down until we get property to change
|
|
1403
|
+
let liveProperty;
|
|
1366
1404
|
for (let i = 0; i < nestedPropertiesToCheck.length && !liveProperty; i++) {
|
|
1367
1405
|
const nestedProperty = nestedPropertiesToCheck[i];
|
|
1368
1406
|
const fullPath = [nestedProperty, finalKey].filter(Boolean).join('.');
|
|
@@ -1427,6 +1465,8 @@
|
|
|
1427
1465
|
'args',
|
|
1428
1466
|
'attach',
|
|
1429
1467
|
'attachArray',
|
|
1468
|
+
'is.default',
|
|
1469
|
+
'isDefault',
|
|
1430
1470
|
'key',
|
|
1431
1471
|
'onAdded',
|
|
1432
1472
|
// 'onReady',
|
|
@@ -1682,9 +1722,51 @@
|
|
|
1682
1722
|
inputActive,
|
|
1683
1723
|
mousePos,
|
|
1684
1724
|
};
|
|
1725
|
+
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
1685
1726
|
const camera = vue.computed(() => ensuredCamera.value?.instance ?? null);
|
|
1727
|
+
/** Run a function using the current camera when it's present. */
|
|
1728
|
+
function useCamera(callback, once = true) {
|
|
1729
|
+
let destroy;
|
|
1730
|
+
destroy = vue.watch(camera, (newVal) => {
|
|
1731
|
+
if (!newVal)
|
|
1732
|
+
return;
|
|
1733
|
+
// TODO: better fix than `any`?
|
|
1734
|
+
callback(newVal);
|
|
1735
|
+
if (once) {
|
|
1736
|
+
destroy?.();
|
|
1737
|
+
}
|
|
1738
|
+
}, { immediate: true });
|
|
1739
|
+
}
|
|
1740
|
+
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
1686
1741
|
const renderer = vue.computed(() => ensureRenderer.value?.instance ?? null);
|
|
1742
|
+
/** Run a function using the current renderer when it's present. */
|
|
1743
|
+
function useRenderer(callback, once = true) {
|
|
1744
|
+
let destroy;
|
|
1745
|
+
destroy = vue.watch(renderer, (newVal) => {
|
|
1746
|
+
if (!newVal)
|
|
1747
|
+
return;
|
|
1748
|
+
// TODO: better fix than `any`?
|
|
1749
|
+
callback(newVal);
|
|
1750
|
+
if (once) {
|
|
1751
|
+
destroy?.();
|
|
1752
|
+
}
|
|
1753
|
+
}, { immediate: true });
|
|
1754
|
+
}
|
|
1755
|
+
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
1687
1756
|
const scene = vue.computed(() => ensuredScene.value.instance);
|
|
1757
|
+
/** Run a function using the current scene when it's present. */
|
|
1758
|
+
function useScene(callback, once = true) {
|
|
1759
|
+
let destroy;
|
|
1760
|
+
destroy = vue.watch(scene, (newVal) => {
|
|
1761
|
+
if (!newVal)
|
|
1762
|
+
return;
|
|
1763
|
+
// TODO: better fix than `any`?
|
|
1764
|
+
callback(newVal);
|
|
1765
|
+
if (once) {
|
|
1766
|
+
destroy?.();
|
|
1767
|
+
}
|
|
1768
|
+
}, { immediate: true });
|
|
1769
|
+
}
|
|
1688
1770
|
// CUSTOM RENDER SUPPORT
|
|
1689
1771
|
// ====================
|
|
1690
1772
|
let app = null;
|
|
@@ -1760,9 +1842,13 @@
|
|
|
1760
1842
|
exports.offBeforeRender = offBeforeRender;
|
|
1761
1843
|
exports.onAfterRender = onAfterRender;
|
|
1762
1844
|
exports.onBeforeRender = onBeforeRender;
|
|
1845
|
+
exports.onStart = onStart;
|
|
1763
1846
|
exports.renderer = renderer;
|
|
1764
1847
|
exports.scene = scene;
|
|
1765
1848
|
exports.setCustomRender = setCustomRender;
|
|
1849
|
+
exports.useCamera = useCamera;
|
|
1850
|
+
exports.useRenderer = useRenderer;
|
|
1851
|
+
exports.useScene = useScene;
|
|
1766
1852
|
|
|
1767
1853
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1768
1854
|
|
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=>{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=I.value?.instance,o=K.value.instance,a=F.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=G(["WebGLRenderer"]),l)s.value=!1,W.value=!0;else{const t={alpha:e.transparent,antialias:!0,canvas:a.value.domElement,...e.rendererArguments??{}};I.value=v({type:"WebGLRenderer",uuid:$,props:{args:[t]}}),W.value=!0;const n=I,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=G(["PerspectiveCamera","OrthographicCamera"]),p?D.value=!0:(e.ortho||e.orthographic?F.value=v({props:{args:e.cameraArgs??[]},type:"OrthographicCamera",uuid:k}):F.value=v({props:{args:e.cameraArgs??[45,.5625,1,1e3]},type:"PerspectiveCamera",uuid:k}),D.value=!0,p=F.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=K.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);const o=t.getCurrentInstance().appContext.app;for(let e of te)e({app:o,camera:p.instance,renderer:l.instance,scene:m.instance});ae({app:o,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={},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;function v(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&&(K.value=r),r}const g=[],b=t.ref(!1);function x({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),R.includes(n)&&(_.value,e.instance&&!g.includes(e)&&(o=e,g.push(o),e.eventListenerRemoveFunctions[n].push((()=>(e=>{const t=g.indexOf(e);-1!==t&&g.splice(t,1)})(e))))),"onClick"===n||"onPointerDown"===n||"onPointerUp"===n){const r=t.watch((()=>b.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 R=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"];let w,A,C;const E=t.ref({x:1/0,y:1/0});let L=!1;let P=[];const M=()=>{const e=_.value?.instance,t=F.value?.instance;if(!e||!t)return;e.setFromCamera(he.mousePos.value,t);const n=e.intersectObjects(g.map((e=>e.instance)));let r=[],o=[],a=[];r=P.map((e=>e.intersection)),n?.forEach((e=>{const t=P.findIndex((t=>t.intersection.object===e.object));if(-1===t){const t=g.find((t=>t.instance?.uuid===e.object.uuid));t&&o.push({element:t,intersection:e})}else{const t=g.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:g.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 J.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||e.props["is-default"]&&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=v({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]}),D=t.ref(!1),F=t.computed({get:()=>D.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}}),K=j("Scene","FALLBACK_SCENE"),_=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)/he.dpr.value,r=(e.instance.domElement.height??1)/he.dpr.value;E.value.x=t.offsetX/n*2-1,E.value.y=-t.offsetY/r*2+1},A=()=>b.value=!0,C=()=>b.value=!1,e.instance.domElement.addEventListener("mousemove",w),e.instance.domElement.addEventListener("mousedown",A),e.instance.domElement.addEventListener("mouseup",C),se(M),L=!0),n&&n())}),{immediate:!0})})(e))),V=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}});var q,z=new Uint8Array(16);function H(){if(!q&&!(q="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 q(z)}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:I.value?.instance,scene:K.value.instance,camera:F.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=v(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??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=K.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 x({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(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(){}},he={dpr:t.ref(1),inputActive:b,mousePos:E},fe=t.computed((()=>F.value?.instance??null));const ye=t.computed((()=>I.value?.instance??null));const ve=t.computed((()=>K.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=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,V(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,n=!0){let r;r=t.watch(fe,(t=>{t&&(e(t),n&&r?.())}),{immediate:!0})},e.useRenderer=function(e,n=!0){let r;r=t.watch(ye,(t=>{t&&(e(t),n&&r?.())}),{immediate:!0})},e.useScene=function(e,n=!0){let r;r=t.watch(ve,(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,
|
|
@@ -435,15 +449,20 @@ const createComponent$1 = (tag) => defineComponent({
|
|
|
435
449
|
inheritAttrs: false,
|
|
436
450
|
name: tag,
|
|
437
451
|
setup(props, context) {
|
|
438
|
-
return () =>
|
|
452
|
+
return () => {
|
|
453
|
+
return h(tag, context.attrs, context.slots?.default?.() || []);
|
|
454
|
+
};
|
|
439
455
|
},
|
|
440
456
|
});
|
|
441
|
-
|
|
457
|
+
// turn components into registered map
|
|
458
|
+
const processed = autoGeneratedComponents
|
|
459
|
+
.map(createComponent$1)
|
|
460
|
+
.reduce((acc, curr) => {
|
|
442
461
|
acc[curr.name] = curr;
|
|
443
462
|
return acc;
|
|
444
|
-
});
|
|
463
|
+
}, {});
|
|
445
464
|
const components = {
|
|
446
|
-
...
|
|
465
|
+
...processed,
|
|
447
466
|
Lunchbox: LunchboxWrapper,
|
|
448
467
|
};
|
|
449
468
|
|
|
@@ -798,6 +817,11 @@ function tryGetNodeWithInstanceType(pascalCaseTypes) {
|
|
|
798
817
|
const found = autoCreated[singleType] ||
|
|
799
818
|
allNodes.find((node) => node.type?.toLowerCase() ===
|
|
800
819
|
singleType.toLowerCase());
|
|
820
|
+
// cancel if found example is marked !isDefault
|
|
821
|
+
if (isMinidomNode(found) &&
|
|
822
|
+
(!found.props['is-default'] || !found.props['isDefault'])) {
|
|
823
|
+
return null;
|
|
824
|
+
}
|
|
801
825
|
// if we have one, save and return
|
|
802
826
|
if (found) {
|
|
803
827
|
const createdAsNode = found;
|
|
@@ -929,10 +953,10 @@ const createComponent = (tag) => defineComponent({
|
|
|
929
953
|
name: tag,
|
|
930
954
|
render() {
|
|
931
955
|
return h(tag, this.$attrs, this.$slots?.default?.() || []);
|
|
932
|
-
}
|
|
956
|
+
},
|
|
933
957
|
});
|
|
934
958
|
const extend = ({ app, ...targets }) => {
|
|
935
|
-
Object.keys(targets).forEach(key => {
|
|
959
|
+
Object.keys(targets).forEach((key) => {
|
|
936
960
|
app.component(key, createComponent(key));
|
|
937
961
|
catalogue[key] = targets[key];
|
|
938
962
|
});
|
|
@@ -1236,9 +1260,22 @@ var MiniDom;
|
|
|
1236
1260
|
}
|
|
1237
1261
|
MiniDom.RendererStandardNode = RendererStandardNode;
|
|
1238
1262
|
})(MiniDom || (MiniDom = {}));
|
|
1263
|
+
function isMinidomNode(item) {
|
|
1264
|
+
return item?.minidomType === 'RendererNode';
|
|
1265
|
+
}
|
|
1239
1266
|
const rootNode = new MiniDom.RendererRootNode();
|
|
1240
1267
|
rootNode.minidomType = 'RootNode';
|
|
1241
1268
|
|
|
1269
|
+
const startCallbacks = [];
|
|
1270
|
+
const onStart = (cb, index = Infinity) => {
|
|
1271
|
+
if (index === Infinity) {
|
|
1272
|
+
startCallbacks.push(cb);
|
|
1273
|
+
}
|
|
1274
|
+
else {
|
|
1275
|
+
startCallbacks.splice(index, 0, cb);
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
|
|
1242
1279
|
let frameID;
|
|
1243
1280
|
const beforeRender = [];
|
|
1244
1281
|
const afterRender = [];
|
|
@@ -1320,8 +1357,13 @@ function updateObjectProp({ node, key, value, }) {
|
|
|
1320
1357
|
if (isEventKey(key)) {
|
|
1321
1358
|
return addEventListener({ node, key, value });
|
|
1322
1359
|
}
|
|
1360
|
+
// update THREE property
|
|
1361
|
+
// get final key
|
|
1362
|
+
const camelKey = key.replace(/-/g, '.');
|
|
1363
|
+
const finalKey = propertyShortcuts[camelKey] || camelKey;
|
|
1323
1364
|
// handle and return early if prop is specific to Vue/Lunchbox
|
|
1324
|
-
if (internalLunchboxVueKeys.includes(key)
|
|
1365
|
+
if (internalLunchboxVueKeys.includes(key) ||
|
|
1366
|
+
internalLunchboxVueKeys.includes(finalKey))
|
|
1325
1367
|
return node;
|
|
1326
1368
|
// everything else should be Three-specific, so let's cancel if this isn't a standard node
|
|
1327
1369
|
if (!isLunchboxStandardNode(node))
|
|
@@ -1336,12 +1378,8 @@ function updateObjectProp({ node, key, value, }) {
|
|
|
1336
1378
|
// cancel if no target
|
|
1337
1379
|
if (!target)
|
|
1338
1380
|
return node;
|
|
1339
|
-
// update THREE property
|
|
1340
|
-
// get final key
|
|
1341
|
-
const camelKey = key.replace(/-/g, '.');
|
|
1342
|
-
let finalKey = propertyShortcuts[camelKey] || camelKey;
|
|
1343
|
-
let liveProperty;
|
|
1344
1381
|
// burrow down until we get property to change
|
|
1382
|
+
let liveProperty;
|
|
1345
1383
|
for (let i = 0; i < nestedPropertiesToCheck.length && !liveProperty; i++) {
|
|
1346
1384
|
const nestedProperty = nestedPropertiesToCheck[i];
|
|
1347
1385
|
const fullPath = [nestedProperty, finalKey].filter(Boolean).join('.');
|
|
@@ -1406,6 +1444,8 @@ const internalLunchboxVueKeys = [
|
|
|
1406
1444
|
'args',
|
|
1407
1445
|
'attach',
|
|
1408
1446
|
'attachArray',
|
|
1447
|
+
'is.default',
|
|
1448
|
+
'isDefault',
|
|
1409
1449
|
'key',
|
|
1410
1450
|
'onAdded',
|
|
1411
1451
|
// 'onReady',
|
|
@@ -1661,9 +1701,51 @@ const globals = {
|
|
|
1661
1701
|
inputActive,
|
|
1662
1702
|
mousePos,
|
|
1663
1703
|
};
|
|
1704
|
+
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
1664
1705
|
const camera = computed(() => ensuredCamera.value?.instance ?? null);
|
|
1706
|
+
/** Run a function using the current camera when it's present. */
|
|
1707
|
+
function useCamera(callback, once = true) {
|
|
1708
|
+
let destroy;
|
|
1709
|
+
destroy = watch(camera, (newVal) => {
|
|
1710
|
+
if (!newVal)
|
|
1711
|
+
return;
|
|
1712
|
+
// TODO: better fix than `any`?
|
|
1713
|
+
callback(newVal);
|
|
1714
|
+
if (once) {
|
|
1715
|
+
destroy?.();
|
|
1716
|
+
}
|
|
1717
|
+
}, { immediate: true });
|
|
1718
|
+
}
|
|
1719
|
+
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
1665
1720
|
const renderer = computed(() => ensureRenderer.value?.instance ?? null);
|
|
1721
|
+
/** Run a function using the current renderer when it's present. */
|
|
1722
|
+
function useRenderer(callback, once = true) {
|
|
1723
|
+
let destroy;
|
|
1724
|
+
destroy = watch(renderer, (newVal) => {
|
|
1725
|
+
if (!newVal)
|
|
1726
|
+
return;
|
|
1727
|
+
// TODO: better fix than `any`?
|
|
1728
|
+
callback(newVal);
|
|
1729
|
+
if (once) {
|
|
1730
|
+
destroy?.();
|
|
1731
|
+
}
|
|
1732
|
+
}, { immediate: true });
|
|
1733
|
+
}
|
|
1734
|
+
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
1666
1735
|
const scene = computed(() => ensuredScene.value.instance);
|
|
1736
|
+
/** Run a function using the current scene when it's present. */
|
|
1737
|
+
function useScene(callback, once = true) {
|
|
1738
|
+
let destroy;
|
|
1739
|
+
destroy = watch(scene, (newVal) => {
|
|
1740
|
+
if (!newVal)
|
|
1741
|
+
return;
|
|
1742
|
+
// TODO: better fix than `any`?
|
|
1743
|
+
callback(newVal);
|
|
1744
|
+
if (once) {
|
|
1745
|
+
destroy?.();
|
|
1746
|
+
}
|
|
1747
|
+
}, { immediate: true });
|
|
1748
|
+
}
|
|
1667
1749
|
// CUSTOM RENDER SUPPORT
|
|
1668
1750
|
// ====================
|
|
1669
1751
|
let app = null;
|
|
@@ -1730,4 +1812,4 @@ const createApp = (root) => {
|
|
|
1730
1812
|
return app;
|
|
1731
1813
|
};
|
|
1732
1814
|
|
|
1733
|
-
export { camera, clearCustomRender, createApp, find, globals, lunchboxRootNode as lunchboxTree, offAfterRender, offBeforeRender, onAfterRender, onBeforeRender, renderer, scene, setCustomRender };
|
|
1815
|
+
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/components/index.ts
CHANGED
|
@@ -13,16 +13,21 @@ const createComponent = (tag: string) =>
|
|
|
13
13
|
inheritAttrs: false,
|
|
14
14
|
name: tag,
|
|
15
15
|
setup(props, context) {
|
|
16
|
-
return () =>
|
|
16
|
+
return () => {
|
|
17
|
+
return h(tag, context.attrs, context.slots?.default?.() || [])
|
|
18
|
+
}
|
|
17
19
|
},
|
|
18
20
|
})
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
// turn components into registered map
|
|
23
|
+
const processed = autoGeneratedComponents
|
|
24
|
+
.map(createComponent)
|
|
25
|
+
.reduce((acc, curr) => {
|
|
26
|
+
acc[curr.name] = curr
|
|
27
|
+
return acc
|
|
28
|
+
}, {} as Record<string, ReturnType<typeof defineComponent>>)
|
|
24
29
|
|
|
25
30
|
export const components = {
|
|
26
|
-
...
|
|
31
|
+
...processed,
|
|
27
32
|
Lunchbox: LunchboxWrapper,
|
|
28
33
|
}
|
package/src/core/ensure.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { allNodes, createNode, MiniDom } from '.'
|
|
1
|
+
import { allNodes, createNode, isMinidomNode, MiniDom } from '.'
|
|
2
2
|
import { setupAutoRaycaster } from './interaction/setupAutoRaycaster'
|
|
3
3
|
import { computed, reactive, ref, WritableComputedRef } from 'vue'
|
|
4
4
|
import { Lunch } from '..'
|
|
@@ -38,6 +38,14 @@ export function tryGetNodeWithInstanceType<T extends THREE.Object3D>(
|
|
|
38
38
|
singleType.toLowerCase()
|
|
39
39
|
)
|
|
40
40
|
|
|
41
|
+
// cancel if found example is marked !isDefault
|
|
42
|
+
if (
|
|
43
|
+
isMinidomNode(found) &&
|
|
44
|
+
(!found.props['is-default'] || !found.props['isDefault'])
|
|
45
|
+
) {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
// if we have one, save and return
|
|
42
50
|
if (found) {
|
|
43
51
|
const createdAsNode = found as MiniDom.RendererStandardNode<T>
|
package/src/core/extend.ts
CHANGED
|
@@ -8,12 +8,18 @@ const createComponent = (tag: string) =>
|
|
|
8
8
|
name: tag,
|
|
9
9
|
render() {
|
|
10
10
|
return h(tag, this.$attrs, this.$slots?.default?.() || [])
|
|
11
|
-
}
|
|
11
|
+
},
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
export const extend = ({
|
|
15
|
-
|
|
14
|
+
export const extend = ({
|
|
15
|
+
app,
|
|
16
|
+
...targets
|
|
17
|
+
}: {
|
|
18
|
+
app: Lunch.App
|
|
19
|
+
[key: string]: any
|
|
20
|
+
}) => {
|
|
21
|
+
Object.keys(targets).forEach((key) => {
|
|
16
22
|
app.component(key, createComponent(key))
|
|
17
23
|
catalogue[key] = targets[key]
|
|
18
24
|
})
|
|
19
|
-
}
|
|
25
|
+
}
|
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
|
+
}
|
|
@@ -31,8 +31,17 @@ export function updateObjectProp({
|
|
|
31
31
|
return addEventListener({ node, key, value })
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// update THREE property
|
|
35
|
+
// get final key
|
|
36
|
+
const camelKey = key.replace(/-/g, '.')
|
|
37
|
+
const finalKey = propertyShortcuts[camelKey] || camelKey
|
|
38
|
+
|
|
34
39
|
// handle and return early if prop is specific to Vue/Lunchbox
|
|
35
|
-
if (
|
|
40
|
+
if (
|
|
41
|
+
internalLunchboxVueKeys.includes(key) ||
|
|
42
|
+
internalLunchboxVueKeys.includes(finalKey)
|
|
43
|
+
)
|
|
44
|
+
return node
|
|
36
45
|
|
|
37
46
|
// everything else should be Three-specific, so let's cancel if this isn't a standard node
|
|
38
47
|
if (!isLunchboxStandardNode(node)) return node
|
|
@@ -49,12 +58,8 @@ export function updateObjectProp({
|
|
|
49
58
|
// cancel if no target
|
|
50
59
|
if (!target) return node
|
|
51
60
|
|
|
52
|
-
// update THREE property
|
|
53
|
-
// get final key
|
|
54
|
-
const camelKey = key.replace(/-/g, '.')
|
|
55
|
-
let finalKey = propertyShortcuts[camelKey] || camelKey
|
|
56
|
-
let liveProperty
|
|
57
61
|
// burrow down until we get property to change
|
|
62
|
+
let liveProperty
|
|
58
63
|
for (let i = 0; i < nestedPropertiesToCheck.length && !liveProperty; i++) {
|
|
59
64
|
const nestedProperty = nestedPropertiesToCheck[i]
|
|
60
65
|
const fullPath = [nestedProperty, finalKey].filter(Boolean).join('.')
|
|
@@ -128,6 +133,8 @@ const internalLunchboxVueKeys = [
|
|
|
128
133
|
'args',
|
|
129
134
|
'attach',
|
|
130
135
|
'attachArray',
|
|
136
|
+
'is.default',
|
|
137
|
+
'isDefault',
|
|
131
138
|
'key',
|
|
132
139
|
'onAdded',
|
|
133
140
|
// 'onReady',
|
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
|
package/src/utils/index.ts
CHANGED
|
@@ -23,7 +23,9 @@ export const isEventKey = (target: any): target is Lunch.EventKey => {
|
|
|
23
23
|
].includes(target)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export const isLunchboxComponent = (
|
|
26
|
+
export const isLunchboxComponent = (
|
|
27
|
+
node: any
|
|
28
|
+
): node is Lunch.LunchboxComponent => {
|
|
27
29
|
return node?.$el && node?.$el?.hasOwnProperty?.('instance')
|
|
28
30
|
}
|
|
29
31
|
|
|
@@ -35,10 +37,12 @@ export const isLunchboxDomComponent = (node: any): node is Lunch.DomMeta => {
|
|
|
35
37
|
return lunchboxDomComponentNames.includes(typeToCheck ?? '')
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
export const isLunchboxStandardNode = (
|
|
40
|
+
export const isLunchboxStandardNode = (
|
|
41
|
+
node: any
|
|
42
|
+
): node is Lunch.StandardMeta => {
|
|
39
43
|
return node?.metaType === 'standardMeta'
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
export const isLunchboxRootNode = (node: any): node is Lunch.RootMeta => {
|
|
43
47
|
return node.isLunchboxRootNode
|
|
44
|
-
}
|
|
48
|
+
}
|