lunchboxjs 0.1.4013 → 0.1.4014
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/.DS_Store +0 -0
- package/dist/lunchboxjs.js +85 -101
- package/dist/lunchboxjs.min.js +1 -1
- package/dist/lunchboxjs.module.js +85 -101
- package/package.json +7 -3
- package/src/.DS_Store +0 -0
- package/src/core/.DS_Store +0 -0
- package/src/core/createNode.ts +5 -1
- package/src/core/ensure.ts +4 -10
- package/src/index.ts +12 -40
- package/src/nodeOps/remove.ts +0 -1
package/README.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
1
|
Custom Vue 3 renderer for ThreeJS.
|
|
2
2
|
|
|
3
|
+
## Full Docs
|
|
4
|
+
|
|
3
5
|
[Docs](//docs.lunchboxjs.com)
|
|
6
|
+
|
|
7
|
+
## Local Dev
|
|
8
|
+
|
|
9
|
+
`npm run dev` to run dev server. From there, edit source code in `/src/...` and examples in `/demo/...` to build and test features.
|
|
10
|
+
|
|
11
|
+
### Creating Examples
|
|
12
|
+
|
|
13
|
+
Run `npm run demo:create` to create a new demo.
|
|
14
|
+
|
|
15
|
+
## Docs Dev
|
|
16
|
+
|
|
17
|
+
`npm run docs:dev` to run docs dev. Docs exist as a Vitepress site in the `/docs` folder.
|
package/dist/.DS_Store
ADDED
|
Binary file
|
package/dist/lunchboxjs.js
CHANGED
|
@@ -544,76 +544,6 @@
|
|
|
544
544
|
return node.isLunchboxRootNode;
|
|
545
545
|
};
|
|
546
546
|
|
|
547
|
-
/** Create a new Lunchbox comment node. */
|
|
548
|
-
function createCommentNode(options = {}) {
|
|
549
|
-
const defaults = {
|
|
550
|
-
text: options.text ?? '',
|
|
551
|
-
};
|
|
552
|
-
return new MiniDom.RendererCommentNode({
|
|
553
|
-
...defaults,
|
|
554
|
-
...options,
|
|
555
|
-
metaType: 'commentMeta',
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
/** Create a new DOM node. */
|
|
559
|
-
function createDomNode(options = {}) {
|
|
560
|
-
const domElement = document.createElement(options.type ?? '');
|
|
561
|
-
const defaults = {
|
|
562
|
-
domElement,
|
|
563
|
-
};
|
|
564
|
-
const node = new MiniDom.RendererDomNode({
|
|
565
|
-
...defaults,
|
|
566
|
-
...options,
|
|
567
|
-
metaType: 'domMeta',
|
|
568
|
-
});
|
|
569
|
-
return node;
|
|
570
|
-
}
|
|
571
|
-
/** Create a new Lunchbox text node. */
|
|
572
|
-
function createTextNode(options = {}) {
|
|
573
|
-
const defaults = {
|
|
574
|
-
text: options.text ?? '',
|
|
575
|
-
};
|
|
576
|
-
return new MiniDom.RendererTextNode({
|
|
577
|
-
...options,
|
|
578
|
-
...defaults,
|
|
579
|
-
metaType: 'textMeta',
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
/** Create a new Lunchbox standard node. */
|
|
583
|
-
function createNode(options = {}, props = {}) {
|
|
584
|
-
const defaults = {
|
|
585
|
-
attached: options.attached ?? [],
|
|
586
|
-
attachedArray: options.attachedArray ?? {},
|
|
587
|
-
instance: options.instance ?? null,
|
|
588
|
-
};
|
|
589
|
-
const node = new MiniDom.RendererStandardNode({
|
|
590
|
-
...options,
|
|
591
|
-
...defaults,
|
|
592
|
-
metaType: 'standardMeta',
|
|
593
|
-
});
|
|
594
|
-
if (node.type && !isLunchboxRootNode(node) && !node.instance) {
|
|
595
|
-
// if (node.type.includes('Camera')) {
|
|
596
|
-
// console.log(node.type, {
|
|
597
|
-
// ...node.props,
|
|
598
|
-
// ...props,
|
|
599
|
-
// })
|
|
600
|
-
// console.trace()
|
|
601
|
-
// }
|
|
602
|
-
node.instance = instantiateThreeObject({
|
|
603
|
-
...node,
|
|
604
|
-
props: {
|
|
605
|
-
...node.props,
|
|
606
|
-
...props,
|
|
607
|
-
},
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
if (node.type === 'scene') {
|
|
611
|
-
// manually set scene override
|
|
612
|
-
ensuredScene.value = node;
|
|
613
|
-
}
|
|
614
|
-
return node;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
547
|
const interactables = [];
|
|
618
548
|
const addInteractable = (target) => {
|
|
619
549
|
interactables.push(target);
|
|
@@ -939,17 +869,10 @@
|
|
|
939
869
|
overrides[pascalType] = val;
|
|
940
870
|
},
|
|
941
871
|
});
|
|
942
|
-
// export const ensuredCamera = buildEnsured<THREE.Camera>(
|
|
943
|
-
// ['PerspectiveCamera', 'OrthographicCamera'],
|
|
944
|
-
// fallbackCameraUuid,
|
|
945
|
-
// {
|
|
946
|
-
// args: [45, 0.5625, 1, 1000],
|
|
947
|
-
// }
|
|
948
|
-
// )
|
|
949
872
|
// ENSURE RENDERER
|
|
950
873
|
// ====================
|
|
951
874
|
const fallbackRendererUuid = 'FALLBACK_RENDERER';
|
|
952
|
-
const
|
|
875
|
+
const ensuredRenderer = buildEnsured(
|
|
953
876
|
// TODO: ensure support for css/svg renderers
|
|
954
877
|
['WebGLRenderer'], //, 'CSS2DRenderer', 'CSS3DRenderer', 'SVGRenderer'],
|
|
955
878
|
fallbackRendererUuid, {});
|
|
@@ -958,7 +881,7 @@
|
|
|
958
881
|
const rendererReady = vue.ref(false);
|
|
959
882
|
const ensureRenderer = vue.computed({
|
|
960
883
|
get() {
|
|
961
|
-
return (rendererReady.value ?
|
|
884
|
+
return (rendererReady.value ? ensuredRenderer.value : null);
|
|
962
885
|
},
|
|
963
886
|
set(val) {
|
|
964
887
|
const t = val.type ?? '';
|
|
@@ -975,6 +898,80 @@
|
|
|
975
898
|
// `unknown` is intentional here - we need to typecast the node since Raycaster isn't an Object3D
|
|
976
899
|
const ensuredRaycaster = buildEnsured('Raycaster', autoRaycasterUuid, {}, (node) => setupAutoRaycaster(node));
|
|
977
900
|
|
|
901
|
+
/** Create a new Lunchbox comment node. */
|
|
902
|
+
function createCommentNode(options = {}) {
|
|
903
|
+
const defaults = {
|
|
904
|
+
text: options.text ?? '',
|
|
905
|
+
};
|
|
906
|
+
return new MiniDom.RendererCommentNode({
|
|
907
|
+
...defaults,
|
|
908
|
+
...options,
|
|
909
|
+
metaType: 'commentMeta',
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
/** Create a new DOM node. */
|
|
913
|
+
function createDomNode(options = {}) {
|
|
914
|
+
const domElement = document.createElement(options.type ?? '');
|
|
915
|
+
const defaults = {
|
|
916
|
+
domElement,
|
|
917
|
+
};
|
|
918
|
+
const node = new MiniDom.RendererDomNode({
|
|
919
|
+
...defaults,
|
|
920
|
+
...options,
|
|
921
|
+
metaType: 'domMeta',
|
|
922
|
+
});
|
|
923
|
+
return node;
|
|
924
|
+
}
|
|
925
|
+
/** Create a new Lunchbox text node. */
|
|
926
|
+
function createTextNode(options = {}) {
|
|
927
|
+
const defaults = {
|
|
928
|
+
text: options.text ?? '',
|
|
929
|
+
};
|
|
930
|
+
return new MiniDom.RendererTextNode({
|
|
931
|
+
...options,
|
|
932
|
+
...defaults,
|
|
933
|
+
metaType: 'textMeta',
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
/** Create a new Lunchbox standard node. */
|
|
937
|
+
function createNode(options = {}, props = {}) {
|
|
938
|
+
const defaults = {
|
|
939
|
+
attached: options.attached ?? [],
|
|
940
|
+
attachedArray: options.attachedArray ?? {},
|
|
941
|
+
instance: options.instance ?? null,
|
|
942
|
+
};
|
|
943
|
+
const node = new MiniDom.RendererStandardNode({
|
|
944
|
+
...options,
|
|
945
|
+
...defaults,
|
|
946
|
+
metaType: 'standardMeta',
|
|
947
|
+
});
|
|
948
|
+
if (node.type && !isLunchboxRootNode(node) && !node.instance) {
|
|
949
|
+
// if (node.type.includes('Camera')) {
|
|
950
|
+
// console.log(node.type, {
|
|
951
|
+
// ...node.props,
|
|
952
|
+
// ...props,
|
|
953
|
+
// })
|
|
954
|
+
// console.trace()
|
|
955
|
+
// }
|
|
956
|
+
node.instance = instantiateThreeObject({
|
|
957
|
+
...node,
|
|
958
|
+
props: {
|
|
959
|
+
...node.props,
|
|
960
|
+
...props,
|
|
961
|
+
},
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
// TODO: these manual overrides are a bit brittle - replace?
|
|
965
|
+
if (node.type?.toLowerCase() === 'scene') {
|
|
966
|
+
// manually set scene override
|
|
967
|
+
ensuredScene.value = node;
|
|
968
|
+
}
|
|
969
|
+
else if (node.type?.toLowerCase().endsWith('camera')) {
|
|
970
|
+
ensuredCamera.value = node;
|
|
971
|
+
}
|
|
972
|
+
return node;
|
|
973
|
+
}
|
|
974
|
+
|
|
978
975
|
const createComponent = (tag) => vue.defineComponent({
|
|
979
976
|
inheritAttrs: false,
|
|
980
977
|
name: tag,
|
|
@@ -1731,46 +1728,31 @@
|
|
|
1731
1728
|
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
1732
1729
|
const camera = vue.computed(() => ensuredCamera.value?.instance ?? null);
|
|
1733
1730
|
/** Run a function using the current camera when it's present. */
|
|
1734
|
-
function useCamera(callback
|
|
1735
|
-
|
|
1736
|
-
destroy = vue.watch(camera, (newVal) => {
|
|
1731
|
+
function useCamera(callback) {
|
|
1732
|
+
return vue.watch(camera, (newVal) => {
|
|
1737
1733
|
if (!newVal)
|
|
1738
1734
|
return;
|
|
1739
|
-
// TODO: better fix than `any`?
|
|
1740
1735
|
callback(newVal);
|
|
1741
|
-
if (once) {
|
|
1742
|
-
destroy?.();
|
|
1743
|
-
}
|
|
1744
1736
|
}, { immediate: true });
|
|
1745
1737
|
}
|
|
1746
1738
|
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
1747
1739
|
const renderer = vue.computed(() => ensureRenderer.value?.instance ?? null);
|
|
1748
1740
|
/** Run a function using the current renderer when it's present. */
|
|
1749
|
-
function useRenderer(callback
|
|
1750
|
-
|
|
1751
|
-
destroy = vue.watch(renderer, (newVal) => {
|
|
1741
|
+
function useRenderer(callback) {
|
|
1742
|
+
return vue.watch(renderer, (newVal) => {
|
|
1752
1743
|
if (!newVal)
|
|
1753
1744
|
return;
|
|
1754
|
-
// TODO: better fix than `any`?
|
|
1755
1745
|
callback(newVal);
|
|
1756
|
-
if (once) {
|
|
1757
|
-
destroy?.();
|
|
1758
|
-
}
|
|
1759
1746
|
}, { immediate: true });
|
|
1760
1747
|
}
|
|
1761
1748
|
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
1762
1749
|
const scene = vue.computed(() => ensuredScene.value.instance);
|
|
1763
1750
|
/** Run a function using the current scene when it's present. */
|
|
1764
|
-
function useScene(callback
|
|
1765
|
-
|
|
1766
|
-
destroy = vue.watch(scene, (newVal) => {
|
|
1751
|
+
function useScene(callback) {
|
|
1752
|
+
return vue.watch(scene, (newVal) => {
|
|
1767
1753
|
if (!newVal)
|
|
1768
1754
|
return;
|
|
1769
|
-
// TODO: better fix than `any`?
|
|
1770
1755
|
callback(newVal);
|
|
1771
|
-
if (once) {
|
|
1772
|
-
destroy?.();
|
|
1773
|
-
}
|
|
1774
1756
|
}, { immediate: true });
|
|
1775
1757
|
}
|
|
1776
1758
|
// CUSTOM RENDER SUPPORT
|
|
@@ -1799,12 +1781,14 @@
|
|
|
1799
1781
|
app = vue.createRenderer(nodeOps).createApp(root);
|
|
1800
1782
|
// register all components
|
|
1801
1783
|
Object.keys(components).forEach((key) => {
|
|
1802
|
-
app
|
|
1784
|
+
app?.component(key, components[key]);
|
|
1803
1785
|
});
|
|
1804
1786
|
// update mount function to match Lunchbox.Node
|
|
1805
1787
|
const { mount } = app;
|
|
1806
1788
|
app.mount = (root, ...args) => {
|
|
1789
|
+
// find DOM element to use as app root
|
|
1807
1790
|
const domElement = (typeof root === 'string' ? document.querySelector(root) : root);
|
|
1791
|
+
// create or find root node
|
|
1808
1792
|
const rootNode = ensureRootNode({
|
|
1809
1793
|
domElement,
|
|
1810
1794
|
isLunchboxRootNode: true,
|
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=I.value?.instance,o=z.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,zoom:Number},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(p&&void 0!==e.zoom&&(p.instance.zoom=e.zoom),m=z.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&&(z.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)&&(K.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=K.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})=>{N({element:e,eventKeys:["onPointerEnter"],intersection:t})})),a.forEach((({element:e,intersection:t})=>{N({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),s.forEach((({element:e,intersection:t})=>{N({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),P=[].concat(o,a)},N=({element:e,eventKeys:t,intersection:n})=>{e&&t.forEach((t=>{e.eventListeners[t]&&e.eventListeners[t].forEach((e=>{e({intersection:n})}))}))};function B(t={}){return e.lunchboxTree||(e.lunchboxTree=new J.RendererRootNode(t)),e.lunchboxTree}function G(e){Array.isArray(e)||(e=[e]);for(let t of e)if(O[t])return O[t];for(let n of e){const e=T[n]||s.find((e=>e.type?.toLowerCase()===n.toLowerCase()));if(!(t=e,"RendererNode"!==t?.minidomType||!1!==e.props["is-default"]&&!1!=!e.props.isDefault))return null;if(e){const t=e;return T[n]=t,t}}var t;return null}e.lunchboxTree=void 0;const T=t.reactive({}),O=t.reactive({});function j(e,n,r={},o=null){Array.isArray(e)||(e=[e]);for(let t of e)T[t]||(T[t]=null),O[t]||(O[t]=null);return t.computed({get(){const t=G(e);if(t)return t;const a=B(),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}}),z=j("Scene","FALLBACK_SCENE"),K=j("Raycaster","AUTO_RAYCASTER",{},(e=>(e=>{if(!e.instance)return;let n=null;n=t.watch((()=>I.value),(e=>{e?.instance&&(L||(w=t=>{const n=(e.instance.domElement.width??1)/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))),_=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}});var V,q=new Uint8Array(16);function H(){if(!V&&!(V="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return V(q)}var Y=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function X(e){return"string"==typeof e&&Y.test(e)}for(var J,Q=[],Z=0;Z<256;++Z)Q.push((Z+256).toString(16).substr(1));function ee(e,t,n){var r=(e=e||{}).random||(e.rng||H)();if(r[6]=15&r[6]|64,r[8]=63&r[8]|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=r[o];return t}return function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=(Q[e[t+0]]+Q[e[t+1]]+Q[e[t+2]]+Q[e[t+3]]+"-"+Q[e[t+4]]+Q[e[t+5]]+"-"+Q[e[t+6]]+Q[e[t+7]]+"-"+Q[e[t+8]]+Q[e[t+9]]+"-"+Q[e[t+10]]+Q[e[t+11]]+Q[e[t+12]]+Q[e[t+13]]+Q[e[t+14]]+Q[e[t+15]]).toLowerCase();if(!X(n))throw TypeError("Stringified UUID is invalid");return n}(r)}!function(e){e.BaseNode=class{constructor(e={},t){this.parentNode=e?.parentNode??t??null,this.minidomType="MinidomBaseNode",this.uuid=e?.uuid??ee(),s.push(this)}uuid;parentNode;get nextSibling(){if(!this.parentNode)return null;const e=this.parentNode.children.findIndex((e=>e.uuid===this.uuid));return-1!==e&&e<this.parentNode.children.length-1?this.parentNode.children[e+1]:null}insertBefore(e,t){e.removeAsChildFromAnyParents(),e.parentNode=this;const n=this.children.findIndex((e=>e.uuid===t?.uuid));-1!==n?this.children.splice(n,0,e):this.children.push(e)}removeChild(e){const t=this.children.findIndex((t=>t?.uuid===e?.uuid));-1!==t&&this.children.splice(t,1)}children=[];addChild(e){return e&&(e.removeAsChildFromAnyParents(),e.parentNode=this,this.insertBefore(e,null)),this}getPath(){const e=[];let t=this;for(;t;)e.unshift(t),t=t.parentNode;return e}drop(){this.parentNode=null,this.removeAsChildFromAnyParents()}walk(e){const t=[this,...this.children],n=[];let r=!0;for(;t.length&&r;){const o=t.shift();if(o){if(n.includes(o))continue;n.push(o),t.push(...o.children.filter((e=>!n.includes(e)))),r=e(o)}else r=!1}}minidomType;removeAsChildFromAnyParents(){s.forEach((e=>e.removeChild(this)))}};class t extends e.BaseNode{constructor(e={},t){super(e,t),this.minidomType="RendererNode",this.eventListeners={},this.eventListenerRemoveFunctions={},this.name=e.name??"",this.metaType=e.metaType??"standardMeta",this.props=e.props??[],this.type=e.type??""}eventListeners;eventListenerRemoveFunctions;name;metaType;props;type;drop(){super.drop(),Object.keys(this.eventListenerRemoveFunctions).forEach((e=>{this.eventListenerRemoveFunctions[e].forEach((e=>e()))}))}}e.RendererBaseNode=t;class n extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement;isLunchboxRootNode=!0}e.RendererRootNode=n;class r extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererCommentNode=r;class o extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement}e.RendererDomNode=o;class a extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererTextNode=a;class i extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.attached=e.attached??[],this.attachedArray=e.attachedArray??{},this.instance=e.instance??null}attached;attachedArray;instance}e.RendererStandardNode=i}(J||(J={}));(new J.RendererRootNode).minidomType="RootNode";const te=[];let ne;const re=[],oe=[],ae=e=>{ne=requestAnimationFrame((()=>ae({app:e.app,renderer:I.value?.instance,scene:z.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??B();if(r.insertBefore(e,n),"commentMeta"!==e.metaType&&"textMeta"!==e.metaType&&(h(e)&&(h(t)||y(t))&&t.domElement.appendChild(e.domElement),f(e))){let n=r.metaType;if("textMeta"===n||"commentMeta"===n){const e=r.getPath();for(let t=e.length-1;t>=0;t--)if("textMeta"!==e[t].metaType&&"commentMeta"!==e[t].metaType){r=e[t];break}}if("standardMeta"===e.metaType&&"scene"!==e.type&&y(r)){const t=z.value;t.instance&&e&&t.addChild(e),e.instance&&e.instance.isObject3D&&t.instance&&t!==e&&t.instance.add(e.instance)}else f(e)&&e.instance?.isObject3D&&f(r)&&r.instance?.isObject3D&&r.instance?.add?.(e.instance);if(e?.props?.attach&&f(t)&&t?.instance){e.type?.toLowerCase().endsWith("loader")&&e.props.src&&(e.props.attach||e.props.attachArray)?function(e,t){const n=e.instance;if(t.attached=t.attached||{},t.attachedArray=t.attachedArray||{},!e.props.attach)return;if("textureloader"===e.type?.toLowerCase()){const r=n.load(e.props.src);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((()=>z.value.instance));let ge=null,be=null;e.camera=fe,e.clearCustomRender=()=>{ge?ge.clearCustomRender():be=null},e.createApp=e=>{ge=t.createRenderer(me).createApp(e),Object.keys(p).forEach((e=>{ge.component(e,p[e])}));const{mount:n}=ge;return ge.mount=(e,...t)=>{const r=B({domElement:"string"==typeof e?document.querySelector(e):e,isLunchboxRootNode:!0,name:"root",metaType:"rootMeta",type:"root",uuid:"LUNCHBOX_ROOT"});ge.rootNode=r;return n(r,...t)},ge.extend=e=>((({app:e,...t})=>{Object.keys(t).forEach((n=>{e.component(n,_(n)),u[n]=t[n]}))})({app:ge,...e}),ge),ge.setCustomRender=e=>{ge.customRender=e},be&&(ge.setCustomRender(be),be=null),ge.clearCustomRender=()=>{ge.customRender=null},ge},e.find=function(e){return e=t.isRef(e)?e.value:e,f(e)?e?.instance:m(e)?e?.$el?.instance:t.isVNode(e)?e.el?.instance:null},e.globals=he,e.offAfterRender=e=>{if(isFinite(e))oe.splice(e,1);else{const t=oe.findIndex((t=>t==e));oe.splice(t,1)}},e.offBeforeRender=e=>{if(isFinite(e))re.splice(e,1);else{const t=re.findIndex((t=>t==e));re.splice(t,1)}},e.onAfterRender=(e,t=1/0)=>{t===1/0?oe.push(e):oe.splice(t,0,e)},e.onBeforeRender=se,e.onStart=(e,t=1/0)=>{t===1/0?te.push(e):te.splice(t,0,e)},e.renderer=ye,e.scene=ve,e.setCustomRender=e=>{ge?ge.setCustomRender(e):be=e},e.useCamera=function(e,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})}));
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue"),require("three"),require("lodash")):"function"==typeof define&&define.amd?define(["exports","vue","three","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LunchboxRenderer={},e.vue,e.three,e.lodash)}(this,(function(e,t,n,r){"use strict";function o(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var a=o(n);const s=[],i=(e,n)=>{const r=W.value?.instance,o=I.value.instance,a=D.value;if(!r?.domElement||!o||!a)return;const s=(e=e??window.innerWidth)/(n=n??window.innerHeight);if("perspectivecamera"===a.type?.toLowerCase()){const e=a.instance;e.aspect=s,e.updateProjectionMatrix()}else if("orthographiccamera"===a.type?.toLowerCase()){const t=a.instance,r=n/e;t.top=10*r,t.bottom=10*-r,t.right=10,t.left=-10,t.updateProjectionMatrix()}else console.log("TODO: non-ortho or perspective camera");r.setSize(e,n),o&&a.instance&&r.render(t.toRaw(o),t.toRaw(a.instance))},c=e=>({position:e,top:0,right:0,bottom:0,left:0,width:"100%",height:"100%"}),d={name:"Lunchbox",props:{background:String,cameraArgs:Array,cameraLook:Array,cameraLookAt:Array,cameraPosition:Array,dpr:Number,ortho:Boolean,orthographic:Boolean,rendererArguments:Object,rendererProperties:Object,shadow:[Boolean,Object],transparent:Boolean,zoom:Number},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=B(["WebGLRenderer"]),l)s.value=!1,U.value=!0;else{const t={alpha:e.transparent,antialias:!0,canvas:a.value.domElement,...e.rendererArguments??{}};W.value=K({type:"WebGLRenderer",uuid:F,props:{args:[t]}}),U.value=!0;const n=W,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=B(["PerspectiveCamera","OrthographicCamera"]),p?S.value=!0:(e.ortho||e.orthographic?D.value=K({props:{args:e.cameraArgs??[]},type:"OrthographicCamera",uuid:j}):D.value=K({props:{args:e.cameraArgs??[45,.5625,1,1e3]},type:"PerspectiveCamera",uuid:j}),S.value=!0,p=D.value),!p.instance)throw new Error("Error creating camera.");if(p&&e.cameraPosition&&p.instance.position.set(...e.cameraPosition),p&&(e.cameraLookAt||e.cameraLook)){const t=e.cameraLookAt||e.cameraLook;p.instance.lookAt(...t)}if(p&&void 0!==e.zoom&&(p.instance.zoom=e.zoom),m=I.value,m&&m.instance&&e.background&&(m.instance.background=new 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,v=[],g=t.ref(!1);function b({node:e,key:n,value:r}){var o;if(e.eventListeners[n]||(e.eventListeners[n]=[]),e.eventListenerRemoveFunctions[n]||(e.eventListenerRemoveFunctions[n]=[]),e.eventListeners[n].push(r),x.includes(n)&&(z.value,e.instance&&!v.includes(e)&&(o=e,v.push(o),e.eventListenerRemoveFunctions[n].push((()=>(e=>{const t=v.indexOf(e);-1!==t&&v.splice(t,1)})(e))))),"onClick"===n||"onPointerDown"===n||"onPointerUp"===n){const r=t.watch((()=>g.value),(t=>{const r=L.map((e=>e.element)).findIndex((t=>t.instance&&t.instance.uuid===e.instance?.uuid));-1!==r&&((!t||"onClick"!==n&&"onPointerDown"!==n)&&(t||"onPointerUp"!==n)||e.eventListeners[n].forEach((e=>{e({intersection:L[r].intersection})})))}));e.eventListenerRemoveFunctions[n].push(r)}return e}const x=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"];let R,w,A;const C=t.ref({x:1/0,y:1/0});let E=!1;let L=[];const P=()=>{const e=z.value?.instance,t=D.value?.instance;if(!e||!t)return;e.setFromCamera(he.mousePos.value,t);const n=e.intersectObjects(v.map((e=>e.instance)));let r=[],o=[],a=[];r=L.map((e=>e.intersection)),n?.forEach((e=>{if(-1===L.findIndex((t=>t.intersection.object===e.object))){const t=v.find((t=>t.instance?.uuid===e.object.uuid));t&&o.push({element:t,intersection:e})}else{const t=v.find((t=>t.instance?.uuid===e.object.uuid));t&&a.push({element:t,intersection:e})}const t=r.findIndex((t=>t.object.uuid===e.object.uuid));-1!==t&&r.splice(t,1)}));const s=r.map((e=>({element:v.find((t=>t.instance?.uuid===e.object.uuid)),intersection:e})));o.forEach((({element:e,intersection:t})=>{M({element:e,eventKeys:["onPointerEnter"],intersection:t})})),a.forEach((({element:e,intersection:t})=>{M({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),s.forEach((({element:e,intersection:t})=>{M({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),L=[].concat(o,a)},M=({element:e,eventKeys:t,intersection:n})=>{e&&t.forEach((t=>{e.eventListeners[t]&&e.eventListeners[t].forEach((e=>{e({intersection:n})}))}))};function N(t={}){return e.lunchboxTree||(e.lunchboxTree=new J.RendererRootNode(t)),e.lunchboxTree}function B(e){Array.isArray(e)||(e=[e]);for(let t of e)if(T[t])return T[t];for(let n of e){const e=G[n]||s.find((e=>e.type?.toLowerCase()===n.toLowerCase()));if(!(t=e,"RendererNode"!==t?.minidomType||!1!==e.props["is-default"]&&!1!=!e.props.isDefault))return null;if(e){const t=e;return G[n]=t,t}}var t;return null}e.lunchboxTree=void 0;const G=t.reactive({}),T=t.reactive({});function O(e,n,r={},o=null){Array.isArray(e)||(e=[e]);for(let t of e)G[t]||(G[t]=null),T[t]||(T[t]=null);return t.computed({get(){const t=B(e);if(t)return t;const a=N(),s=K({type:e[0],uuid:n,props:r});return a.addChild(s),G[e[0]]=s,o&&o(s),s},set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);T[n]=e}})}const j="FALLBACK_CAMERA",k=O(["PerspectiveCamera","OrthographicCamera"],j,{args:[45,.5625,1,1e3]}),S=t.ref(!1),D=t.computed({get:()=>S.value?k.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);T[n]=e}}),F="FALLBACK_RENDERER",$=O(["WebGLRenderer"],F,{}),U=t.ref(!1),W=t.computed({get:()=>U.value?$.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);T[n]=e}}),I=O("Scene","FALLBACK_SCENE"),z=O("Raycaster","AUTO_RAYCASTER",{},(e=>(e=>{if(!e.instance)return;let n=null;n=t.watch((()=>W.value),(e=>{e?.instance&&(E||(R=t=>{const n=(e.instance.domElement.width??1)/he.dpr.value,r=(e.instance.domElement.height??1)/he.dpr.value;C.value.x=t.offsetX/n*2-1,C.value.y=-t.offsetY/r*2+1},w=()=>g.value=!0,A=()=>g.value=!1,e.instance.domElement.addEventListener("mousemove",R),e.instance.domElement.addEventListener("mousedown",w),e.instance.domElement.addEventListener("mouseup",A),se(P),E=!0),n&&n())}),{immediate:!0})})(e)));function K(e={},t={}){const n={attached:e.attached??[],attachedArray:e.attachedArray??{},instance:e.instance??null},r=new J.RendererStandardNode({...e,...n,metaType:"standardMeta"});return!r.type||y(r)||r.instance||(r.instance=function(e){if(!e.type)return null;const t=e.type[0].toUpperCase()+e.type.slice(1),n=u[e.type]||a[t];if(!n)throw`${t} is not part of the THREE namespace! Did you forget to extend? import {extend} from 'lunchbox'; extend({app, YourComponent, ...})`;const r=(e.props.args??[]).map((t=>function({node:e,prop:t}){const n="string"==typeof t&&t.startsWith("$attachedArray"),r=function({node:e,prop:t}){if("string"==typeof t&&t.startsWith("$attachedArray"))return e.attachedArray[t.replace("$attachedArray.","")];if("string"==typeof t&&t.startsWith("$attached"))return e.attached[t.replace("$attached.","")];return t}({node:e,prop:t});return Array.isArray(r)&&n?r:[r]}({node:e,prop:t})));let o=[];r.forEach((e=>{o=o.concat(e)}));return new n(...o)}({...r,props:{...r.props,...t}})),"scene"===r.type?.toLowerCase()?I.value=r:r.type?.toLowerCase().endsWith("camera")&&(D.value=r),r}const _=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}});var V,q=new Uint8Array(16);function H(){if(!V&&!(V="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return V(q)}var Y=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function X(e){return"string"==typeof e&&Y.test(e)}for(var J,Q=[],Z=0;Z<256;++Z)Q.push((Z+256).toString(16).substr(1));function ee(e,t,n){var r=(e=e||{}).random||(e.rng||H)();if(r[6]=15&r[6]|64,r[8]=63&r[8]|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=r[o];return t}return function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=(Q[e[t+0]]+Q[e[t+1]]+Q[e[t+2]]+Q[e[t+3]]+"-"+Q[e[t+4]]+Q[e[t+5]]+"-"+Q[e[t+6]]+Q[e[t+7]]+"-"+Q[e[t+8]]+Q[e[t+9]]+"-"+Q[e[t+10]]+Q[e[t+11]]+Q[e[t+12]]+Q[e[t+13]]+Q[e[t+14]]+Q[e[t+15]]).toLowerCase();if(!X(n))throw TypeError("Stringified UUID is invalid");return n}(r)}!function(e){e.BaseNode=class{constructor(e={},t){this.parentNode=e?.parentNode??t??null,this.minidomType="MinidomBaseNode",this.uuid=e?.uuid??ee(),s.push(this)}uuid;parentNode;get nextSibling(){if(!this.parentNode)return null;const e=this.parentNode.children.findIndex((e=>e.uuid===this.uuid));return-1!==e&&e<this.parentNode.children.length-1?this.parentNode.children[e+1]:null}insertBefore(e,t){e.removeAsChildFromAnyParents(),e.parentNode=this;const n=this.children.findIndex((e=>e.uuid===t?.uuid));-1!==n?this.children.splice(n,0,e):this.children.push(e)}removeChild(e){const t=this.children.findIndex((t=>t?.uuid===e?.uuid));-1!==t&&this.children.splice(t,1)}children=[];addChild(e){return e&&(e.removeAsChildFromAnyParents(),e.parentNode=this,this.insertBefore(e,null)),this}getPath(){const e=[];let t=this;for(;t;)e.unshift(t),t=t.parentNode;return e}drop(){this.parentNode=null,this.removeAsChildFromAnyParents()}walk(e){const t=[this,...this.children],n=[];let r=!0;for(;t.length&&r;){const o=t.shift();if(o){if(n.includes(o))continue;n.push(o),t.push(...o.children.filter((e=>!n.includes(e)))),r=e(o)}else r=!1}}minidomType;removeAsChildFromAnyParents(){s.forEach((e=>e.removeChild(this)))}};class t extends e.BaseNode{constructor(e={},t){super(e,t),this.minidomType="RendererNode",this.eventListeners={},this.eventListenerRemoveFunctions={},this.name=e.name??"",this.metaType=e.metaType??"standardMeta",this.props=e.props??[],this.type=e.type??""}eventListeners;eventListenerRemoveFunctions;name;metaType;props;type;drop(){super.drop(),Object.keys(this.eventListenerRemoveFunctions).forEach((e=>{this.eventListenerRemoveFunctions[e].forEach((e=>e()))}))}}e.RendererBaseNode=t;class n extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement;isLunchboxRootNode=!0}e.RendererRootNode=n;class r extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererCommentNode=r;class o extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement}e.RendererDomNode=o;class a extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererTextNode=a;class i extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.attached=e.attached??[],this.attachedArray=e.attachedArray??{},this.instance=e.instance??null}attached;attachedArray;instance}e.RendererStandardNode=i}(J||(J={}));(new J.RendererRootNode).minidomType="RootNode";const te=[];let ne;const re=[],oe=[],ae=e=>{ne=requestAnimationFrame((()=>ae({app:e.app,renderer:W.value?.instance,scene:I.value.instance,camera:D.value?.instance})));const{app:n,renderer:r,scene:o,camera:a}=e;re.forEach((t=>{t&&t(e)})),r&&o&&a&&(n.customRender?n.customRender(e):r.render(t.toRaw(o),t.toRaw(a))),oe.forEach((t=>{t&&t(e)}))},se=(e,t=1/0)=>{t===1/0?re.push(e):re.splice(t,0,e)},ie=()=>{ne&&cancelAnimationFrame(ne)};const ce={x:"position.x",y:"position.y",z:"position.z"},de=["","parameters"],ue=["args","attach","attachArray","is.default","isDefault","key","onAdded","ref","src"],le=["geometry","material"];function pe(e,t,n,r){const o=r??e.instance,a=t.instance;e.props.attach===n&&(t.attached={[n]:o,...t.attached||{}},a[n]=r??e.instance),e.props.attachArray===n&&(t.attachedArray[e.props.attachArray]||(t.attachedArray[e.props.attachArray]=[]),t.attachedArray[e.props.attachArray].push(o),a[n]=[a[n]])}const me={createElement:(e,t,n,r)=>{const o={type:e};r&&(o.props=r);if(h(e)){const e=function(e={}){const t={domElement:document.createElement(e.type??"")};return new J.RendererDomNode({...t,...e,metaType:"domMeta"})}(o);return e}const a=K(o);return le.forEach((t=>{e.toLowerCase().endsWith(t)&&(a.props.attach=t)})),a},createText:e=>function(e={}){const t={text:e.text??""};return new J.RendererTextNode({...e,...t,metaType:"textMeta"})}({text:e}),createComment:e=>function(e={}){const t={text:e.text??""};return new J.RendererCommentNode({...t,...e,metaType:"commentMeta"})}({text:e}),insert:(e,t,n)=>{let r=t??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=I.value;t.instance&&e&&t.addChild(e),e.instance&&e.instance.isObject3D&&t.instance&&t!==e&&t.instance.add(e.instance)}else f(e)&&e.instance?.isObject3D&&f(r)&&r.instance?.isObject3D&&r.instance?.add?.(e.instance);if(e?.props?.attach&&f(t)&&t?.instance){e.type?.toLowerCase().endsWith("loader")&&e.props.src&&(e.props.attach||e.props.attachArray)?function(e,t){const n=e.instance;if(t.attached=t.attached||{},t.attachedArray=t.attachedArray||{},!e.props.attach)return;if("textureloader"===e.type?.toLowerCase()){const r=n.load(e.props.src);pe(e,t,e.props.attach,r)}else n.load(e.props.src,(n=>{pe(e,t,e.props.attach,n)}),null,(e=>{throw new Error(e)}))}(e,t):pe(e,t,e.props.attach)}e.props?.onAdded&&e.props.onAdded({instance:e.instance})}},nextSibling(e){const t=e.nextSibling;return t||null},parentNode(e){const t=e.parentNode;return t||null},patchProp(e,t,n,o){h(e)?"style"===t?Object.keys(o).forEach((t=>{e.domElement.style[t]=o[t]})):e.domElement.setAttribute(t,o):y(e)||t.startsWith("$")||function({node:e,key:t,value:n}){if((e=>["onClick","onContextMenu","onDoubleClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove","onWheel"].includes(e))(t))return b({node:e,key:t,value:n});const o=t.replace(/-/g,"."),a=ce[o]||o;if(ue.includes(t)||ue.includes(a))return e;if(!f(e))return e;if("string"==typeof n&&n.startsWith("$attached")){const t=n.replace("$attached.","");n=r.get(e.attached,t,null)}const s=e.instance;if(!s)return e;let i;for(let e=0;e<de.length&&!i;e++){const t=[de[e],a].filter(Boolean).join(".");i=i=r.get(s,t)}if(i&&r.isNumber(n)&&i.setScalar)i.setScalar(n);else if(i&&i.set){const e=Array.isArray(n)?n:[n];s[a].set(...e)}else"function"==typeof i?i.bind(e.instance)(...n):void 0!==r.get(s,a,void 0)?r.set(s,a,""===n||n):console.log(`No property ${a} found on ${s}`);const c=s?.texture?.type||s?.type;if("string"==typeof c){const e=c.toLowerCase();switch(!0){case e.includes("material"):s.needsUpdate=!0;break;case e.includes("camera")&&s.updateProjectionMatrix:s.updateProjectionMatrix()}}}({node:e,key:t,value:o})},remove:e=>{if(!e)return;const t=Object.keys(T),n=[];e.walk((e=>(n.push(e),!0))),n.forEach((e=>{const n=t.find((t=>T[t]?.uuid===e.uuid));if(n&&(T[n]=null),f(e)){e.instance?.removeFromParent?.();const t="scene"!==e.type&&e.instance?.dispose;t&&t.bind(e.instance)(),e.instance=null}e.drop();const r=s.findIndex((t=>t.uuid===e.uuid));-1!==r&&s.splice(r,1)}))},setElementText(){},setText(){}},he={dpr:t.ref(1),inputActive:g,mousePos:C},fe=t.computed((()=>D.value?.instance??null));const ye=t.computed((()=>W.value?.instance??null));const ve=t.computed((()=>I.value.instance));let ge=null,be=null;e.camera=fe,e.clearCustomRender=()=>{ge?ge.clearCustomRender():be=null},e.createApp=e=>{ge=t.createRenderer(me).createApp(e),Object.keys(p).forEach((e=>{ge?.component(e,p[e])}));const{mount:n}=ge;return ge.mount=(e,...t)=>{const r=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,_(n)),u[n]=t[n]}))})({app:ge,...e}),ge),ge.setCustomRender=e=>{ge.customRender=e},be&&(ge.setCustomRender(be),be=null),ge.clearCustomRender=()=>{ge.customRender=null},ge},e.find=function(e){return e=t.isRef(e)?e.value:e,f(e)?e?.instance:m(e)?e?.$el?.instance:t.isVNode(e)?e.el?.instance:null},e.globals=he,e.offAfterRender=e=>{if(isFinite(e))oe.splice(e,1);else{const t=oe.findIndex((t=>t==e));oe.splice(t,1)}},e.offBeforeRender=e=>{if(isFinite(e))re.splice(e,1);else{const t=re.findIndex((t=>t==e));re.splice(t,1)}},e.onAfterRender=(e,t=1/0)=>{t===1/0?oe.push(e):oe.splice(t,0,e)},e.onBeforeRender=se,e.onStart=(e,t=1/0)=>{t===1/0?te.push(e):te.splice(t,0,e)},e.renderer=ye,e.scene=ve,e.setCustomRender=e=>{ge?ge.setCustomRender(e):be=e},e.useCamera=function(e){return t.watch(fe,(t=>{t&&e(t)}),{immediate:!0})},e.useRenderer=function(e){return t.watch(ye,(t=>{t&&e(t)}),{immediate:!0})},e.useScene=function(e){return t.watch(ve,(t=>{t&&e(t)}),{immediate:!0})},Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
@@ -523,76 +523,6 @@ const isLunchboxRootNode = (node) => {
|
|
|
523
523
|
return node.isLunchboxRootNode;
|
|
524
524
|
};
|
|
525
525
|
|
|
526
|
-
/** Create a new Lunchbox comment node. */
|
|
527
|
-
function createCommentNode(options = {}) {
|
|
528
|
-
const defaults = {
|
|
529
|
-
text: options.text ?? '',
|
|
530
|
-
};
|
|
531
|
-
return new MiniDom.RendererCommentNode({
|
|
532
|
-
...defaults,
|
|
533
|
-
...options,
|
|
534
|
-
metaType: 'commentMeta',
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
/** Create a new DOM node. */
|
|
538
|
-
function createDomNode(options = {}) {
|
|
539
|
-
const domElement = document.createElement(options.type ?? '');
|
|
540
|
-
const defaults = {
|
|
541
|
-
domElement,
|
|
542
|
-
};
|
|
543
|
-
const node = new MiniDom.RendererDomNode({
|
|
544
|
-
...defaults,
|
|
545
|
-
...options,
|
|
546
|
-
metaType: 'domMeta',
|
|
547
|
-
});
|
|
548
|
-
return node;
|
|
549
|
-
}
|
|
550
|
-
/** Create a new Lunchbox text node. */
|
|
551
|
-
function createTextNode(options = {}) {
|
|
552
|
-
const defaults = {
|
|
553
|
-
text: options.text ?? '',
|
|
554
|
-
};
|
|
555
|
-
return new MiniDom.RendererTextNode({
|
|
556
|
-
...options,
|
|
557
|
-
...defaults,
|
|
558
|
-
metaType: 'textMeta',
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
/** Create a new Lunchbox standard node. */
|
|
562
|
-
function createNode(options = {}, props = {}) {
|
|
563
|
-
const defaults = {
|
|
564
|
-
attached: options.attached ?? [],
|
|
565
|
-
attachedArray: options.attachedArray ?? {},
|
|
566
|
-
instance: options.instance ?? null,
|
|
567
|
-
};
|
|
568
|
-
const node = new MiniDom.RendererStandardNode({
|
|
569
|
-
...options,
|
|
570
|
-
...defaults,
|
|
571
|
-
metaType: 'standardMeta',
|
|
572
|
-
});
|
|
573
|
-
if (node.type && !isLunchboxRootNode(node) && !node.instance) {
|
|
574
|
-
// if (node.type.includes('Camera')) {
|
|
575
|
-
// console.log(node.type, {
|
|
576
|
-
// ...node.props,
|
|
577
|
-
// ...props,
|
|
578
|
-
// })
|
|
579
|
-
// console.trace()
|
|
580
|
-
// }
|
|
581
|
-
node.instance = instantiateThreeObject({
|
|
582
|
-
...node,
|
|
583
|
-
props: {
|
|
584
|
-
...node.props,
|
|
585
|
-
...props,
|
|
586
|
-
},
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
if (node.type === 'scene') {
|
|
590
|
-
// manually set scene override
|
|
591
|
-
ensuredScene.value = node;
|
|
592
|
-
}
|
|
593
|
-
return node;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
526
|
const interactables = [];
|
|
597
527
|
const addInteractable = (target) => {
|
|
598
528
|
interactables.push(target);
|
|
@@ -918,17 +848,10 @@ const ensuredCamera = computed({
|
|
|
918
848
|
overrides[pascalType] = val;
|
|
919
849
|
},
|
|
920
850
|
});
|
|
921
|
-
// export const ensuredCamera = buildEnsured<THREE.Camera>(
|
|
922
|
-
// ['PerspectiveCamera', 'OrthographicCamera'],
|
|
923
|
-
// fallbackCameraUuid,
|
|
924
|
-
// {
|
|
925
|
-
// args: [45, 0.5625, 1, 1000],
|
|
926
|
-
// }
|
|
927
|
-
// )
|
|
928
851
|
// ENSURE RENDERER
|
|
929
852
|
// ====================
|
|
930
853
|
const fallbackRendererUuid = 'FALLBACK_RENDERER';
|
|
931
|
-
const
|
|
854
|
+
const ensuredRenderer = buildEnsured(
|
|
932
855
|
// TODO: ensure support for css/svg renderers
|
|
933
856
|
['WebGLRenderer'], //, 'CSS2DRenderer', 'CSS3DRenderer', 'SVGRenderer'],
|
|
934
857
|
fallbackRendererUuid, {});
|
|
@@ -937,7 +860,7 @@ fallbackRendererUuid, {});
|
|
|
937
860
|
const rendererReady = ref(false);
|
|
938
861
|
const ensureRenderer = computed({
|
|
939
862
|
get() {
|
|
940
|
-
return (rendererReady.value ?
|
|
863
|
+
return (rendererReady.value ? ensuredRenderer.value : null);
|
|
941
864
|
},
|
|
942
865
|
set(val) {
|
|
943
866
|
const t = val.type ?? '';
|
|
@@ -954,6 +877,80 @@ const autoRaycasterUuid = 'AUTO_RAYCASTER';
|
|
|
954
877
|
// `unknown` is intentional here - we need to typecast the node since Raycaster isn't an Object3D
|
|
955
878
|
const ensuredRaycaster = buildEnsured('Raycaster', autoRaycasterUuid, {}, (node) => setupAutoRaycaster(node));
|
|
956
879
|
|
|
880
|
+
/** Create a new Lunchbox comment node. */
|
|
881
|
+
function createCommentNode(options = {}) {
|
|
882
|
+
const defaults = {
|
|
883
|
+
text: options.text ?? '',
|
|
884
|
+
};
|
|
885
|
+
return new MiniDom.RendererCommentNode({
|
|
886
|
+
...defaults,
|
|
887
|
+
...options,
|
|
888
|
+
metaType: 'commentMeta',
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
/** Create a new DOM node. */
|
|
892
|
+
function createDomNode(options = {}) {
|
|
893
|
+
const domElement = document.createElement(options.type ?? '');
|
|
894
|
+
const defaults = {
|
|
895
|
+
domElement,
|
|
896
|
+
};
|
|
897
|
+
const node = new MiniDom.RendererDomNode({
|
|
898
|
+
...defaults,
|
|
899
|
+
...options,
|
|
900
|
+
metaType: 'domMeta',
|
|
901
|
+
});
|
|
902
|
+
return node;
|
|
903
|
+
}
|
|
904
|
+
/** Create a new Lunchbox text node. */
|
|
905
|
+
function createTextNode(options = {}) {
|
|
906
|
+
const defaults = {
|
|
907
|
+
text: options.text ?? '',
|
|
908
|
+
};
|
|
909
|
+
return new MiniDom.RendererTextNode({
|
|
910
|
+
...options,
|
|
911
|
+
...defaults,
|
|
912
|
+
metaType: 'textMeta',
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
/** Create a new Lunchbox standard node. */
|
|
916
|
+
function createNode(options = {}, props = {}) {
|
|
917
|
+
const defaults = {
|
|
918
|
+
attached: options.attached ?? [],
|
|
919
|
+
attachedArray: options.attachedArray ?? {},
|
|
920
|
+
instance: options.instance ?? null,
|
|
921
|
+
};
|
|
922
|
+
const node = new MiniDom.RendererStandardNode({
|
|
923
|
+
...options,
|
|
924
|
+
...defaults,
|
|
925
|
+
metaType: 'standardMeta',
|
|
926
|
+
});
|
|
927
|
+
if (node.type && !isLunchboxRootNode(node) && !node.instance) {
|
|
928
|
+
// if (node.type.includes('Camera')) {
|
|
929
|
+
// console.log(node.type, {
|
|
930
|
+
// ...node.props,
|
|
931
|
+
// ...props,
|
|
932
|
+
// })
|
|
933
|
+
// console.trace()
|
|
934
|
+
// }
|
|
935
|
+
node.instance = instantiateThreeObject({
|
|
936
|
+
...node,
|
|
937
|
+
props: {
|
|
938
|
+
...node.props,
|
|
939
|
+
...props,
|
|
940
|
+
},
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
// TODO: these manual overrides are a bit brittle - replace?
|
|
944
|
+
if (node.type?.toLowerCase() === 'scene') {
|
|
945
|
+
// manually set scene override
|
|
946
|
+
ensuredScene.value = node;
|
|
947
|
+
}
|
|
948
|
+
else if (node.type?.toLowerCase().endsWith('camera')) {
|
|
949
|
+
ensuredCamera.value = node;
|
|
950
|
+
}
|
|
951
|
+
return node;
|
|
952
|
+
}
|
|
953
|
+
|
|
957
954
|
const createComponent = (tag) => defineComponent({
|
|
958
955
|
inheritAttrs: false,
|
|
959
956
|
name: tag,
|
|
@@ -1710,46 +1707,31 @@ const globals = {
|
|
|
1710
1707
|
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
1711
1708
|
const camera = computed(() => ensuredCamera.value?.instance ?? null);
|
|
1712
1709
|
/** Run a function using the current camera when it's present. */
|
|
1713
|
-
function useCamera(callback
|
|
1714
|
-
|
|
1715
|
-
destroy = watch(camera, (newVal) => {
|
|
1710
|
+
function useCamera(callback) {
|
|
1711
|
+
return watch(camera, (newVal) => {
|
|
1716
1712
|
if (!newVal)
|
|
1717
1713
|
return;
|
|
1718
|
-
// TODO: better fix than `any`?
|
|
1719
1714
|
callback(newVal);
|
|
1720
|
-
if (once) {
|
|
1721
|
-
destroy?.();
|
|
1722
|
-
}
|
|
1723
1715
|
}, { immediate: true });
|
|
1724
1716
|
}
|
|
1725
1717
|
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
1726
1718
|
const renderer = computed(() => ensureRenderer.value?.instance ?? null);
|
|
1727
1719
|
/** Run a function using the current renderer when it's present. */
|
|
1728
|
-
function useRenderer(callback
|
|
1729
|
-
|
|
1730
|
-
destroy = watch(renderer, (newVal) => {
|
|
1720
|
+
function useRenderer(callback) {
|
|
1721
|
+
return watch(renderer, (newVal) => {
|
|
1731
1722
|
if (!newVal)
|
|
1732
1723
|
return;
|
|
1733
|
-
// TODO: better fix than `any`?
|
|
1734
1724
|
callback(newVal);
|
|
1735
|
-
if (once) {
|
|
1736
|
-
destroy?.();
|
|
1737
|
-
}
|
|
1738
1725
|
}, { immediate: true });
|
|
1739
1726
|
}
|
|
1740
1727
|
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
1741
1728
|
const scene = computed(() => ensuredScene.value.instance);
|
|
1742
1729
|
/** Run a function using the current scene when it's present. */
|
|
1743
|
-
function useScene(callback
|
|
1744
|
-
|
|
1745
|
-
destroy = watch(scene, (newVal) => {
|
|
1730
|
+
function useScene(callback) {
|
|
1731
|
+
return watch(scene, (newVal) => {
|
|
1746
1732
|
if (!newVal)
|
|
1747
1733
|
return;
|
|
1748
|
-
// TODO: better fix than `any`?
|
|
1749
1734
|
callback(newVal);
|
|
1750
|
-
if (once) {
|
|
1751
|
-
destroy?.();
|
|
1752
|
-
}
|
|
1753
1735
|
}, { immediate: true });
|
|
1754
1736
|
}
|
|
1755
1737
|
// CUSTOM RENDER SUPPORT
|
|
@@ -1778,12 +1760,14 @@ const createApp = (root) => {
|
|
|
1778
1760
|
app = createRenderer(nodeOps).createApp(root);
|
|
1779
1761
|
// register all components
|
|
1780
1762
|
Object.keys(components).forEach((key) => {
|
|
1781
|
-
app
|
|
1763
|
+
app?.component(key, components[key]);
|
|
1782
1764
|
});
|
|
1783
1765
|
// update mount function to match Lunchbox.Node
|
|
1784
1766
|
const { mount } = app;
|
|
1785
1767
|
app.mount = (root, ...args) => {
|
|
1768
|
+
// find DOM element to use as app root
|
|
1786
1769
|
const domElement = (typeof root === 'string' ? document.querySelector(root) : root);
|
|
1770
|
+
// create or find root node
|
|
1787
1771
|
const rootNode = ensureRootNode({
|
|
1788
1772
|
domElement,
|
|
1789
1773
|
isLunchboxRootNode: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lunchboxjs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4014",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite -c utils/vite.config.ts",
|
|
6
6
|
"build": "vue-tsc --noEmit && vite build -c utils/vite.config.ts",
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
"prepare": "npm run build:lib",
|
|
12
12
|
"docs:dev": "vitepress dev docs",
|
|
13
13
|
"docs:build": "vitepress build docs",
|
|
14
|
-
"docs:serve": "vitepress serve docs"
|
|
14
|
+
"docs:serve": "vitepress serve docs",
|
|
15
|
+
"demo:create": "node utils/createExample"
|
|
15
16
|
},
|
|
16
17
|
"dependencies": {
|
|
17
|
-
"lodash": "4.17.21",
|
|
18
18
|
"uuid": "8.3.2",
|
|
19
19
|
"vue": "^3.2.16"
|
|
20
20
|
},
|
|
@@ -26,7 +26,11 @@
|
|
|
26
26
|
"@types/uuid": "8.3.1",
|
|
27
27
|
"@vitejs/plugin-vue": "^1.9.3",
|
|
28
28
|
"chroma-js": "2.1.2",
|
|
29
|
+
"kolorist": "1.5.1",
|
|
30
|
+
"lodash": "4.17.21",
|
|
29
31
|
"nice-color-palettes": "3.0.0",
|
|
32
|
+
"prompt": "1.3.0",
|
|
33
|
+
"prompts": "2.4.2",
|
|
30
34
|
"rollup-plugin-delete": "2.0.0",
|
|
31
35
|
"rollup-plugin-terser": "7.0.2",
|
|
32
36
|
"typescript": "^4.4.3",
|
package/src/.DS_Store
ADDED
|
Binary file
|
|
Binary file
|
package/src/core/createNode.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isLunchboxRootNode } from '../utils'
|
|
2
2
|
import { instantiateThreeObject, MiniDom, ensuredScene } from '.'
|
|
3
3
|
import { Lunch } from '..'
|
|
4
|
+
import { ensuredCamera } from './ensure'
|
|
4
5
|
|
|
5
6
|
/** Create a new Lunchbox comment node. */
|
|
6
7
|
export function createCommentNode(options: Partial<Lunch.CommentMeta> = {}) {
|
|
@@ -74,9 +75,12 @@ export function createNode<T extends object = THREE.Object3D>(
|
|
|
74
75
|
})
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
|
|
78
|
+
// TODO: these manual overrides are a bit brittle - replace?
|
|
79
|
+
if (node.type?.toLowerCase() === 'scene') {
|
|
78
80
|
// manually set scene override
|
|
79
81
|
ensuredScene.value = node as Lunch.Node<THREE.Scene>
|
|
82
|
+
} else if (node.type?.toLowerCase().endsWith('camera')) {
|
|
83
|
+
ensuredCamera.value = node as Lunch.Node<THREE.Camera>
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
return node
|
package/src/core/ensure.ts
CHANGED
|
@@ -158,18 +158,10 @@ export const ensuredCamera = computed<Lunch.Node<THREE.Camera> | null>({
|
|
|
158
158
|
},
|
|
159
159
|
})
|
|
160
160
|
|
|
161
|
-
// export const ensuredCamera = buildEnsured<THREE.Camera>(
|
|
162
|
-
// ['PerspectiveCamera', 'OrthographicCamera'],
|
|
163
|
-
// fallbackCameraUuid,
|
|
164
|
-
// {
|
|
165
|
-
// args: [45, 0.5625, 1, 1000],
|
|
166
|
-
// }
|
|
167
|
-
// )
|
|
168
|
-
|
|
169
161
|
// ENSURE RENDERER
|
|
170
162
|
// ====================
|
|
171
163
|
export const fallbackRendererUuid = 'FALLBACK_RENDERER'
|
|
172
|
-
export const
|
|
164
|
+
export const ensuredRenderer = buildEnsured(
|
|
173
165
|
// TODO: ensure support for css/svg renderers
|
|
174
166
|
['WebGLRenderer'], //, 'CSS2DRenderer', 'CSS3DRenderer', 'SVGRenderer'],
|
|
175
167
|
fallbackRendererUuid,
|
|
@@ -181,7 +173,9 @@ export const rendererReady = ref(false)
|
|
|
181
173
|
|
|
182
174
|
export const ensureRenderer = computed<Lunch.Node<THREE.WebGLRenderer> | null>({
|
|
183
175
|
get() {
|
|
184
|
-
return (
|
|
176
|
+
return (
|
|
177
|
+
rendererReady.value ? (ensuredRenderer.value as any) : (null as any)
|
|
178
|
+
) as any
|
|
185
179
|
},
|
|
186
180
|
set(val: any) {
|
|
187
181
|
const t = val.type ?? ''
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
computed,
|
|
3
|
-
createRenderer,
|
|
4
|
-
Component,
|
|
5
|
-
ref,
|
|
6
|
-
watch,
|
|
7
|
-
WatchStopHandle,
|
|
8
|
-
} from 'vue'
|
|
1
|
+
import { computed, createRenderer, Component, ref, watch } from 'vue'
|
|
9
2
|
import { nodeOps } from './nodeOps'
|
|
10
3
|
import {
|
|
11
4
|
// createdCamera,
|
|
@@ -47,20 +40,13 @@ export const globals = {
|
|
|
47
40
|
export const camera = computed(() => ensuredCamera.value?.instance ?? null)
|
|
48
41
|
/** Run a function using the current camera when it's present. */
|
|
49
42
|
export function useCamera<T extends THREE.Camera = THREE.PerspectiveCamera>(
|
|
50
|
-
callback: (cam: T) => void
|
|
51
|
-
once = true
|
|
43
|
+
callback: (cam: T) => void
|
|
52
44
|
) {
|
|
53
|
-
|
|
54
|
-
destroy = watch(
|
|
45
|
+
return watch(
|
|
55
46
|
camera,
|
|
56
47
|
(newVal) => {
|
|
57
48
|
if (!newVal) return
|
|
58
|
-
|
|
59
|
-
// TODO: better fix than `any`?
|
|
60
|
-
callback(newVal as any)
|
|
61
|
-
if (once) {
|
|
62
|
-
destroy?.()
|
|
63
|
-
}
|
|
49
|
+
callback(newVal as unknown as T)
|
|
64
50
|
},
|
|
65
51
|
{ immediate: true }
|
|
66
52
|
)
|
|
@@ -70,20 +56,13 @@ export function useCamera<T extends THREE.Camera = THREE.PerspectiveCamera>(
|
|
|
70
56
|
export const renderer = computed(() => ensureRenderer.value?.instance ?? null)
|
|
71
57
|
/** Run a function using the current renderer when it's present. */
|
|
72
58
|
export function useRenderer<T extends THREE.Renderer = THREE.WebGLRenderer>(
|
|
73
|
-
callback: (rend: T) => void
|
|
74
|
-
once = true
|
|
59
|
+
callback: (rend: T) => void
|
|
75
60
|
) {
|
|
76
|
-
|
|
77
|
-
destroy = watch(
|
|
61
|
+
return watch(
|
|
78
62
|
renderer,
|
|
79
63
|
(newVal) => {
|
|
80
64
|
if (!newVal) return
|
|
81
|
-
|
|
82
|
-
// TODO: better fix than `any`?
|
|
83
|
-
callback(newVal as any)
|
|
84
|
-
if (once) {
|
|
85
|
-
destroy?.()
|
|
86
|
-
}
|
|
65
|
+
callback(newVal as unknown as T)
|
|
87
66
|
},
|
|
88
67
|
{ immediate: true }
|
|
89
68
|
)
|
|
@@ -92,21 +71,12 @@ export function useRenderer<T extends THREE.Renderer = THREE.WebGLRenderer>(
|
|
|
92
71
|
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
93
72
|
export const scene = computed(() => ensuredScene.value.instance)
|
|
94
73
|
/** Run a function using the current scene when it's present. */
|
|
95
|
-
export function useScene(
|
|
96
|
-
|
|
97
|
-
once = true
|
|
98
|
-
) {
|
|
99
|
-
let destroy: WatchStopHandle
|
|
100
|
-
destroy = watch(
|
|
74
|
+
export function useScene(callback: (newScene: THREE.Scene) => void) {
|
|
75
|
+
return watch(
|
|
101
76
|
scene,
|
|
102
77
|
(newVal) => {
|
|
103
78
|
if (!newVal) return
|
|
104
|
-
|
|
105
|
-
// TODO: better fix than `any`?
|
|
106
79
|
callback(newVal as any)
|
|
107
|
-
if (once) {
|
|
108
|
-
destroy?.()
|
|
109
|
-
}
|
|
110
80
|
},
|
|
111
81
|
{ immediate: true }
|
|
112
82
|
)
|
|
@@ -142,15 +112,17 @@ export const createApp = (root: Component) => {
|
|
|
142
112
|
|
|
143
113
|
// register all components
|
|
144
114
|
Object.keys(components).forEach((key) => {
|
|
145
|
-
app
|
|
115
|
+
app?.component(key, (components as any)[key])
|
|
146
116
|
})
|
|
147
117
|
|
|
148
118
|
// update mount function to match Lunchbox.Node
|
|
149
119
|
const { mount } = app
|
|
150
120
|
app.mount = (root, ...args) => {
|
|
121
|
+
// find DOM element to use as app root
|
|
151
122
|
const domElement = (
|
|
152
123
|
typeof root === 'string' ? document.querySelector(root) : root
|
|
153
124
|
) as HTMLElement
|
|
125
|
+
// create or find root node
|
|
154
126
|
const rootNode = ensureRootNode({
|
|
155
127
|
domElement,
|
|
156
128
|
isLunchboxRootNode: true,
|
package/src/nodeOps/remove.ts
CHANGED