lunchboxjs 0.1.4004 → 0.1.4005

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 CHANGED
@@ -0,0 +1,3 @@
1
+ Custom Vue 3 renderer for ThreeJS.
2
+
3
+ [Docs](//docs.lunchboxjs.com)
@@ -105,6 +105,8 @@
105
105
  // These should match the Lunchbox.WrapperProps interface
106
106
  background: String,
107
107
  cameraArgs: Array,
108
+ cameraLook: Array,
109
+ cameraLookAt: Array,
108
110
  cameraPosition: Array,
109
111
  dpr: Number,
110
112
  ortho: Boolean,
@@ -194,7 +196,6 @@
194
196
  if (!camera) {
195
197
  // create ortho camera
196
198
  if (props.ortho || props.orthographic) {
197
- // const size: Vector2 = new Vector2()
198
199
  ensuredCamera.value = createNode({
199
200
  props: { args: props.cameraArgs ?? [] },
200
201
  type: 'OrthographicCamera',
@@ -220,6 +221,11 @@
220
221
  if (camera && props.cameraPosition) {
221
222
  camera.instance?.position.set(...props.cameraPosition);
222
223
  }
224
+ // angle camera if needed
225
+ if (camera && (props.cameraLookAt || props.cameraLook)) {
226
+ const source = (props.cameraLookAt || props.cameraLook);
227
+ camera.instance?.lookAt(...source);
228
+ }
223
229
  // SCENE
224
230
  // ====================
225
231
  scene = ensuredScene.value;
@@ -276,21 +282,6 @@
276
282
  },
277
283
  };
278
284
 
279
- const catalogue = {};
280
-
281
- const lunchboxDomComponentNames = [
282
- 'canvas',
283
- 'div',
284
- 'LunchboxWrapper',
285
- ];
286
- // component creation utility
287
- const createComponent$1 = (tag) => vue.defineComponent({
288
- inheritAttrs: false,
289
- name: tag,
290
- setup(props, context) {
291
- return () => vue.h(tag, context.attrs, context.slots?.default?.() || []);
292
- },
293
- });
294
285
  // list of all components to register out of the box
295
286
  const autoGeneratedComponents = [
296
287
  // ThreeJS basics
@@ -403,21 +394,11 @@
403
394
  'arrayCamera',
404
395
  // renderers
405
396
  'webGLRenderer',
406
- ].map(createComponent$1).reduce((acc, curr) => {
407
- acc[curr.name] = curr;
408
- return acc;
409
- });
410
- const components = {
411
- ...autoGeneratedComponents,
412
- 'Lunchbox': LunchboxWrapper,
413
- // Gltf,
414
- };
415
- // console.log(components, Gltf)
416
- /*
417
- // List copied from r3f
418
- // https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/three-types.ts
397
+ /*
398
+ // List copied from r3f:
399
+ // https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/three-types.ts
419
400
 
420
- // NOT IMPLEMENTED:
401
+ // NOT IMPLEMENTED (can be added via Extend - docs.lunchboxjs.com/components/extend/):
421
402
  audioListener: AudioListenerProps
422
403
  positionalAudio: PositionalAudioProps
423
404
 
@@ -465,6 +446,27 @@
465
446
  fogExp2: FogExp2Props
466
447
  shape: ShapeProps
467
448
  */
449
+ ];
450
+
451
+ const catalogue = {};
452
+
453
+ const lunchboxDomComponentNames = ['canvas', 'div', 'LunchboxWrapper'];
454
+ // component creation utility
455
+ const createComponent$1 = (tag) => vue.defineComponent({
456
+ inheritAttrs: false,
457
+ name: tag,
458
+ setup(props, context) {
459
+ return () => vue.h(tag, context.attrs, context.slots?.default?.() || []);
460
+ },
461
+ });
462
+ autoGeneratedComponents.map(createComponent$1).reduce((acc, curr) => {
463
+ acc[curr.name] = curr;
464
+ return acc;
465
+ });
466
+ const components = {
467
+ ...autoGeneratedComponents,
468
+ Lunchbox: LunchboxWrapper,
469
+ };
468
470
 
469
471
  function find(target) {
470
472
  target = vue.isRef(target) ? target.value : target;
@@ -1301,6 +1303,15 @@
1301
1303
  beforeRender.splice(index, 0, cb);
1302
1304
  }
1303
1305
  };
1306
+ const offBeforeRender = (cb) => {
1307
+ if (isFinite(cb)) {
1308
+ beforeRender.splice(cb, 1);
1309
+ }
1310
+ else {
1311
+ const idx = beforeRender.findIndex((v) => v == cb);
1312
+ beforeRender.splice(idx, 1);
1313
+ }
1314
+ };
1304
1315
  const onAfterRender = (cb, index = Infinity) => {
1305
1316
  if (index === Infinity) {
1306
1317
  afterRender.push(cb);
@@ -1309,6 +1320,15 @@
1309
1320
  afterRender.splice(index, 0, cb);
1310
1321
  }
1311
1322
  };
1323
+ const offAfterRender = (cb) => {
1324
+ if (isFinite(cb)) {
1325
+ afterRender.splice(cb, 1);
1326
+ }
1327
+ else {
1328
+ const idx = afterRender.findIndex((v) => v == cb);
1329
+ afterRender.splice(idx, 1);
1330
+ }
1331
+ };
1312
1332
  const cancelUpdate = () => {
1313
1333
  if (frameID)
1314
1334
  cancelAnimationFrame(frameID);
@@ -1736,6 +1756,8 @@
1736
1756
  exports.createApp = createApp;
1737
1757
  exports.find = find;
1738
1758
  exports.globals = globals;
1759
+ exports.offAfterRender = offAfterRender;
1760
+ exports.offBeforeRender = offBeforeRender;
1739
1761
  exports.onAfterRender = onAfterRender;
1740
1762
  exports.onBeforeRender = onBeforeRender;
1741
1763
  exports.renderer = renderer;
@@ -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,cameraPosition:Array,dpr:Number,ortho:Boolean,orthographic:Boolean,rendererProperties:Object,shadow:[Boolean,Object],transparent:Boolean},setup(e,o){const a=t.ref(),s=t.ref(!0),d=t.ref(e.dpr??-1),u=t.ref();let l,p,m;return t.onMounted((()=>{if(!a.value)throw new Error("missing canvas");if(l=N(["WebGLRenderer"]),l)return s.value=!1,void(W.value=!0);{const t={antialias:!0,canvas:a.value.domElement};e.transparent&&(t.alpha=!0),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=N(["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&&e.cameraPosition&&p.instance?.position.set(...e.cameraPosition),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),me.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),oe({app:t.getCurrentInstance().appContext.app,camera:p.instance,renderer:l.instance,scene:m.instance})})),t.onBeforeUnmount((()=>{se()})),()=>[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,C,E;const A=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(me.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 G(t={}){return e.lunchboxTree||(e.lunchboxTree=new J.RendererRootNode(t)),e.lunchboxTree}function N(e){Array.isArray(e)||(e=[e]);for(let t of e)if(O[t])return O[t];for(let t of e){const e=T[t]||s.find((e=>e.type?.toLowerCase()===t.toLowerCase()));if(e){const n=e;return T[t]=n,n}}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=N(e);if(t)return t;const a=G(),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)/me.dpr.value,r=(e.instance.domElement.height??1)/me.dpr.value;A.value.x=t.offsetX/n*2-1,A.value.y=-t.offsetY/r*2+1},C=()=>b.value=!0,E=()=>b.value=!1,e.instance.domElement.addEventListener("mousemove",w),e.instance.domElement.addEventListener("mousedown",C),e.instance.domElement.addEventListener("mouseup",E),ae(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={}));let te;(new J.RendererRootNode).minidomType="RootNode";const ne=[],re=[],oe=e=>{te=requestAnimationFrame((()=>oe({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;ne.forEach((t=>{t&&t(e)})),r&&o&&a&&(n.customRender?n.customRender(e):r.render(t.toRaw(o),t.toRaw(a))),re.forEach((t=>{t&&t(e)}))},ae=(e,t=1/0)=>{t===1/0?ne.push(e):ne.splice(t,0,e)},se=()=>{te&&cancelAnimationFrame(te)};const ie={x:"position.x",y:"position.y",z:"position.z"},ce=["","parameters"],de=["args","attach","attachArray","key","onAdded","ref","src"],ue=["geometry","material"];function le(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 pe={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 ue.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??G();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);le(e,t,e.props.attach,r)}else n.load(e.props.src,(n=>{le(e,t,e.props.attach,n)}),null,(e=>{throw new Error(e)}))}(e,t):le(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});if(de.includes(t))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 o=e.instance;if(!o)return e;const a=t.replace(/-/g,".");let s,i=ie[a]||a;for(let e=0;e<ce.length&&!s;e++){const t=[ce[e],i].filter(Boolean).join(".");s=s=r.get(o,t)}if(s&&r.isNumber(n)&&s.setScalar)s.setScalar(n);else if(s&&s.set){const e=Array.isArray(n)?n:[n];o[i].set(...e)}else"function"==typeof s?s.bind(e.instance)(...n):void 0!==r.get(o,i,void 0)?r.set(o,i,""===n||n):console.log(`No property ${i} found on ${o}`);const c=o?.texture?.type||o?.type;if("string"==typeof c){const e=c.toLowerCase();switch(!0){case e.includes("material"):o.needsUpdate=!0;break;case e.includes("camera")&&o.updateProjectionMatrix:o.updateProjectionMatrix()}}}({node:e,key:t,value:o})},remove:e=>{if(!e)return;const t=Object.keys(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(){}},me={dpr:t.ref(1),inputActive:b,mousePos:A},he=t.computed((()=>F.value?.instance??null)),fe=t.computed((()=>I.value?.instance??null)),ye=t.computed((()=>K.value.instance));let ve=null,ge=null;e.camera=he,e.clearCustomRender=()=>{ve?ve.clearCustomRender():ge=null},e.createApp=e=>{ve=t.createRenderer(pe).createApp(e),Object.keys(p).forEach((e=>{ve.component(e,p[e])}));const{mount:n}=ve;return ve.mount=(e,...t)=>{const r=G({domElement:"string"==typeof e?document.querySelector(e):e,isLunchboxRootNode:!0,name:"root",metaType:"rootMeta",type:"root",uuid:"LUNCHBOX_ROOT"});ve.rootNode=r;return n(r,...t)},ve.extend=e=>((({app:e,...t})=>{Object.keys(t).forEach((n=>{e.component(n,V(n)),u[n]=t[n]}))})({app:ve,...e}),ve),ve.setCustomRender=e=>{ve.customRender=e},ge&&(ve.setCustomRender(ge),ge=null),ve.clearCustomRender=()=>{ve.customRender=null},ve},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=me,e.onAfterRender=(e,t=1/0)=>{t===1/0?re.push(e):re.splice(t,0,e)},e.onBeforeRender=ae,e.renderer=fe,e.scene=ye,e.setCustomRender=e=>{ve?ve.setCustomRender(e):ge=e},Object.defineProperty(e,"__esModule",{value:!0})}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue"),require("three"),require("lodash")):"function"==typeof define&&define.amd?define(["exports","vue","three","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LunchboxRenderer={},e.vue,e.three,e.lodash)}(this,(function(e,t,n,r){"use strict";function o(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var a=o(n);const s=[],i=(e,n)=>{const r=K.value?.instance,o=_.value.instance,a=$.value;if(!r?.domElement||!o||!a)return;const s=(e=e??window.innerWidth)/(n=n??window.innerHeight);if("perspectivecamera"===a.type?.toLowerCase()){const e=a.instance;e.aspect=s,e.updateProjectionMatrix()}else if("orthographiccamera"===a.type?.toLowerCase()){const t=a.instance,r=n/e;t.top=10*r,t.bottom=10*-r,t.right=10,t.left=-10,t.updateProjectionMatrix()}else console.log("TODO: non-ortho or perspective camera");r.setSize(e,n),o&&a.instance&&r.render(t.toRaw(o),t.toRaw(a.instance))},c=e=>({position:e,top:0,right:0,bottom:0,left:0,width:"100%",height:"100%"}),d={name:"Lunchbox",props:{background:String,cameraArgs:Array,cameraLook:Array,cameraLookAt:Array,cameraPosition:Array,dpr:Number,ortho:Boolean,orthographic:Boolean,rendererProperties:Object,shadow:[Boolean,Object],transparent:Boolean},setup(e,o){const a=t.ref(),s=t.ref(!0),d=t.ref(e.dpr??-1),u=t.ref();let l,p,m;return t.onMounted((()=>{if(!a.value)throw new Error("missing canvas");if(l=T(["WebGLRenderer"]),l)return s.value=!1,void(I.value=!0);{const t={antialias:!0,canvas:a.value.domElement};e.transparent&&(t.alpha=!0),K.value=g({type:"WebGLRenderer",uuid:U,props:{args:[t]}}),I.value=!0;const n=K,o={shadow:e.shadow};n.value.instance&&o?.shadow&&(n.value.instance.shadowMap.enabled=!0,"object"==typeof o.shadow&&(n.value.instance.shadowMap.type=o.shadow.type)),e.rendererProperties&&Object.keys(e.rendererProperties).forEach((t=>{r.set(n.value,t,e.rendererProperties[t])})),l=n.value}if(p=T(["PerspectiveCamera","OrthographicCamera"]),p?D.value=!0:(e.ortho||e.orthographic?$.value=g({props:{args:e.cameraArgs??[]},type:"OrthographicCamera",uuid:F}):$.value=g({props:{args:e.cameraArgs??[45,.5625,1,1e3]},type:"PerspectiveCamera",uuid:F}),D.value=!0,p=$.value),p&&e.cameraPosition&&p.instance?.position.set(...e.cameraPosition),p&&(e.cameraLookAt||e.cameraLook)){const t=e.cameraLookAt||e.cameraLook;p.instance?.lookAt(...t)}if(m=_.value,m&&m.instance&&e.background&&(m.instance.background=new n.Color(e.background)),-1===d.value&&(d.value=window.devicePixelRatio),!l?.instance)throw new Error("missing renderer");l.instance.setPixelRatio(d.value),he.dpr.value=d.value,((e,t,n)=>{const r=e.value?.domElement;if(!r)throw new Error("missing container");i();const o=new ResizeObserver((([e])=>{i()}));r&&o.observe(r),n((()=>{t&&o.unobserve(t)}))})(u,l.instance.domElement,t.onBeforeUnmount),ae({app:t.getCurrentInstance().appContext.app,camera:p.instance,renderer:l.instance,scene:m.instance})})),t.onBeforeUnmount((()=>{ie()})),()=>[o.slots.default?.()??null,t.h("div",{style:c("absolute"),ref:u},[s.value?t.h("canvas",{style:c("fixed"),class:"lunchbox-canvas",ref:a}):null])]}},u=["mesh","instancedMesh","scene","sprite","object3D","instancedBufferGeometry","bufferGeometry","boxBufferGeometry","circleBufferGeometry","coneBufferGeometry","cylinderBufferGeometry","dodecahedronBufferGeometry","extrudeBufferGeometry","icosahedronBufferGeometry","latheBufferGeometry","octahedronBufferGeometry","parametricBufferGeometry","planeBufferGeometry","polyhedronBufferGeometry","ringBufferGeometry","shapeBufferGeometry","sphereBufferGeometry","tetrahedronBufferGeometry","textBufferGeometry","torusBufferGeometry","torusKnotBufferGeometry","tubeBufferGeometry","wireframeGeometry","parametricGeometry","tetrahedronGeometry","octahedronGeometry","icosahedronGeometry","dodecahedronGeometry","polyhedronGeometry","tubeGeometry","torusKnotGeometry","torusGeometry","sphereGeometry","ringGeometry","planeGeometry","latheGeometry","shapeGeometry","extrudeGeometry","edgesGeometry","coneGeometry","cylinderGeometry","circleGeometry","boxGeometry","material","shadowMaterial","spriteMaterial","rawShaderMaterial","shaderMaterial","pointsMaterial","meshPhysicalMaterial","meshStandardMaterial","meshPhongMaterial","meshToonMaterial","meshNormalMaterial","meshLambertMaterial","meshDepthMaterial","meshDistanceMaterial","meshBasicMaterial","meshMatcapMaterial","lineDashedMaterial","lineBasicMaterial","light","spotLightShadow","spotLight","pointLight","rectAreaLight","hemisphereLight","directionalLightShadow","directionalLight","ambientLight","lightShadow","ambientLightProbe","hemisphereLightProbe","lightProbe","texture","videoTexture","dataTexture","dataTexture3D","compressedTexture","cubeTexture","canvasTexture","depthTexture","textureLoader","group","catmullRomCurve3","points","cameraHelper","camera","perspectiveCamera","orthographicCamera","cubeCamera","arrayCamera","webGLRenderer"],l={},p=["canvas","div","LunchboxWrapper"];u.map((e=>t.defineComponent({inheritAttrs:!1,name:e,setup:(n,r)=>()=>t.h(e,r.attrs,r.slots?.default?.()||[])}))).reduce(((e,t)=>(e[t.name]=t,e)));const m={...u,Lunchbox:d};const h=e=>e?.$el&&e?.$el?.hasOwnProperty?.("instance"),f=e=>{if("domMeta"===e?.metaType)return!0;const t="string"==typeof e?e:e?.type;return p.includes(t??"")},y=e=>"standardMeta"===e?.metaType,v=e=>e.isLunchboxRootNode;function g(e={},t={}){const n={attached:e.attached??[],attachedArray:e.attachedArray??{},instance:e.instance??null},r=new Q.RendererStandardNode({...e,...n,metaType:"standardMeta"});return!r.type||v(r)||r.instance||(r.instance=function(e){if(!e.type)return null;const t=e.type[0].toUpperCase()+e.type.slice(1),n=l[e.type]||a[t];if(!n)throw`${t} is not part of the THREE namespace! Did you forget to extend? import {extend} from 'lunchbox'; extend({app, YourComponent, ...})`;const r=(e.props.args??[]).map((t=>function({node:e,prop:t}){const n="string"==typeof t&&t.startsWith("$attachedArray"),r=function({node:e,prop:t}){if("string"==typeof t&&t.startsWith("$attachedArray"))return e.attachedArray[t.replace("$attachedArray.","")];if("string"==typeof t&&t.startsWith("$attached"))return e.attached[t.replace("$attached.","")];return t}({node:e,prop:t});return Array.isArray(r)&&n?r:[r]}({node:e,prop:t})));let o=[];r.forEach((e=>{o=o.concat(e)}));return new n(...o)}({...r,props:{...r.props,...t}})),"scene"===r.type&&(_.value=r),r}const b=[],x=t.ref(!1);function R({node:e,key:n,value:r}){var o;if(e.eventListeners[n]||(e.eventListeners[n]=[]),e.eventListenerRemoveFunctions[n]||(e.eventListenerRemoveFunctions[n]=[]),e.eventListeners[n].push(r),A.includes(n)&&(V.value,e.instance&&!b.includes(e)&&(o=e,b.push(o),e.eventListenerRemoveFunctions[n].push((()=>(e=>{const t=b.indexOf(e);-1!==t&&b.splice(t,1)})(e))))),"onClick"===n||"onPointerDown"===n||"onPointerUp"===n){const r=t.watch((()=>x.value),(t=>{const r=M.map((e=>e.element)).findIndex((t=>t.instance&&t.instance.uuid===e.instance?.uuid));-1!==r&&((!t||"onClick"!==n&&"onPointerDown"!==n)&&(t||"onPointerUp"!==n)||e.eventListeners[n].forEach((e=>{e({intersection:M[r].intersection})})))}));e.eventListenerRemoveFunctions[n].push(r)}return e}const A=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"];let w,C,E;const L=t.ref({x:1/0,y:1/0});let P=!1;let M=[];const B=()=>{const e=V.value?.instance,t=$.value?.instance;if(!e||!t)return;e.setFromCamera(he.mousePos.value,t);const n=e.intersectObjects(b.map((e=>e.instance)));let r=[],o=[],a=[];r=M.map((e=>e.intersection)),n?.forEach((e=>{const t=M.findIndex((t=>t.intersection.object===e.object));if(-1===t){const t=b.find((t=>t.instance?.uuid===e.object.uuid));t&&o.push({element:t,intersection:e})}else{const t=b.find((t=>t.instance?.uuid===e.object.uuid));t&&a.push({element:t,intersection:e})}const n=r.findIndex((t=>t.object.uuid===e.object.uuid));-1!==n&&r.splice(n,1)}));const s=r.map((e=>({element:b.find((t=>t.instance?.uuid===e.object.uuid)),intersection:e})));o.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerEnter"],intersection:t})})),a.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),s.forEach((({element:e,intersection:t})=>{G({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),M=[].concat(o,a)},G=({element:e,eventKeys:t,intersection:n})=>{e&&t.forEach((t=>{e.eventListeners[t]&&e.eventListeners[t].forEach((e=>{e({intersection:n})}))}))};function N(t={}){return e.lunchboxTree||(e.lunchboxTree=new Q.RendererRootNode(t)),e.lunchboxTree}function T(e){Array.isArray(e)||(e=[e]);for(let t of e)if(j[t])return j[t];for(let t of e){const e=O[t]||s.find((e=>e.type?.toLowerCase()===t.toLowerCase()));if(e){const n=e;return O[t]=n,n}}return null}e.lunchboxTree=void 0;const O=t.reactive({}),j=t.reactive({});function k(e,n,r={},o=null){Array.isArray(e)||(e=[e]);for(let t of e)O[t]||(O[t]=null),j[t]||(j[t]=null);return t.computed({get(){const t=T(e);if(t)return t;const a=N(),s=g({type:e[0],uuid:n,props:r});return a.addChild(s),O[e[0]]=s,o&&o(s),s},set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}})}const F="FALLBACK_CAMERA",S=k(["PerspectiveCamera","OrthographicCamera"],F,{args:[45,.5625,1,1e3]}),D=t.ref(!1),$=t.computed({get:()=>D.value?S.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}}),U="FALLBACK_RENDERER",W=k(["WebGLRenderer"],U,{}),I=t.ref(!1),K=t.computed({get:()=>I.value?W.value:null,set(e){const t=e.type??"",n=t[0].toUpperCase()+t.slice(1);j[n]=e}}),_=k("Scene","FALLBACK_SCENE"),V=k("Raycaster","AUTO_RAYCASTER",{},(e=>(e=>{if(!e.instance)return;let n=null;n=t.watch((()=>K.value),(e=>{e?.instance&&(P||(w=t=>{const n=(e.instance.domElement.width??1)/he.dpr.value,r=(e.instance.domElement.height??1)/he.dpr.value;L.value.x=t.offsetX/n*2-1,L.value.y=-t.offsetY/r*2+1},C=()=>x.value=!0,E=()=>x.value=!1,e.instance.domElement.addEventListener("mousemove",w),e.instance.domElement.addEventListener("mousedown",C),e.instance.domElement.addEventListener("mouseup",E),se(B),P=!0),n&&n())}),{immediate:!0})})(e))),q=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}});var z,H=new Uint8Array(16);function Y(){if(!z&&!(z="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return z(H)}var X=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function J(e){return"string"==typeof e&&X.test(e)}for(var Q,Z=[],ee=0;ee<256;++ee)Z.push((ee+256).toString(16).substr(1));function te(e,t,n){var r=(e=e||{}).random||(e.rng||Y)();if(r[6]=15&r[6]|64,r[8]=63&r[8]|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=r[o];return t}return function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=(Z[e[t+0]]+Z[e[t+1]]+Z[e[t+2]]+Z[e[t+3]]+"-"+Z[e[t+4]]+Z[e[t+5]]+"-"+Z[e[t+6]]+Z[e[t+7]]+"-"+Z[e[t+8]]+Z[e[t+9]]+"-"+Z[e[t+10]]+Z[e[t+11]]+Z[e[t+12]]+Z[e[t+13]]+Z[e[t+14]]+Z[e[t+15]]).toLowerCase();if(!J(n))throw TypeError("Stringified UUID is invalid");return n}(r)}!function(e){e.BaseNode=class{constructor(e={},t){this.parentNode=e?.parentNode??t??null,this.minidomType="MinidomBaseNode",this.uuid=e?.uuid??te(),s.push(this)}uuid;parentNode;get nextSibling(){if(!this.parentNode)return null;const e=this.parentNode.children.findIndex((e=>e.uuid===this.uuid));return-1!==e&&e<this.parentNode.children.length-1?this.parentNode.children[e+1]:null}insertBefore(e,t){e.removeAsChildFromAnyParents(),e.parentNode=this;const n=this.children.findIndex((e=>e.uuid===t?.uuid));-1!==n?this.children.splice(n,0,e):this.children.push(e)}removeChild(e){const t=this.children.findIndex((t=>t?.uuid===e?.uuid));-1!==t&&this.children.splice(t,1)}children=[];addChild(e){return e&&(e.removeAsChildFromAnyParents(),e.parentNode=this,this.insertBefore(e,null)),this}getPath(){const e=[];let t=this;for(;t;)e.unshift(t),t=t.parentNode;return e}drop(){this.parentNode=null,this.removeAsChildFromAnyParents()}walk(e){const t=[this,...this.children],n=[];let r=!0;for(;t.length&&r;){const o=t.shift();if(o){if(n.includes(o))continue;n.push(o),t.push(...o.children.filter((e=>!n.includes(e)))),r=e(o)}else r=!1}}minidomType;removeAsChildFromAnyParents(){s.forEach((e=>e.removeChild(this)))}};class t extends e.BaseNode{constructor(e={},t){super(e,t),this.minidomType="RendererNode",this.eventListeners={},this.eventListenerRemoveFunctions={},this.name=e.name??"",this.metaType=e.metaType??"standardMeta",this.props=e.props??[],this.type=e.type??""}eventListeners;eventListenerRemoveFunctions;name;metaType;props;type;drop(){super.drop(),Object.keys(this.eventListenerRemoveFunctions).forEach((e=>{this.eventListenerRemoveFunctions[e].forEach((e=>e()))}))}}e.RendererBaseNode=t;class n extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement;isLunchboxRootNode=!0}e.RendererRootNode=n;class r extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererCommentNode=r;class o extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement}e.RendererDomNode=o;class a extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererTextNode=a;class i extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.attached=e.attached??[],this.attachedArray=e.attachedArray??{},this.instance=e.instance??null}attached;attachedArray;instance}e.RendererStandardNode=i}(Q||(Q={}));let ne;(new Q.RendererRootNode).minidomType="RootNode";const re=[],oe=[],ae=e=>{ne=requestAnimationFrame((()=>ae({app:e.app,renderer:K.value?.instance,scene:_.value.instance,camera:$.value?.instance})));const{app:n,renderer:r,scene:o,camera:a}=e;re.forEach((t=>{t&&t(e)})),r&&o&&a&&(n.customRender?n.customRender(e):r.render(t.toRaw(o),t.toRaw(a))),oe.forEach((t=>{t&&t(e)}))},se=(e,t=1/0)=>{t===1/0?re.push(e):re.splice(t,0,e)},ie=()=>{ne&&cancelAnimationFrame(ne)};const ce={x:"position.x",y:"position.y",z:"position.z"},de=["","parameters"],ue=["args","attach","attachArray","key","onAdded","ref","src"],le=["geometry","material"];function pe(e,t,n,r){const o=r??e.instance,a=t.instance;e.props.attach===n&&(t.attached={[n]:o,...t.attached||{}},a[n]=r??e.instance),e.props.attachArray===n&&(t.attachedArray[e.props.attachArray]||(t.attachedArray[e.props.attachArray]=[]),t.attachedArray[e.props.attachArray].push(o),a[n]=[a[n]])}const me={createElement:(e,t,n,r)=>{const o={type:e};r&&(o.props=r);if(f(e)){const e=function(e={}){const t={domElement:document.createElement(e.type??"")};return new Q.RendererDomNode({...t,...e,metaType:"domMeta"})}(o);return e}const a=g(o);return le.forEach((t=>{e.toLowerCase().endsWith(t)&&(a.props.attach=t)})),a},createText:e=>function(e={}){const t={text:e.text??""};return new Q.RendererTextNode({...e,...t,metaType:"textMeta"})}({text:e}),createComment:e=>function(e={}){const t={text:e.text??""};return new Q.RendererCommentNode({...t,...e,metaType:"commentMeta"})}({text:e}),insert:(e,t,n)=>{let r=t??N();if(r.insertBefore(e,n),"commentMeta"!==e.metaType&&"textMeta"!==e.metaType&&(f(e)&&(f(t)||v(t))&&t.domElement.appendChild(e.domElement),y(e))){let n=r.metaType;if("textMeta"===n||"commentMeta"===n){const e=r.getPath();for(let t=e.length-1;t>=0;t--)if("textMeta"!==e[t].metaType&&"commentMeta"!==e[t].metaType){r=e[t];break}}if("standardMeta"===e.metaType&&"scene"!==e.type&&v(r)){const t=_.value;t.instance&&e&&t.addChild(e),e.instance&&e.instance.isObject3D&&t.instance&&t!==e&&t.instance.add(e.instance)}else y(e)&&e.instance?.isObject3D&&y(r)&&r.instance?.isObject3D&&r.instance?.add?.(e.instance);if(e?.props?.attach&&y(t)&&t?.instance){e.type?.toLowerCase().endsWith("loader")&&e.props.src&&(e.props.attach||e.props.attachArray)?function(e,t){const n=e.instance;if(t.attached=t.attached||{},t.attachedArray=t.attachedArray||{},!e.props.attach)return;if("textureloader"===e.type?.toLowerCase()){const r=n.load(e.props.src);pe(e,t,e.props.attach,r)}else n.load(e.props.src,(n=>{pe(e,t,e.props.attach,n)}),null,(e=>{throw new Error(e)}))}(e,t):pe(e,t,e.props.attach)}e.props?.onAdded&&e.props.onAdded({instance:e.instance})}},nextSibling(e){const t=e.nextSibling;return t||null},parentNode(e){const t=e.parentNode;return t||null},patchProp(e,t,n,o){f(e)?"style"===t?Object.keys(o).forEach((t=>{e.domElement.style[t]=o[t]})):e.domElement.setAttribute(t,o):v(e)||t.startsWith("$")||function({node:e,key:t,value:n}){if((e=>["onClick","onContextMenu","onDoubleClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove","onWheel"].includes(e))(t))return R({node:e,key:t,value:n});if(ue.includes(t))return e;if(!y(e))return e;if("string"==typeof n&&n.startsWith("$attached")){const t=n.replace("$attached.","");n=r.get(e.attached,t,null)}const o=e.instance;if(!o)return e;const a=t.replace(/-/g,".");let s,i=ce[a]||a;for(let e=0;e<de.length&&!s;e++){const t=[de[e],i].filter(Boolean).join(".");s=s=r.get(o,t)}if(s&&r.isNumber(n)&&s.setScalar)s.setScalar(n);else if(s&&s.set){const e=Array.isArray(n)?n:[n];o[i].set(...e)}else"function"==typeof s?s.bind(e.instance)(...n):void 0!==r.get(o,i,void 0)?r.set(o,i,""===n||n):console.log(`No property ${i} found on ${o}`);const c=o?.texture?.type||o?.type;if("string"==typeof c){const e=c.toLowerCase();switch(!0){case e.includes("material"):o.needsUpdate=!0;break;case e.includes("camera")&&o.updateProjectionMatrix:o.updateProjectionMatrix()}}}({node:e,key:t,value:o})},remove:e=>{if(!e)return;const t=Object.keys(j),n=[];e.walk((e=>(n.push(e),!0))),n.forEach((e=>{const n=t.find((t=>j[t]?.uuid===e.uuid));if(n&&(j[n]=null),y(e)){e.instance?.removeFromParent?.();const t="scene"!==e.type&&e.instance?.dispose;t&&t.bind(e.instance)(),e.instance=null}e.drop();const r=s.findIndex((t=>t.uuid===e.uuid));-1!==r&&s.splice(r,1)}))},setElementText(){},setText(){}},he={dpr:t.ref(1),inputActive:x,mousePos:L},fe=t.computed((()=>$.value?.instance??null)),ye=t.computed((()=>K.value?.instance??null)),ve=t.computed((()=>_.value.instance));let ge=null,be=null;e.camera=fe,e.clearCustomRender=()=>{ge?ge.clearCustomRender():be=null},e.createApp=e=>{ge=t.createRenderer(me).createApp(e),Object.keys(m).forEach((e=>{ge.component(e,m[e])}));const{mount:n}=ge;return ge.mount=(e,...t)=>{const r=N({domElement:"string"==typeof e?document.querySelector(e):e,isLunchboxRootNode:!0,name:"root",metaType:"rootMeta",type:"root",uuid:"LUNCHBOX_ROOT"});ge.rootNode=r;return n(r,...t)},ge.extend=e=>((({app:e,...t})=>{Object.keys(t).forEach((n=>{e.component(n,q(n)),l[n]=t[n]}))})({app:ge,...e}),ge),ge.setCustomRender=e=>{ge.customRender=e},be&&(ge.setCustomRender(be),be=null),ge.clearCustomRender=()=>{ge.customRender=null},ge},e.find=function(e){return e=t.isRef(e)?e.value:e,y(e)?e?.instance:h(e)?e?.$el?.instance:t.isVNode(e)?e.el?.instance:null},e.globals=he,e.offAfterRender=e=>{if(isFinite(e))oe.splice(e,1);else{const t=oe.findIndex((t=>t==e));oe.splice(t,1)}},e.offBeforeRender=e=>{if(isFinite(e))re.splice(e,1);else{const t=re.findIndex((t=>t==e));re.splice(t,1)}},e.onAfterRender=(e,t=1/0)=>{t===1/0?oe.push(e):oe.splice(t,0,e)},e.onBeforeRender=se,e.renderer=ye,e.scene=ve,e.setCustomRender=e=>{ge?ge.setCustomRender(e):be=e},Object.defineProperty(e,"__esModule",{value:!0})}));
@@ -84,6 +84,8 @@ const LunchboxWrapper = {
84
84
  // These should match the Lunchbox.WrapperProps interface
85
85
  background: String,
86
86
  cameraArgs: Array,
87
+ cameraLook: Array,
88
+ cameraLookAt: Array,
87
89
  cameraPosition: Array,
88
90
  dpr: Number,
89
91
  ortho: Boolean,
@@ -173,7 +175,6 @@ const LunchboxWrapper = {
173
175
  if (!camera) {
174
176
  // create ortho camera
175
177
  if (props.ortho || props.orthographic) {
176
- // const size: Vector2 = new Vector2()
177
178
  ensuredCamera.value = createNode({
178
179
  props: { args: props.cameraArgs ?? [] },
179
180
  type: 'OrthographicCamera',
@@ -199,6 +200,11 @@ const LunchboxWrapper = {
199
200
  if (camera && props.cameraPosition) {
200
201
  camera.instance?.position.set(...props.cameraPosition);
201
202
  }
203
+ // angle camera if needed
204
+ if (camera && (props.cameraLookAt || props.cameraLook)) {
205
+ const source = (props.cameraLookAt || props.cameraLook);
206
+ camera.instance?.lookAt(...source);
207
+ }
202
208
  // SCENE
203
209
  // ====================
204
210
  scene = ensuredScene.value;
@@ -255,21 +261,6 @@ const LunchboxWrapper = {
255
261
  },
256
262
  };
257
263
 
258
- const catalogue = {};
259
-
260
- const lunchboxDomComponentNames = [
261
- 'canvas',
262
- 'div',
263
- 'LunchboxWrapper',
264
- ];
265
- // component creation utility
266
- const createComponent$1 = (tag) => defineComponent({
267
- inheritAttrs: false,
268
- name: tag,
269
- setup(props, context) {
270
- return () => h(tag, context.attrs, context.slots?.default?.() || []);
271
- },
272
- });
273
264
  // list of all components to register out of the box
274
265
  const autoGeneratedComponents = [
275
266
  // ThreeJS basics
@@ -382,21 +373,11 @@ const autoGeneratedComponents = [
382
373
  'arrayCamera',
383
374
  // renderers
384
375
  'webGLRenderer',
385
- ].map(createComponent$1).reduce((acc, curr) => {
386
- acc[curr.name] = curr;
387
- return acc;
388
- });
389
- const components = {
390
- ...autoGeneratedComponents,
391
- 'Lunchbox': LunchboxWrapper,
392
- // Gltf,
393
- };
394
- // console.log(components, Gltf)
395
- /*
396
- // List copied from r3f
397
- // https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/three-types.ts
376
+ /*
377
+ // List copied from r3f:
378
+ // https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/three-types.ts
398
379
 
399
- // NOT IMPLEMENTED:
380
+ // NOT IMPLEMENTED (can be added via Extend - docs.lunchboxjs.com/components/extend/):
400
381
  audioListener: AudioListenerProps
401
382
  positionalAudio: PositionalAudioProps
402
383
 
@@ -444,6 +425,27 @@ const components = {
444
425
  fogExp2: FogExp2Props
445
426
  shape: ShapeProps
446
427
  */
428
+ ];
429
+
430
+ const catalogue = {};
431
+
432
+ const lunchboxDomComponentNames = ['canvas', 'div', 'LunchboxWrapper'];
433
+ // component creation utility
434
+ const createComponent$1 = (tag) => defineComponent({
435
+ inheritAttrs: false,
436
+ name: tag,
437
+ setup(props, context) {
438
+ return () => h(tag, context.attrs, context.slots?.default?.() || []);
439
+ },
440
+ });
441
+ autoGeneratedComponents.map(createComponent$1).reduce((acc, curr) => {
442
+ acc[curr.name] = curr;
443
+ return acc;
444
+ });
445
+ const components = {
446
+ ...autoGeneratedComponents,
447
+ Lunchbox: LunchboxWrapper,
448
+ };
447
449
 
448
450
  function find(target) {
449
451
  target = isRef(target) ? target.value : target;
@@ -1280,6 +1282,15 @@ const onBeforeRender = (cb, index = Infinity) => {
1280
1282
  beforeRender.splice(index, 0, cb);
1281
1283
  }
1282
1284
  };
1285
+ const offBeforeRender = (cb) => {
1286
+ if (isFinite(cb)) {
1287
+ beforeRender.splice(cb, 1);
1288
+ }
1289
+ else {
1290
+ const idx = beforeRender.findIndex((v) => v == cb);
1291
+ beforeRender.splice(idx, 1);
1292
+ }
1293
+ };
1283
1294
  const onAfterRender = (cb, index = Infinity) => {
1284
1295
  if (index === Infinity) {
1285
1296
  afterRender.push(cb);
@@ -1288,6 +1299,15 @@ const onAfterRender = (cb, index = Infinity) => {
1288
1299
  afterRender.splice(index, 0, cb);
1289
1300
  }
1290
1301
  };
1302
+ const offAfterRender = (cb) => {
1303
+ if (isFinite(cb)) {
1304
+ afterRender.splice(cb, 1);
1305
+ }
1306
+ else {
1307
+ const idx = afterRender.findIndex((v) => v == cb);
1308
+ afterRender.splice(idx, 1);
1309
+ }
1310
+ };
1291
1311
  const cancelUpdate = () => {
1292
1312
  if (frameID)
1293
1313
  cancelAnimationFrame(frameID);
@@ -1710,4 +1730,4 @@ const createApp = (root) => {
1710
1730
  return app;
1711
1731
  };
1712
1732
 
1713
- export { camera, clearCustomRender, createApp, find, globals, lunchboxRootNode as lunchboxTree, onAfterRender, onBeforeRender, renderer, scene, setCustomRender };
1733
+ export { camera, clearCustomRender, createApp, find, globals, lunchboxRootNode as lunchboxTree, offAfterRender, offBeforeRender, onAfterRender, onBeforeRender, renderer, scene, setCustomRender };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lunchboxjs",
3
- "version": "0.1.4004",
3
+ "version": "0.1.4005",
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",
@@ -25,6 +25,8 @@
25
25
  "@types/three": "0.133.0",
26
26
  "@types/uuid": "8.3.1",
27
27
  "@vitejs/plugin-vue": "^1.9.3",
28
+ "chroma-js": "2.1.2",
29
+ "nice-color-palettes": "3.0.0",
28
30
  "rollup-plugin-delete": "2.0.0",
29
31
  "rollup-plugin-terser": "7.0.2",
30
32
  "typescript": "^4.4.3",
@@ -45,6 +45,8 @@ export const LunchboxWrapper: ComponentOptions = {
45
45
  // These should match the Lunchbox.WrapperProps interface
46
46
  background: String,
47
47
  cameraArgs: Array,
48
+ cameraLook: Array,
49
+ cameraLookAt: Array,
48
50
  cameraPosition: Array,
49
51
  dpr: Number,
50
52
  ortho: Boolean,
@@ -149,8 +151,6 @@ export const LunchboxWrapper: ComponentOptions = {
149
151
  if (!camera) {
150
152
  // create ortho camera
151
153
  if (props.ortho || props.orthographic) {
152
- // const size: Vector2 = new Vector2()
153
-
154
154
  ensuredCamera.value = createNode<THREE.OrthographicCamera>({
155
155
  props: { args: props.cameraArgs ?? [] },
156
156
  type: 'OrthographicCamera',
@@ -176,6 +176,11 @@ export const LunchboxWrapper: ComponentOptions = {
176
176
  if (camera && props.cameraPosition) {
177
177
  camera.instance?.position.set(...props.cameraPosition)
178
178
  }
179
+ // angle camera if needed
180
+ if (camera && (props.cameraLookAt || props.cameraLook)) {
181
+ const source = (props.cameraLookAt || props.cameraLook)!
182
+ camera.instance?.lookAt(...source)
183
+ }
179
184
 
180
185
  // SCENE
181
186
  // ====================
@@ -0,0 +1,175 @@
1
+ // list of all components to register out of the box
2
+ export const autoGeneratedComponents = [
3
+ // ThreeJS basics
4
+ 'mesh',
5
+ 'instancedMesh',
6
+ 'scene',
7
+ 'sprite',
8
+ 'object3D',
9
+
10
+ // geometry
11
+ 'instancedBufferGeometry',
12
+ 'bufferGeometry',
13
+ 'boxBufferGeometry',
14
+ 'circleBufferGeometry',
15
+ 'coneBufferGeometry',
16
+ 'cylinderBufferGeometry',
17
+ 'dodecahedronBufferGeometry',
18
+ 'extrudeBufferGeometry',
19
+ 'icosahedronBufferGeometry',
20
+ 'latheBufferGeometry',
21
+ 'octahedronBufferGeometry',
22
+ 'parametricBufferGeometry',
23
+ 'planeBufferGeometry',
24
+ 'polyhedronBufferGeometry',
25
+ 'ringBufferGeometry',
26
+ 'shapeBufferGeometry',
27
+ 'sphereBufferGeometry',
28
+ 'tetrahedronBufferGeometry',
29
+ 'textBufferGeometry',
30
+ 'torusBufferGeometry',
31
+ 'torusKnotBufferGeometry',
32
+ 'tubeBufferGeometry',
33
+ 'wireframeGeometry',
34
+ 'parametricGeometry',
35
+ 'tetrahedronGeometry',
36
+ 'octahedronGeometry',
37
+ 'icosahedronGeometry',
38
+ 'dodecahedronGeometry',
39
+ 'polyhedronGeometry',
40
+ 'tubeGeometry',
41
+ 'torusKnotGeometry',
42
+ 'torusGeometry',
43
+ // textgeometry has been moved to /examples/jsm/geometries/TextGeometry
44
+ // 'textGeometry',
45
+ 'sphereGeometry',
46
+ 'ringGeometry',
47
+ 'planeGeometry',
48
+ 'latheGeometry',
49
+ 'shapeGeometry',
50
+ 'extrudeGeometry',
51
+ 'edgesGeometry',
52
+ 'coneGeometry',
53
+ 'cylinderGeometry',
54
+ 'circleGeometry',
55
+ 'boxGeometry',
56
+
57
+ // materials
58
+ 'material',
59
+ 'shadowMaterial',
60
+ 'spriteMaterial',
61
+ 'rawShaderMaterial',
62
+ 'shaderMaterial',
63
+ 'pointsMaterial',
64
+ 'meshPhysicalMaterial',
65
+ 'meshStandardMaterial',
66
+ 'meshPhongMaterial',
67
+ 'meshToonMaterial',
68
+ 'meshNormalMaterial',
69
+ 'meshLambertMaterial',
70
+ 'meshDepthMaterial',
71
+ 'meshDistanceMaterial',
72
+ 'meshBasicMaterial',
73
+ 'meshMatcapMaterial',
74
+ 'lineDashedMaterial',
75
+ 'lineBasicMaterial',
76
+
77
+ // lights
78
+ 'light',
79
+ 'spotLightShadow',
80
+ 'spotLight',
81
+ 'pointLight',
82
+ 'rectAreaLight',
83
+ 'hemisphereLight',
84
+ 'directionalLightShadow',
85
+ 'directionalLight',
86
+ 'ambientLight',
87
+ 'lightShadow',
88
+ 'ambientLightProbe',
89
+ 'hemisphereLightProbe',
90
+ 'lightProbe',
91
+
92
+ // textures
93
+ 'texture',
94
+ 'videoTexture',
95
+ 'dataTexture',
96
+ 'dataTexture3D',
97
+ 'compressedTexture',
98
+ 'cubeTexture',
99
+ 'canvasTexture',
100
+ 'depthTexture',
101
+
102
+ // Texture loaders
103
+ 'textureLoader',
104
+
105
+ // misc
106
+ 'group',
107
+ 'catmullRomCurve3',
108
+ 'points',
109
+
110
+ // helpers
111
+ 'cameraHelper',
112
+
113
+ // cameras
114
+ 'camera',
115
+ 'perspectiveCamera',
116
+ 'orthographicCamera',
117
+ 'cubeCamera',
118
+ 'arrayCamera',
119
+
120
+ // renderers
121
+ 'webGLRenderer',
122
+
123
+ /*
124
+ // List copied from r3f:
125
+ // https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/three-types.ts
126
+
127
+ // NOT IMPLEMENTED (can be added via Extend - docs.lunchboxjs.com/components/extend/):
128
+ audioListener: AudioListenerProps
129
+ positionalAudio: PositionalAudioProps
130
+
131
+ lOD: LODProps
132
+ skinnedMesh: SkinnedMeshProps
133
+ skeleton: SkeletonProps
134
+ bone: BoneProps
135
+ lineSegments: LineSegmentsProps
136
+ lineLoop: LineLoopProps
137
+ // see `audio`
138
+ // line: LineProps
139
+ immediateRenderObject: ImmediateRenderObjectProps
140
+
141
+ // primitive
142
+ primitive: PrimitiveProps
143
+
144
+ // helpers
145
+ spotLightHelper: SpotLightHelperProps
146
+ skeletonHelper: SkeletonHelperProps
147
+ pointLightHelper: PointLightHelperProps
148
+ hemisphereLightHelper: HemisphereLightHelperProps
149
+ gridHelper: GridHelperProps
150
+ polarGridHelper: PolarGridHelperProps
151
+ directionalLightHelper: DirectionalLightHelperProps
152
+ boxHelper: BoxHelperProps
153
+ box3Helper: Box3HelperProps
154
+ planeHelper: PlaneHelperProps
155
+ arrowHelper: ArrowHelperProps
156
+ axesHelper: AxesHelperProps
157
+
158
+
159
+ // misc
160
+ raycaster: RaycasterProps
161
+ vector2: Vector2Props
162
+ vector3: Vector3Props
163
+ vector4: Vector4Props
164
+ euler: EulerProps
165
+ matrix3: Matrix3Props
166
+ matrix4: Matrix4Props
167
+ quaternion: QuaternionProps
168
+ bufferAttribute: BufferAttributeProps
169
+ instancedBufferAttribute: InstancedBufferAttributeProps
170
+ color: ColorProps
171
+ fog: FogProps
172
+ fogExp2: FogExp2Props
173
+ shape: ShapeProps
174
+ */
175
+ ]
@@ -1,16 +1,11 @@
1
1
  import { h, defineComponent } from 'vue'
2
- // import Gltf from './Gltf'
3
- // import { Lunchbox } from '../types'
4
2
  import { LunchboxWrapper } from './LunchboxWrapper/LunchboxWrapper'
3
+ import { autoGeneratedComponents } from './autoGeneratedComponents'
5
4
 
6
5
  import { catalogue } from './catalogue'
7
6
  export { catalogue }
8
7
 
9
- export const lunchboxDomComponentNames = [
10
- 'canvas',
11
- 'div',
12
- 'LunchboxWrapper',
13
- ]
8
+ export const lunchboxDomComponentNames = ['canvas', 'div', 'LunchboxWrapper']
14
9
 
15
10
  // component creation utility
16
11
  const createComponent = (tag: string) =>
@@ -22,190 +17,12 @@ const createComponent = (tag: string) =>
22
17
  },
23
18
  })
24
19
 
25
- // list of all components to register out of the box
26
- const autoGeneratedComponents = [
27
-
28
- // ThreeJS basics
29
- 'mesh',
30
- 'instancedMesh',
31
- 'scene',
32
- 'sprite',
33
- 'object3D',
34
-
35
- // geometry
36
- 'instancedBufferGeometry',
37
- 'bufferGeometry',
38
- 'boxBufferGeometry',
39
- 'circleBufferGeometry',
40
- 'coneBufferGeometry',
41
- 'cylinderBufferGeometry',
42
- 'dodecahedronBufferGeometry',
43
- 'extrudeBufferGeometry',
44
- 'icosahedronBufferGeometry',
45
- 'latheBufferGeometry',
46
- 'octahedronBufferGeometry',
47
- 'parametricBufferGeometry',
48
- 'planeBufferGeometry',
49
- 'polyhedronBufferGeometry',
50
- 'ringBufferGeometry',
51
- 'shapeBufferGeometry',
52
- 'sphereBufferGeometry',
53
- 'tetrahedronBufferGeometry',
54
- 'textBufferGeometry',
55
- 'torusBufferGeometry',
56
- 'torusKnotBufferGeometry',
57
- 'tubeBufferGeometry',
58
- 'wireframeGeometry',
59
- 'parametricGeometry',
60
- 'tetrahedronGeometry',
61
- 'octahedronGeometry',
62
- 'icosahedronGeometry',
63
- 'dodecahedronGeometry',
64
- 'polyhedronGeometry',
65
- 'tubeGeometry',
66
- 'torusKnotGeometry',
67
- 'torusGeometry',
68
- // textgeometry has been moved to /examples/jsm/geometries/TextGeometry
69
- // 'textGeometry',
70
- 'sphereGeometry',
71
- 'ringGeometry',
72
- 'planeGeometry',
73
- 'latheGeometry',
74
- 'shapeGeometry',
75
- 'extrudeGeometry',
76
- 'edgesGeometry',
77
- 'coneGeometry',
78
- 'cylinderGeometry',
79
- 'circleGeometry',
80
- 'boxGeometry',
81
-
82
- // materials
83
- 'material',
84
- 'shadowMaterial',
85
- 'spriteMaterial',
86
- 'rawShaderMaterial',
87
- 'shaderMaterial',
88
- 'pointsMaterial',
89
- 'meshPhysicalMaterial',
90
- 'meshStandardMaterial',
91
- 'meshPhongMaterial',
92
- 'meshToonMaterial',
93
- 'meshNormalMaterial',
94
- 'meshLambertMaterial',
95
- 'meshDepthMaterial',
96
- 'meshDistanceMaterial',
97
- 'meshBasicMaterial',
98
- 'meshMatcapMaterial',
99
- 'lineDashedMaterial',
100
- 'lineBasicMaterial',
101
-
102
- // lights
103
- 'light',
104
- 'spotLightShadow',
105
- 'spotLight',
106
- 'pointLight',
107
- 'rectAreaLight',
108
- 'hemisphereLight',
109
- 'directionalLightShadow',
110
- 'directionalLight',
111
- 'ambientLight',
112
- 'lightShadow',
113
- 'ambientLightProbe',
114
- 'hemisphereLightProbe',
115
- 'lightProbe',
116
-
117
- // textures
118
- 'texture',
119
- 'videoTexture',
120
- 'dataTexture',
121
- 'dataTexture3D',
122
- 'compressedTexture',
123
- 'cubeTexture',
124
- 'canvasTexture',
125
- 'depthTexture',
126
-
127
- // Texture loaders
128
- 'textureLoader',
129
-
130
- // misc
131
- 'group',
132
- 'catmullRomCurve3',
133
- 'points',
134
-
135
- // helpers
136
- 'cameraHelper',
137
-
138
- // cameras
139
- 'camera',
140
- 'perspectiveCamera',
141
- 'orthographicCamera',
142
- 'cubeCamera',
143
- 'arrayCamera',
144
-
145
- // renderers
146
- 'webGLRenderer',
147
- ].map(createComponent).reduce((acc, curr) => {
148
- ; (acc as any)[curr.name] = curr
20
+ autoGeneratedComponents.map(createComponent).reduce((acc, curr) => {
21
+ ;(acc as any)[curr.name] = curr
149
22
  return acc
150
23
  })
151
24
 
152
25
  export const components = {
153
26
  ...autoGeneratedComponents,
154
- 'Lunchbox': LunchboxWrapper,
155
- // Gltf,
27
+ Lunchbox: LunchboxWrapper,
156
28
  }
157
-
158
- // console.log(components, Gltf)
159
-
160
- /*
161
- // List copied from r3f
162
- // https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/three-types.ts
163
-
164
- // NOT IMPLEMENTED:
165
- audioListener: AudioListenerProps
166
- positionalAudio: PositionalAudioProps
167
-
168
- lOD: LODProps
169
- skinnedMesh: SkinnedMeshProps
170
- skeleton: SkeletonProps
171
- bone: BoneProps
172
- lineSegments: LineSegmentsProps
173
- lineLoop: LineLoopProps
174
- // see `audio`
175
- // line: LineProps
176
- immediateRenderObject: ImmediateRenderObjectProps
177
-
178
- // primitive
179
- primitive: PrimitiveProps
180
-
181
- // helpers
182
- spotLightHelper: SpotLightHelperProps
183
- skeletonHelper: SkeletonHelperProps
184
- pointLightHelper: PointLightHelperProps
185
- hemisphereLightHelper: HemisphereLightHelperProps
186
- gridHelper: GridHelperProps
187
- polarGridHelper: PolarGridHelperProps
188
- directionalLightHelper: DirectionalLightHelperProps
189
- boxHelper: BoxHelperProps
190
- box3Helper: Box3HelperProps
191
- planeHelper: PlaneHelperProps
192
- arrowHelper: ArrowHelperProps
193
- axesHelper: AxesHelperProps
194
-
195
-
196
- // misc
197
- raycaster: RaycasterProps
198
- vector2: Vector2Props
199
- vector3: Vector3Props
200
- vector4: Vector4Props
201
- euler: EulerProps
202
- matrix3: Matrix3Props
203
- matrix4: Matrix4Props
204
- quaternion: QuaternionProps
205
- bufferAttribute: BufferAttributeProps
206
- instancedBufferAttribute: InstancedBufferAttributeProps
207
- color: ColorProps
208
- fog: FogProps
209
- fogExp2: FogExp2Props
210
- shape: ShapeProps
211
- */
@@ -53,6 +53,15 @@ export const onBeforeRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
53
53
  }
54
54
  }
55
55
 
56
+ export const offBeforeRender = (cb: Lunch.UpdateCallback | number) => {
57
+ if (isFinite(cb as number)) {
58
+ beforeRender.splice(cb as number, 1)
59
+ } else {
60
+ const idx = beforeRender.findIndex((v) => v == cb)
61
+ beforeRender.splice(idx, 1)
62
+ }
63
+ }
64
+
56
65
  export const onAfterRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
57
66
  if (index === Infinity) {
58
67
  afterRender.push(cb)
@@ -61,6 +70,15 @@ export const onAfterRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
61
70
  }
62
71
  }
63
72
 
73
+ export const offAfterRender = (cb: Lunch.UpdateCallback | number) => {
74
+ if (isFinite(cb as number)) {
75
+ afterRender.splice(cb as number, 1)
76
+ } else {
77
+ const idx = afterRender.findIndex((v) => v == cb)
78
+ afterRender.splice(idx, 1)
79
+ }
80
+ }
81
+
64
82
  export const cancelUpdate = () => {
65
83
  if (frameID) cancelAnimationFrame(frameID)
66
84
  }
package/src/index.ts CHANGED
@@ -17,7 +17,12 @@ import { components } from './components'
17
17
  import { Lunch } from './types'
18
18
 
19
19
  export { lunchboxRootNode as lunchboxTree } from './core'
20
- export { onBeforeRender, onAfterRender } from './core'
20
+ export {
21
+ offAfterRender,
22
+ offBeforeRender,
23
+ onBeforeRender,
24
+ onAfterRender,
25
+ } from './core'
21
26
  export * from './types'
22
27
 
23
28
  // Utilities
package/src/types.ts CHANGED
@@ -139,6 +139,8 @@ export declare namespace Lunch {
139
139
  interface WrapperProps {
140
140
  background?: string
141
141
  cameraArgs?: any[]
142
+ cameraLook?: [number, number, number]
143
+ cameraLookAt?: [number, number, number]
142
144
  cameraPosition?: [number, number, number]
143
145
  dpr?: number
144
146
  ortho?: boolean