lunchboxjs 0.1.4011 → 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/LICENSE.md +7 -0
- package/README.md +14 -0
- package/dist/.DS_Store +0 -0
- package/dist/lunchboxjs.js +92 -102
- package/dist/lunchboxjs.min.js +1 -1
- package/dist/lunchboxjs.module.js +92 -102
- package/package.json +8 -4
- package/src/.DS_Store +0 -0
- package/src/components/LunchboxWrapper/LunchboxWrapper.ts +5 -0
- package/src/core/.DS_Store +0 -0
- package/src/core/createNode.ts +5 -1
- package/src/core/ensure.ts +6 -11
- package/src/index.ts +12 -40
- package/src/nodeOps/remove.ts +0 -1
- package/src/types.ts +1 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2022 Breakfast Studio, LLC
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
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
|
@@ -115,6 +115,7 @@
|
|
|
115
115
|
rendererProperties: Object,
|
|
116
116
|
shadow: [Boolean, Object],
|
|
117
117
|
transparent: Boolean,
|
|
118
|
+
zoom: Number,
|
|
118
119
|
},
|
|
119
120
|
setup(props, context) {
|
|
120
121
|
const canvas = vue.ref();
|
|
@@ -228,6 +229,10 @@
|
|
|
228
229
|
const source = (props.cameraLookAt || props.cameraLook);
|
|
229
230
|
camera.instance.lookAt(...source);
|
|
230
231
|
}
|
|
232
|
+
// zoom camera if needed
|
|
233
|
+
if (camera && props.zoom !== undefined) {
|
|
234
|
+
camera.instance.zoom = props.zoom;
|
|
235
|
+
}
|
|
231
236
|
// SCENE
|
|
232
237
|
// ====================
|
|
233
238
|
scene = ensuredScene.value;
|
|
@@ -539,76 +544,6 @@
|
|
|
539
544
|
return node.isLunchboxRootNode;
|
|
540
545
|
};
|
|
541
546
|
|
|
542
|
-
/** Create a new Lunchbox comment node. */
|
|
543
|
-
function createCommentNode(options = {}) {
|
|
544
|
-
const defaults = {
|
|
545
|
-
text: options.text ?? '',
|
|
546
|
-
};
|
|
547
|
-
return new MiniDom.RendererCommentNode({
|
|
548
|
-
...defaults,
|
|
549
|
-
...options,
|
|
550
|
-
metaType: 'commentMeta',
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
/** Create a new DOM node. */
|
|
554
|
-
function createDomNode(options = {}) {
|
|
555
|
-
const domElement = document.createElement(options.type ?? '');
|
|
556
|
-
const defaults = {
|
|
557
|
-
domElement,
|
|
558
|
-
};
|
|
559
|
-
const node = new MiniDom.RendererDomNode({
|
|
560
|
-
...defaults,
|
|
561
|
-
...options,
|
|
562
|
-
metaType: 'domMeta',
|
|
563
|
-
});
|
|
564
|
-
return node;
|
|
565
|
-
}
|
|
566
|
-
/** Create a new Lunchbox text node. */
|
|
567
|
-
function createTextNode(options = {}) {
|
|
568
|
-
const defaults = {
|
|
569
|
-
text: options.text ?? '',
|
|
570
|
-
};
|
|
571
|
-
return new MiniDom.RendererTextNode({
|
|
572
|
-
...options,
|
|
573
|
-
...defaults,
|
|
574
|
-
metaType: 'textMeta',
|
|
575
|
-
});
|
|
576
|
-
}
|
|
577
|
-
/** Create a new Lunchbox standard node. */
|
|
578
|
-
function createNode(options = {}, props = {}) {
|
|
579
|
-
const defaults = {
|
|
580
|
-
attached: options.attached ?? [],
|
|
581
|
-
attachedArray: options.attachedArray ?? {},
|
|
582
|
-
instance: options.instance ?? null,
|
|
583
|
-
};
|
|
584
|
-
const node = new MiniDom.RendererStandardNode({
|
|
585
|
-
...options,
|
|
586
|
-
...defaults,
|
|
587
|
-
metaType: 'standardMeta',
|
|
588
|
-
});
|
|
589
|
-
if (node.type && !isLunchboxRootNode(node) && !node.instance) {
|
|
590
|
-
// if (node.type.includes('Camera')) {
|
|
591
|
-
// console.log(node.type, {
|
|
592
|
-
// ...node.props,
|
|
593
|
-
// ...props,
|
|
594
|
-
// })
|
|
595
|
-
// console.trace()
|
|
596
|
-
// }
|
|
597
|
-
node.instance = instantiateThreeObject({
|
|
598
|
-
...node,
|
|
599
|
-
props: {
|
|
600
|
-
...node.props,
|
|
601
|
-
...props,
|
|
602
|
-
},
|
|
603
|
-
});
|
|
604
|
-
}
|
|
605
|
-
if (node.type === 'scene') {
|
|
606
|
-
// manually set scene override
|
|
607
|
-
ensuredScene.value = node;
|
|
608
|
-
}
|
|
609
|
-
return node;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
547
|
const interactables = [];
|
|
613
548
|
const addInteractable = (target) => {
|
|
614
549
|
interactables.push(target);
|
|
@@ -840,7 +775,8 @@
|
|
|
840
775
|
singleType.toLowerCase());
|
|
841
776
|
// cancel if found example is marked !isDefault
|
|
842
777
|
if (isMinidomNode(found) &&
|
|
843
|
-
(
|
|
778
|
+
(found.props['is-default'] === false ||
|
|
779
|
+
!found.props['isDefault'] === false)) {
|
|
844
780
|
return null;
|
|
845
781
|
}
|
|
846
782
|
// if we have one, save and return
|
|
@@ -933,17 +869,10 @@
|
|
|
933
869
|
overrides[pascalType] = val;
|
|
934
870
|
},
|
|
935
871
|
});
|
|
936
|
-
// export const ensuredCamera = buildEnsured<THREE.Camera>(
|
|
937
|
-
// ['PerspectiveCamera', 'OrthographicCamera'],
|
|
938
|
-
// fallbackCameraUuid,
|
|
939
|
-
// {
|
|
940
|
-
// args: [45, 0.5625, 1, 1000],
|
|
941
|
-
// }
|
|
942
|
-
// )
|
|
943
872
|
// ENSURE RENDERER
|
|
944
873
|
// ====================
|
|
945
874
|
const fallbackRendererUuid = 'FALLBACK_RENDERER';
|
|
946
|
-
const
|
|
875
|
+
const ensuredRenderer = buildEnsured(
|
|
947
876
|
// TODO: ensure support for css/svg renderers
|
|
948
877
|
['WebGLRenderer'], //, 'CSS2DRenderer', 'CSS3DRenderer', 'SVGRenderer'],
|
|
949
878
|
fallbackRendererUuid, {});
|
|
@@ -952,7 +881,7 @@
|
|
|
952
881
|
const rendererReady = vue.ref(false);
|
|
953
882
|
const ensureRenderer = vue.computed({
|
|
954
883
|
get() {
|
|
955
|
-
return (rendererReady.value ?
|
|
884
|
+
return (rendererReady.value ? ensuredRenderer.value : null);
|
|
956
885
|
},
|
|
957
886
|
set(val) {
|
|
958
887
|
const t = val.type ?? '';
|
|
@@ -969,6 +898,80 @@
|
|
|
969
898
|
// `unknown` is intentional here - we need to typecast the node since Raycaster isn't an Object3D
|
|
970
899
|
const ensuredRaycaster = buildEnsured('Raycaster', autoRaycasterUuid, {}, (node) => setupAutoRaycaster(node));
|
|
971
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
|
+
|
|
972
975
|
const createComponent = (tag) => vue.defineComponent({
|
|
973
976
|
inheritAttrs: false,
|
|
974
977
|
name: tag,
|
|
@@ -1725,46 +1728,31 @@
|
|
|
1725
1728
|
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
1726
1729
|
const camera = vue.computed(() => ensuredCamera.value?.instance ?? null);
|
|
1727
1730
|
/** Run a function using the current camera when it's present. */
|
|
1728
|
-
function useCamera(callback
|
|
1729
|
-
|
|
1730
|
-
destroy = vue.watch(camera, (newVal) => {
|
|
1731
|
+
function useCamera(callback) {
|
|
1732
|
+
return vue.watch(camera, (newVal) => {
|
|
1731
1733
|
if (!newVal)
|
|
1732
1734
|
return;
|
|
1733
|
-
// TODO: better fix than `any`?
|
|
1734
1735
|
callback(newVal);
|
|
1735
|
-
if (once) {
|
|
1736
|
-
destroy?.();
|
|
1737
|
-
}
|
|
1738
1736
|
}, { immediate: true });
|
|
1739
1737
|
}
|
|
1740
1738
|
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
1741
1739
|
const renderer = vue.computed(() => ensureRenderer.value?.instance ?? null);
|
|
1742
1740
|
/** Run a function using the current renderer when it's present. */
|
|
1743
|
-
function useRenderer(callback
|
|
1744
|
-
|
|
1745
|
-
destroy = vue.watch(renderer, (newVal) => {
|
|
1741
|
+
function useRenderer(callback) {
|
|
1742
|
+
return vue.watch(renderer, (newVal) => {
|
|
1746
1743
|
if (!newVal)
|
|
1747
1744
|
return;
|
|
1748
|
-
// TODO: better fix than `any`?
|
|
1749
1745
|
callback(newVal);
|
|
1750
|
-
if (once) {
|
|
1751
|
-
destroy?.();
|
|
1752
|
-
}
|
|
1753
1746
|
}, { immediate: true });
|
|
1754
1747
|
}
|
|
1755
1748
|
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
1756
1749
|
const scene = vue.computed(() => ensuredScene.value.instance);
|
|
1757
1750
|
/** Run a function using the current scene when it's present. */
|
|
1758
|
-
function useScene(callback
|
|
1759
|
-
|
|
1760
|
-
destroy = vue.watch(scene, (newVal) => {
|
|
1751
|
+
function useScene(callback) {
|
|
1752
|
+
return vue.watch(scene, (newVal) => {
|
|
1761
1753
|
if (!newVal)
|
|
1762
1754
|
return;
|
|
1763
|
-
// TODO: better fix than `any`?
|
|
1764
1755
|
callback(newVal);
|
|
1765
|
-
if (once) {
|
|
1766
|
-
destroy?.();
|
|
1767
|
-
}
|
|
1768
1756
|
}, { immediate: true });
|
|
1769
1757
|
}
|
|
1770
1758
|
// CUSTOM RENDER SUPPORT
|
|
@@ -1793,12 +1781,14 @@
|
|
|
1793
1781
|
app = vue.createRenderer(nodeOps).createApp(root);
|
|
1794
1782
|
// register all components
|
|
1795
1783
|
Object.keys(components).forEach((key) => {
|
|
1796
|
-
app
|
|
1784
|
+
app?.component(key, components[key]);
|
|
1797
1785
|
});
|
|
1798
1786
|
// update mount function to match Lunchbox.Node
|
|
1799
1787
|
const { mount } = app;
|
|
1800
1788
|
app.mount = (root, ...args) => {
|
|
1789
|
+
// find DOM element to use as app root
|
|
1801
1790
|
const domElement = (typeof root === 'string' ? document.querySelector(root) : root);
|
|
1791
|
+
// create or find root node
|
|
1802
1792
|
const rootNode = ensureRootNode({
|
|
1803
1793
|
domElement,
|
|
1804
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=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})}));
|
|
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})}));
|
|
@@ -94,6 +94,7 @@ const LunchboxWrapper = {
|
|
|
94
94
|
rendererProperties: Object,
|
|
95
95
|
shadow: [Boolean, Object],
|
|
96
96
|
transparent: Boolean,
|
|
97
|
+
zoom: Number,
|
|
97
98
|
},
|
|
98
99
|
setup(props, context) {
|
|
99
100
|
const canvas = ref();
|
|
@@ -207,6 +208,10 @@ const LunchboxWrapper = {
|
|
|
207
208
|
const source = (props.cameraLookAt || props.cameraLook);
|
|
208
209
|
camera.instance.lookAt(...source);
|
|
209
210
|
}
|
|
211
|
+
// zoom camera if needed
|
|
212
|
+
if (camera && props.zoom !== undefined) {
|
|
213
|
+
camera.instance.zoom = props.zoom;
|
|
214
|
+
}
|
|
210
215
|
// SCENE
|
|
211
216
|
// ====================
|
|
212
217
|
scene = ensuredScene.value;
|
|
@@ -518,76 +523,6 @@ const isLunchboxRootNode = (node) => {
|
|
|
518
523
|
return node.isLunchboxRootNode;
|
|
519
524
|
};
|
|
520
525
|
|
|
521
|
-
/** Create a new Lunchbox comment node. */
|
|
522
|
-
function createCommentNode(options = {}) {
|
|
523
|
-
const defaults = {
|
|
524
|
-
text: options.text ?? '',
|
|
525
|
-
};
|
|
526
|
-
return new MiniDom.RendererCommentNode({
|
|
527
|
-
...defaults,
|
|
528
|
-
...options,
|
|
529
|
-
metaType: 'commentMeta',
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
/** Create a new DOM node. */
|
|
533
|
-
function createDomNode(options = {}) {
|
|
534
|
-
const domElement = document.createElement(options.type ?? '');
|
|
535
|
-
const defaults = {
|
|
536
|
-
domElement,
|
|
537
|
-
};
|
|
538
|
-
const node = new MiniDom.RendererDomNode({
|
|
539
|
-
...defaults,
|
|
540
|
-
...options,
|
|
541
|
-
metaType: 'domMeta',
|
|
542
|
-
});
|
|
543
|
-
return node;
|
|
544
|
-
}
|
|
545
|
-
/** Create a new Lunchbox text node. */
|
|
546
|
-
function createTextNode(options = {}) {
|
|
547
|
-
const defaults = {
|
|
548
|
-
text: options.text ?? '',
|
|
549
|
-
};
|
|
550
|
-
return new MiniDom.RendererTextNode({
|
|
551
|
-
...options,
|
|
552
|
-
...defaults,
|
|
553
|
-
metaType: 'textMeta',
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
/** Create a new Lunchbox standard node. */
|
|
557
|
-
function createNode(options = {}, props = {}) {
|
|
558
|
-
const defaults = {
|
|
559
|
-
attached: options.attached ?? [],
|
|
560
|
-
attachedArray: options.attachedArray ?? {},
|
|
561
|
-
instance: options.instance ?? null,
|
|
562
|
-
};
|
|
563
|
-
const node = new MiniDom.RendererStandardNode({
|
|
564
|
-
...options,
|
|
565
|
-
...defaults,
|
|
566
|
-
metaType: 'standardMeta',
|
|
567
|
-
});
|
|
568
|
-
if (node.type && !isLunchboxRootNode(node) && !node.instance) {
|
|
569
|
-
// if (node.type.includes('Camera')) {
|
|
570
|
-
// console.log(node.type, {
|
|
571
|
-
// ...node.props,
|
|
572
|
-
// ...props,
|
|
573
|
-
// })
|
|
574
|
-
// console.trace()
|
|
575
|
-
// }
|
|
576
|
-
node.instance = instantiateThreeObject({
|
|
577
|
-
...node,
|
|
578
|
-
props: {
|
|
579
|
-
...node.props,
|
|
580
|
-
...props,
|
|
581
|
-
},
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
if (node.type === 'scene') {
|
|
585
|
-
// manually set scene override
|
|
586
|
-
ensuredScene.value = node;
|
|
587
|
-
}
|
|
588
|
-
return node;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
526
|
const interactables = [];
|
|
592
527
|
const addInteractable = (target) => {
|
|
593
528
|
interactables.push(target);
|
|
@@ -819,7 +754,8 @@ function tryGetNodeWithInstanceType(pascalCaseTypes) {
|
|
|
819
754
|
singleType.toLowerCase());
|
|
820
755
|
// cancel if found example is marked !isDefault
|
|
821
756
|
if (isMinidomNode(found) &&
|
|
822
|
-
(
|
|
757
|
+
(found.props['is-default'] === false ||
|
|
758
|
+
!found.props['isDefault'] === false)) {
|
|
823
759
|
return null;
|
|
824
760
|
}
|
|
825
761
|
// if we have one, save and return
|
|
@@ -912,17 +848,10 @@ const ensuredCamera = computed({
|
|
|
912
848
|
overrides[pascalType] = val;
|
|
913
849
|
},
|
|
914
850
|
});
|
|
915
|
-
// export const ensuredCamera = buildEnsured<THREE.Camera>(
|
|
916
|
-
// ['PerspectiveCamera', 'OrthographicCamera'],
|
|
917
|
-
// fallbackCameraUuid,
|
|
918
|
-
// {
|
|
919
|
-
// args: [45, 0.5625, 1, 1000],
|
|
920
|
-
// }
|
|
921
|
-
// )
|
|
922
851
|
// ENSURE RENDERER
|
|
923
852
|
// ====================
|
|
924
853
|
const fallbackRendererUuid = 'FALLBACK_RENDERER';
|
|
925
|
-
const
|
|
854
|
+
const ensuredRenderer = buildEnsured(
|
|
926
855
|
// TODO: ensure support for css/svg renderers
|
|
927
856
|
['WebGLRenderer'], //, 'CSS2DRenderer', 'CSS3DRenderer', 'SVGRenderer'],
|
|
928
857
|
fallbackRendererUuid, {});
|
|
@@ -931,7 +860,7 @@ fallbackRendererUuid, {});
|
|
|
931
860
|
const rendererReady = ref(false);
|
|
932
861
|
const ensureRenderer = computed({
|
|
933
862
|
get() {
|
|
934
|
-
return (rendererReady.value ?
|
|
863
|
+
return (rendererReady.value ? ensuredRenderer.value : null);
|
|
935
864
|
},
|
|
936
865
|
set(val) {
|
|
937
866
|
const t = val.type ?? '';
|
|
@@ -948,6 +877,80 @@ const autoRaycasterUuid = 'AUTO_RAYCASTER';
|
|
|
948
877
|
// `unknown` is intentional here - we need to typecast the node since Raycaster isn't an Object3D
|
|
949
878
|
const ensuredRaycaster = buildEnsured('Raycaster', autoRaycasterUuid, {}, (node) => setupAutoRaycaster(node));
|
|
950
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
|
+
|
|
951
954
|
const createComponent = (tag) => defineComponent({
|
|
952
955
|
inheritAttrs: false,
|
|
953
956
|
name: tag,
|
|
@@ -1704,46 +1707,31 @@ const globals = {
|
|
|
1704
1707
|
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
1705
1708
|
const camera = computed(() => ensuredCamera.value?.instance ?? null);
|
|
1706
1709
|
/** Run a function using the current camera when it's present. */
|
|
1707
|
-
function useCamera(callback
|
|
1708
|
-
|
|
1709
|
-
destroy = watch(camera, (newVal) => {
|
|
1710
|
+
function useCamera(callback) {
|
|
1711
|
+
return watch(camera, (newVal) => {
|
|
1710
1712
|
if (!newVal)
|
|
1711
1713
|
return;
|
|
1712
|
-
// TODO: better fix than `any`?
|
|
1713
1714
|
callback(newVal);
|
|
1714
|
-
if (once) {
|
|
1715
|
-
destroy?.();
|
|
1716
|
-
}
|
|
1717
1715
|
}, { immediate: true });
|
|
1718
1716
|
}
|
|
1719
1717
|
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
1720
1718
|
const renderer = computed(() => ensureRenderer.value?.instance ?? null);
|
|
1721
1719
|
/** Run a function using the current renderer when it's present. */
|
|
1722
|
-
function useRenderer(callback
|
|
1723
|
-
|
|
1724
|
-
destroy = watch(renderer, (newVal) => {
|
|
1720
|
+
function useRenderer(callback) {
|
|
1721
|
+
return watch(renderer, (newVal) => {
|
|
1725
1722
|
if (!newVal)
|
|
1726
1723
|
return;
|
|
1727
|
-
// TODO: better fix than `any`?
|
|
1728
1724
|
callback(newVal);
|
|
1729
|
-
if (once) {
|
|
1730
|
-
destroy?.();
|
|
1731
|
-
}
|
|
1732
1725
|
}, { immediate: true });
|
|
1733
1726
|
}
|
|
1734
1727
|
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
1735
1728
|
const scene = computed(() => ensuredScene.value.instance);
|
|
1736
1729
|
/** Run a function using the current scene when it's present. */
|
|
1737
|
-
function useScene(callback
|
|
1738
|
-
|
|
1739
|
-
destroy = watch(scene, (newVal) => {
|
|
1730
|
+
function useScene(callback) {
|
|
1731
|
+
return watch(scene, (newVal) => {
|
|
1740
1732
|
if (!newVal)
|
|
1741
1733
|
return;
|
|
1742
|
-
// TODO: better fix than `any`?
|
|
1743
1734
|
callback(newVal);
|
|
1744
|
-
if (once) {
|
|
1745
|
-
destroy?.();
|
|
1746
|
-
}
|
|
1747
1735
|
}, { immediate: true });
|
|
1748
1736
|
}
|
|
1749
1737
|
// CUSTOM RENDER SUPPORT
|
|
@@ -1772,12 +1760,14 @@ const createApp = (root) => {
|
|
|
1772
1760
|
app = createRenderer(nodeOps).createApp(root);
|
|
1773
1761
|
// register all components
|
|
1774
1762
|
Object.keys(components).forEach((key) => {
|
|
1775
|
-
app
|
|
1763
|
+
app?.component(key, components[key]);
|
|
1776
1764
|
});
|
|
1777
1765
|
// update mount function to match Lunchbox.Node
|
|
1778
1766
|
const { mount } = app;
|
|
1779
1767
|
app.mount = (root, ...args) => {
|
|
1768
|
+
// find DOM element to use as app root
|
|
1780
1769
|
const domElement = (typeof root === 'string' ? document.querySelector(root) : root);
|
|
1770
|
+
// create or find root node
|
|
1781
1771
|
const rootNode = ensureRootNode({
|
|
1782
1772
|
domElement,
|
|
1783
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",
|
|
@@ -36,7 +40,7 @@
|
|
|
36
40
|
"vue-tsc": "^0.3.0"
|
|
37
41
|
},
|
|
38
42
|
"peerDependencies": {
|
|
39
|
-
"three": "
|
|
43
|
+
"three": "0.137.5"
|
|
40
44
|
},
|
|
41
45
|
"files": [
|
|
42
46
|
"dist",
|
package/src/.DS_Store
ADDED
|
Binary file
|
|
@@ -56,6 +56,7 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
56
56
|
rendererProperties: Object,
|
|
57
57
|
shadow: [Boolean, Object],
|
|
58
58
|
transparent: Boolean,
|
|
59
|
+
zoom: Number,
|
|
59
60
|
},
|
|
60
61
|
setup(props: Lunch.WrapperProps, context) {
|
|
61
62
|
const canvas = ref<MiniDom.RendererDomNode>()
|
|
@@ -184,6 +185,10 @@ export const LunchboxWrapper: ComponentOptions = {
|
|
|
184
185
|
const source = (props.cameraLookAt || props.cameraLook)!
|
|
185
186
|
camera.instance.lookAt(...source)
|
|
186
187
|
}
|
|
188
|
+
// zoom camera if needed
|
|
189
|
+
if (camera && props.zoom !== undefined) {
|
|
190
|
+
;(camera.instance as THREE.OrthographicCamera).zoom = props.zoom
|
|
191
|
+
}
|
|
187
192
|
|
|
188
193
|
// SCENE
|
|
189
194
|
// ====================
|
|
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
|
@@ -41,7 +41,8 @@ export function tryGetNodeWithInstanceType<T extends THREE.Object3D>(
|
|
|
41
41
|
// cancel if found example is marked !isDefault
|
|
42
42
|
if (
|
|
43
43
|
isMinidomNode(found) &&
|
|
44
|
-
(
|
|
44
|
+
(found.props['is-default'] === false ||
|
|
45
|
+
!found.props['isDefault'] === false)
|
|
45
46
|
) {
|
|
46
47
|
return null
|
|
47
48
|
}
|
|
@@ -157,18 +158,10 @@ export const ensuredCamera = computed<Lunch.Node<THREE.Camera> | null>({
|
|
|
157
158
|
},
|
|
158
159
|
})
|
|
159
160
|
|
|
160
|
-
// export const ensuredCamera = buildEnsured<THREE.Camera>(
|
|
161
|
-
// ['PerspectiveCamera', 'OrthographicCamera'],
|
|
162
|
-
// fallbackCameraUuid,
|
|
163
|
-
// {
|
|
164
|
-
// args: [45, 0.5625, 1, 1000],
|
|
165
|
-
// }
|
|
166
|
-
// )
|
|
167
|
-
|
|
168
161
|
// ENSURE RENDERER
|
|
169
162
|
// ====================
|
|
170
163
|
export const fallbackRendererUuid = 'FALLBACK_RENDERER'
|
|
171
|
-
export const
|
|
164
|
+
export const ensuredRenderer = buildEnsured(
|
|
172
165
|
// TODO: ensure support for css/svg renderers
|
|
173
166
|
['WebGLRenderer'], //, 'CSS2DRenderer', 'CSS3DRenderer', 'SVGRenderer'],
|
|
174
167
|
fallbackRendererUuid,
|
|
@@ -180,7 +173,9 @@ export const rendererReady = ref(false)
|
|
|
180
173
|
|
|
181
174
|
export const ensureRenderer = computed<Lunch.Node<THREE.WebGLRenderer> | null>({
|
|
182
175
|
get() {
|
|
183
|
-
return (
|
|
176
|
+
return (
|
|
177
|
+
rendererReady.value ? (ensuredRenderer.value as any) : (null as any)
|
|
178
|
+
) as any
|
|
184
179
|
},
|
|
185
180
|
set(val: any) {
|
|
186
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