zf-twin-3d 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1346 -0
- package/dist/index.mjs +10 -0
- package/package.json +37 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {Group,Tween,Easing}from'@tweenjs/tween.js';import {OrbitControls}from'three/examples/jsm/controls/OrbitControls.js';import {Vector3,MathUtils,Scene,WebGLRenderer,CubeTextureLoader,PCFShadowMap,SRGBColorSpace,Color,Mesh,HemisphereLight,DirectionalLight,PerspectiveCamera,Spherical,Box3,Sphere,Vector2,WebGLRenderTarget,TextureLoader,ClampToEdgeWrapping,LinearFilter,Timer,LoopRepeat,LoopOnce,AnimationMixer,MeshBasicMaterial,CanvasTexture,PlaneGeometry,DoubleSide,Sprite,MeshStandardMaterial,SpriteMaterial,Group as Group$1,Raycaster,BufferGeometry,BufferAttribute}from'three';export*from'three';import {GLTFLoader}from'three/examples/jsm/loaders/GLTFLoader.js';import {EffectComposer}from'three/examples/jsm/postprocessing/EffectComposer.js';import {OutlinePass}from'three/examples/jsm/postprocessing/OutlinePass.js';import {OutputPass}from'three/examples/jsm/postprocessing/OutputPass.js';import {RenderPass}from'three/examples/jsm/postprocessing/RenderPass.js';function F(r){let e=0;for(let t=0;t<r.length-1;t++)e+=r[t].distanceTo(r[t+1]);return e}function R(r,e,t,i){if(t<=0)return i.copy(r[0]);if(t>=1)return i.copy(r[r.length-1]);let s=t*e,n=0;for(let o=0;o<r.length-1;o++){let a=r[o].distanceTo(r[o+1]);if(n+a>=s){let c=a>0?(s-n)/a:0;return i.lerpVectors(r[o],r[o+1],c)}n+=a;}return i.copy(r[r.length-1])}function S(r,e,t,i,s,n=2){if(e<=0)return s.copy(i);let o=t*e,a=Math.min(o+n,e);if(R(r,e,a/e,s),s.distanceToSquared(i)>1e-10)return s;for(let c=r.length-2;c>=0;c--){let l=new Vector3().subVectors(r[c+1],r[c]);if(l.lengthSq()>1e-10)return s.copy(i).add(l.normalize().multiplyScalar(n))}return s.copy(i)}function Me(r,e,t){if(e<=0||r.length<3)return r.map(s=>s.clone());let i=[r[0].clone()];for(let s=1;s<r.length-1;s++){let n=ie(r[s-1],r[s],r[s+1],e,t);if(n){i.push(n.t1),i.push(...n.arcPoints),i.push(n.t2);continue}i.push(r[s].clone());}return i.push(r[r.length-1].clone()),i}function ie(r,e,t,i,s){let n=new Vector3().subVectors(e,r),o=new Vector3().subVectors(t,e),a=n.length(),c=o.length();if(a<1e-6||c<1e-6)return null;n.divideScalar(a),o.divideScalar(c);let l=Math.max(-1,Math.min(1,n.dot(o))),h=Math.acos(l);if(h<1e-6||Math.PI-h<1e-6)return null;let p=h/2,u=Math.tan(p);if(u<1e-6)return null;let d=Math.min(a*u,c*u);if(d<1e-6)return null;let x=Math.min(i,d),A=x/u,M=e.clone().addScaledVector(n,-A),ve=e.clone().addScaledVector(o,A),L=new Vector3().crossVectors(n,o);if(L.lengthSq()<1e-10)return null;L.normalize();let nt=new Vector3().crossVectors(L,n).normalize(),ee=M.clone().addScaledVector(nt,x),Oe=new Vector3().subVectors(M,ee),ot=new Vector3().subVectors(ve,ee),je=Math.sign(new Vector3().crossVectors(Oe,ot).dot(L));if(je===0)return null;let Ce=Math.max(1,Math.floor(s)),De=[];for(let te=1;te<Ce;te++){let at=h*(te/Ce)*je;De.push(Oe.clone().applyAxisAngle(L,at).add(ee));}return {t1:M,t2:ve,arcPoints:De}}var U=class{pcInstance;orbitControls;cameraTweenGroup;cameraTweenDampingRestore=null;constructor(e,t){this.cameraTweenGroup=new Group,this.pcInstance=new PerspectiveCamera(50,e/t,2,6e3);}init(e){this.attachOrbitControls(e),this.setCamera({position:[2.480263436745355,111.89688895672828,109.84053922873402],target:[3.7833793836494762,14.00565270016025,-11.22361866991802]});}updateCameraTweens(e=performance.now()){this.cameraTweenGroup.update(e);}setCamera(e){let t=new Vector3(...e.target),i;if("position"in e)i=new Vector3(...e.position);else {let n=e.distance??0,o=Math.PI/2-MathUtils.degToRad(e.pitch),a=MathUtils.degToRad(e.yaw),c=new Spherical(n,o,a),l=new Vector3().setFromSpherical(c);i=new Vector3().copy(t).add(l);}let s=e.duration??2;return s<=0?(this.clearCameraPoseTweens(),this.finishCameraTweenDamping(),this.pcInstance.position.copy(i),this.orbitControls?.target.copy(t),Promise.resolve()):this.runCameraPoseTween(t,i,s)}focusObject(e,t){let i=e.object3D;if(!i)return Promise.resolve();let s=new Box3().setFromObject(i);if(s.isEmpty())return Promise.resolve();let n=s.getCenter(new Vector3),o=t?.distance??this.resolveFocusDistanceByBounds(s);return this.setCamera({target:n.toArray(),yaw:t?.yaw??0,pitch:t?.pitch??35,distance:o,duration:t?.duration??2})}getCamera(){let e=this.orbitControls?.target??new Vector3(0,0,0),t=this.pcInstance.position.toArray(),i=new Vector3().subVectors(this.pcInstance.position,e),s=new Spherical().setFromVector3(i),n=MathUtils.radToDeg(Math.PI/2-s.phi),o=MathUtils.radToDeg(s.theta);return {position:t,target:e.toArray(),yaw:o,pitch:n,distance:s.radius}}moveCameraAlongPath(e,t){if(!this.orbitControls||e.length===0||t<=0)return Promise.resolve();let i=e.map(l=>new Vector3(...l)),s=F(i);if(s===0)return Promise.resolve();let n=i[0],o=new Vector3;this.pcInstance.position.copy(n),S(i,s,0,n,o),this.orbitControls.target.copy(o),this.clearCameraPoseTweens(),this.cameraTweenDampingRestore=this.orbitControls.enableDamping,this.orbitControls.enableDamping=false;let a={t:0},c=new Vector3;return new Promise(l=>{new Tween(a,this.cameraTweenGroup).to({t:1},t*1e3).easing(Easing.Linear.None).onUpdate(()=>{R(i,s,a.t,c),S(i,s,a.t,c,o),this.pcInstance.position.copy(c),this.orbitControls?.target.copy(o);}).onComplete(()=>{this.finishCameraTweenDamping(),l();}).onStop(()=>{this.finishCameraTweenDamping(),l();}).start(performance.now());})}stopCameraPathMovement(){this.clearCameraPoseTweens(),this.finishCameraTweenDamping();}attachOrbitControls(e){if(this.orbitControls)return;let t=new OrbitControls(this.pcInstance,e);t.minDistance=1,t.maxDistance=3e3,t.enableDamping=true,this.orbitControls=t;}finishCameraTweenDamping(){this.orbitControls&&this.cameraTweenDampingRestore!==null&&(this.orbitControls.enableDamping=this.cameraTweenDampingRestore,this.cameraTweenDampingRestore=null);}clearCameraPoseTweens(){let e=this.cameraTweenGroup.getAll();for(let t of e)t.stop();this.cameraTweenGroup.removeAll();}runCameraPoseTween(e,t,i){if(!this.orbitControls)return Promise.resolve();this.clearCameraPoseTweens(),this.cameraTweenDampingRestore=this.orbitControls.enableDamping,this.orbitControls.enableDamping=false;let s=this.orbitControls.target.clone(),n=this.pcInstance.position.clone(),o={tx:s.x,ty:s.y,tz:s.z,px:n.x,py:n.y,pz:n.z},a={tx:e.x,ty:e.y,tz:e.z,px:t.x,py:t.y,pz:t.z};return new Promise(c=>{new Tween(o,this.cameraTweenGroup).to(a,i*1e3).easing(Easing.Cubic.InOut).onUpdate(()=>{this.pcInstance.position.set(o.px,o.py,o.pz),this.orbitControls?.target.set(o.tx,o.ty,o.tz);}).onComplete(()=>{this.finishCameraTweenDamping(),c();}).onStop(()=>{this.finishCameraTweenDamping(),c();}).start(performance.now());})}resolveFocusDistanceByBounds(e){let t=e.getBoundingSphere(new Sphere),i=MathUtils.degToRad(this.pcInstance.fov),s=t.radius/Math.sin(i/1.5);return Math.max(s,this.orbitControls?.minDistance??1)}};var j=(a=>(a.CLICK="click",a.DOUBLE_CLICK="double-click",a.MOUSE_ENTER="mouse-enter",a.MOUSE_LEAVE="mouse-leave",a.RIGHT_DOUBLE_CLICK="right-double-click",a.LEVEL_CHANGE="level-change",a.FRAME_UPDATE="frame-update",a))(j||{}),Ee=(t=>(t.BUILDING_HOVER_HIGHLIGHT="building-hover-highlight",t.SCENE_LEVEL_SWITCH="scene-level-switch",t))(Ee||{});function Pe(r,e){let t=r.getBoundingClientRect();return {x:e.clientX-t.left,y:e.clientY-t.top}}function re(r,e,t,i){function s(u){let d=u;for(;d;){if(!d.visible)return false;d=d.parent;}return true}let n=r.getBoundingClientRect(),o=(i.clientX-n.left)/n.width*2-1,a=-((i.clientY-n.top)/n.height)*2+1,c=new Vector2(o,a),l=new Raycaster;return l.setFromCamera(c,e),l.intersectObjects(t,true).find(u=>s(u.object))}var f=(c=>(c.CAMPUS="campus",c.BUILDING="building",c.FLOOR="floor",c.MARKER="marker",c.UI_ANCHOR="ui-anchor",c.ELEMENT="element",c.THING="thing",c.POLYLINE="polyline",c))(f||{}),se=(t=>(t.BUILDING="building_",t.FLOOR="floor_",t))(se||{});function T(r){let e=new Set;r.traverse(t=>{if(!(t instanceof Mesh))return;t.geometry?.dispose();let i=t.material,s=Array.isArray(i)?i:i?[i]:[];for(let n of s)!n||e.has(n)||(e.add(n),n.dispose());});}function V(r,e){let t="building_[^_]+",i="floor_\\d+",s=e??t;return new RegExp(`^${s}_${i}$`).test(r)}function b(r,e,t){e&&requestAnimationFrame(()=>{t()||e(r);});}function bt(r){let e=r.trim();return /^[0-9a-f]{3,8}$/i.test(e)?`#${e}`:e}function ne(r){return Number.isFinite(r)?Math.min(1,Math.max(0,r)):1}function B(r){let e=bt(r),t=1,i=e.match(/^rgba\s*\(\s*[\d.]+\s*,\s*[\d.]+\s*,\s*[\d.]+\s*,\s*([\d.]+)\s*\)$/i);i&&(t=ne(Number.parseFloat(i[1]))),e.match(/^#([0-9a-f]{8})$/i)&&(t=ne(Number.parseInt(e.slice(7,9),16)/255));let n=new Color;try{n.setStyle(e);}catch{throw new Error(`\u65E0\u6548\u989C\u8272: ${r}`)}return {color:n,alpha:t}}function ae(r){return "color"in r&&r.color instanceof Color}function ce(r,e){r.traverse(t=>{if(!(t instanceof Mesh))return;let i=t.material;if(Array.isArray(i))for(let s of i)e(s);else i&&e(i);});}function le(r,e,t){r.traverse(i=>{if(!(i instanceof Mesh)||i.userData.customObject!==e)return;let s=i.material;if(Array.isArray(s))for(let n of s)t(n);else s&&t(s);});}function Ae(r){let e=new Set;return ce(r,t=>e.add(t)),e}function Le(r,e){let t=new Set;return le(r,e,i=>t.add(i)),t}function Re(r,e){let t=new Map,i=[];return r.traverse(s=>{if(!(s instanceof Mesh)||s.userData.customObject!==e)return;let n=a=>{let c=t.get(a);return c||(c=a.clone(),t.set(a,c),i.push(c)),c},o=s.material;Array.isArray(o)?s.material=o.map(a=>n(a)):o&&(s.material=n(o));}),i}function Ie(r){let e=new Map;for(let t of r)e.set(t,{color:ae(t)?t.color.clone():null,opacity:t.opacity,transparent:t.transparent});return e}function Be(r,e,t){ae(r)&&(r.color.copy(e),t<1&&(r.transparent=true,r.opacity=t));}function Fe(r,e){let t=ne(e);r.opacity=t,r.transparent=t<1;}function Ue(r){for(let[e,t]of r)ae(e)&&t.color&&e.color.copy(t.color),e.opacity=t.opacity,e.transparent=t.transparent;}function pe(r){return r.type==="campus"}function G(r){return r.type==="building"}function he(r){return r.type==="floor"}function ue(r){return r==="building"||r==="floor"||r==="element"}var N=class{constructor(e,t){this.app=e;this.customObject=t;}app;customObject;materialSnapshots=null;materialsIsolated=false;highlight(){this.customObject.object3D&&this.app.outlineHighlighter.setSelection(this.customObject.object3D);}clearHighlight(){this.app.outlineHighlighter.clearSelection();}setColor(e){let{color:t,alpha:i}=B(e);this.forEachModelMaterial(s=>{Be(s,t,i);});}setOpacity(e){this.forEachModelMaterial(t=>{Fe(t,e);});}resetColor(){let e=this.materialSnapshots;e&&Ue(e);}reset(){this.clearHighlight(),this.resetColor();}forEachModelMaterial(e){let t=this.customObject.object3D;if(!t)return;let i=ue(this.customObject.type);i&&this.ensureMaterialIsolation(),this.ensureMaterialSnapshots(),(i?n=>le(t,this.customObject,n):n=>ce(t,n))(e);}ensureMaterialSnapshots(){let e=this.customObject.object3D;if(!e||this.materialSnapshots)return;let t=ue(this.customObject.type);this.materialSnapshots=Ie(t?Le(e,this.customObject):Ae(e));}ensureMaterialIsolation(){if(this.materialsIsolated)return;let e=this.customObject.object3D;e&&(Re(e,this.customObject),this.materialsIsolated=true);}};var m=class{type;name;id;localPosition=null;position;scale;rotation;visible=true;userData={};style;_parent;_object3D=null;destroyed=false;app;constructor(e){this.app=e.app,this.type=e.type,this.name=e.name??"",this.id=e.id??this.name,this._parent=e.parent??null,this.position=e.position??[0,0,0],this.scale=e.scale??[1,1,1],this.rotation=e.rotation??[0,0,0],this.localPosition=e.localPosition??null,this.style=new N(this.app,this);}get parent(){return this._parent}get object3D(){return this._object3D}set object3D(e){this._object3D=e;}get children(){let e=[];for(let t of this.app.customObjects)t!==this&&t.parent===this&&e.push(t);return e}setVisible(e){this.destroyed||(this.object3D&&(this.object3D.visible=e,e||this.style.clearHighlight()),this.visible=e);}setPosition(e){this.object3D?.position.set(e[0],e[1],e[2]),this.position=e;}setLocalPosition(e){if(this.localPosition=e,!this.object3D)return;let t=this.parent?.object3D;t&&this.object3D.parent!==t&&t.add(this.object3D),this.object3D.position.set(e[0],e[1],e[2]);let i=new Vector3;this.object3D.getWorldPosition(i),this.position=i.toArray();}setScale(e){this.object3D?.scale.set(e[0],e[1],e[2]),this.scale=e;}setRotation(e){this.object3D?.rotation.set(MathUtils.degToRad(e[0]),MathUtils.degToRad(e[1]),MathUtils.degToRad(e[2]),"XYZ"),this.rotation=e;}destroy(){this.destroyed||(this.destroyed=true,this.style.clearHighlight(),this.disposeResources(),this.app.unregisterCustomObject(this));}disposeResources(){this.beforeDisposeResources(),this.disposeOwnedResources(),this.afterDisposeResources();}beforeDisposeResources(){}disposeOwnedResources(){}afterDisposeResources(){}syncTransformFromObject3D(e){this.position=e.position.toArray(),this.scale=e.scale.toArray(),this.rotation=[MathUtils.radToDeg(e.rotation.x),MathUtils.radToDeg(e.rotation.y),MathUtils.radToDeg(e.rotation.z)];}clearCustomObjectBinding(e,t=true){if(!t){delete e.userData.customObject;return}e.traverse(i=>{delete i.userData.customObject;});}detachObject3D(e){e.removeFromParent();}disposeObject3DSubtree(e){T(e);}setScaleState(e){this.scale=e;}setRotationState(e){this.rotation=e;}isUsingLocalPosition(){return !!this.parent&&!!this.localPosition}};var C=class extends m{building;get parent(){return this.building}constructor(e,t){super({app:t,type:"floor",name:e.name,id:e.id,parent:e.parent}),this.building=e.parent,this.object3D=e.object3D,this.syncTransformFromObject3D(e.object3D),this.app.customObjects.add(this),this.bindFloorCustomObject();}bindFloorCustomObject(){this.object3D?.traverse(e=>{e.userData.customObject=this;});}disposeOwnedResources(){this.object3D&&(this.clearCustomObjectBinding(this.object3D),this.detachObject3D(this.object3D),this.disposeObject3DSubtree(this.object3D),this.object3D=null,this.building.detachFloor(this));}releaseAfterBuildingDisposed(){this.destroyed=true,this.object3D=null;}};var O=class extends m{campus;get parent(){return this.campus}floors=[];constructor(e,t){super({app:t,type:"building",name:e.name,id:e.id,parent:e.parent}),this.campus=e.parent,this.object3D=e.object3D,this.syncTransformFromObject3D(e.object3D),this.app.customObjects.add(this),this.bindBuildingCustomObject(),this.parseFloors();}bindBuildingCustomObject(){if(!this.campus.object3D||!this.object3D)return;let e=this.name.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),t=new RegExp(`^${e}(?:_\\d+)?$`);this.campus.object3D?.traverse(i=>{t.test(i.name)&&(i.userData.customObject=this);});}parseFloors(){if(!this.campus.object3D||!this.object3D)return;let e=this.object3D.name;this.campus.object3D?.traverse(t=>{if(V(t.name,e)){let i=new C({object3D:t,parent:this,name:t.name},this.app);this.floors.push(i);}});}detachFloor(e){let t=this.floors.indexOf(e);t>=0&&this.floors.splice(t,1);}setVisible(e,t=true){if(super.setVisible(e),!!t)for(let i of this.floors)i.setVisible(e);}disposeOwnedResources(){if(!this.object3D)return;let e=[...this.floors];for(let t of e)t.destroy();this.clearCustomObjectBinding(this.object3D),this.detachObject3D(this.object3D),this.disposeObject3DSubtree(this.object3D),this.object3D=null,this.campus?.detachBuilding(this);}releaseAfterCampusDisposed(){this.destroyed=true,this.object3D=null;for(let e of this.floors)e.releaseAfterBuildingDisposed();this.floors.length=0;}};var H=class extends m{get parent(){return this._parent}constructor(e,t){super({app:t,type:"element",name:e.object3D.name,id:e.id,parent:e.parent}),this.object3D=e.object3D,this.syncTransformFromObject3D(e.object3D),this.app.customObjects.add(this),this.bindElementCustomObject();}releaseAfterCampusDisposed(){this.destroyed=true,this.object3D=null;}beforeDisposeResources(){this.style.resetColor();}disposeOwnedResources(){this.object3D&&(this.clearCustomObjectBinding(this.object3D),this.object3D=null);}bindElementCustomObject(){this.object3D?.traverse(e=>{e.userData.customObject=this;});}};var E=class extends m{buildings=[];otherElements=[];constructor(e,t){super({app:t,type:"campus",name:e.name,id:e.id,position:e.position,scale:e.scale,rotation:e.rotation}),this.loadModel(e.url,e.onReady);}detachBuilding(e){let t=this.buildings.indexOf(e);t>=0&&this.buildings.splice(t,1);}loadModel(e,t){new GLTFLoader().load(e,i=>{if(this.destroyed){T(i.scene);return}let s=new Set;i.scene.traverse(n=>{if(n.userData.customObject=this,n instanceof Mesh){if(n.castShadow=true,n.receiveShadow=true,!n.name||this.isBuildingRelatedName(n.name)||this.isFloorRelatedName(n.name))return;s.add(this.getParentGroup(n));}}),this.app.scene.add(i.scene),this.object3D=i.scene,this.setPosition(this.position),this.setScale(this.scale),this.setRotation(this.rotation),this.parseBuildings(i.scene);for(let n of s){let o=new H({object3D:n,parent:this},this.app);this.otherElements.push(o);}b(this,t,()=>this.destroyed);});}disposeOwnedResources(){let e=this.object3D;e&&(this.clearCustomObjectBinding(e),this.detachObject3D(e),this.disposeObject3DSubtree(e),this.object3D=null);for(let t of this.buildings)t.releaseAfterCampusDisposed();this.buildings.length=0;for(let t of this.otherElements)t.releaseAfterCampusDisposed();this.otherElements.length=0;}parseBuildings(e){e.traverse(t=>{if(this.isBuildingName(t.name)){let i=new O({object3D:t,parent:this,name:t.name},this.app);this.buildings.push(i);}});}getParentGroup(e){return e.parent&&e.parent instanceof Group$1?e.parent:e}isBuildingName(e){return new RegExp("^building_[^_]+$").test(e)}isBuildingRelatedName(e){return new RegExp("^building_[^_]+(?:_\\d+)?$").test(e)}isFloorRelatedName(e){return V(e)||new RegExp("^building_[^_]+_floor_\\d+_\\d+$").test(e)}};var k=class{constructor(e,t){this.app=e;this.sceneEvent=t;this.pausedEventKeys=new Set,this.handleMouseEnter=this.handleMouseEnter.bind(this),this.handleMouseLeave=this.handleMouseLeave.bind(this),this.handleDoubleClick=this.handleDoubleClick.bind(this),this.handleRightDoubleClick=this.handleRightDoubleClick.bind(this);}app;sceneEvent;pausedEventKeys;currentHoveredObject=null;init(){this.sceneEvent.on("double-click",this.handleDoubleClick),this.sceneEvent.on("right-double-click",this.handleRightDoubleClick),this.sceneEvent.on("mouse-enter",this.handleMouseEnter),this.sceneEvent.on("mouse-leave",this.handleMouseLeave);}pause(e){this.pausedEventKeys.add(e),e==="building-hover-highlight"&&(this.currentHoveredObject?.style.clearHighlight(),this.currentHoveredObject=null);}handleDoubleClick(e){if(this.isPaused("scene-level-switch"))return;let t=e.customObject,i=this.app.sceneLevel.current instanceof E,s=this.app.sceneLevel.current instanceof O;(t instanceof O&&i||t instanceof C&&s)&&this.app.sceneLevel.changeLevel(t);}handleRightDoubleClick(){this.isPaused("scene-level-switch")||this.app.sceneLevel.goToParentLevel();}resume(e){this.pausedEventKeys.delete(e);}handleMouseEnter(e){if(this.isPaused("building-hover-highlight"))return;let t=this.getHoverableObject(e.customObject);t&&(this.currentHoveredObject&&this.currentHoveredObject!==t&&this.currentHoveredObject.style.clearHighlight(),t.style.highlight(),this.currentHoveredObject=t);}handleMouseLeave(e){if(this.isPaused("building-hover-highlight"))return;let t=this.getHoverableObject(e.customObject);t&&(t.style.clearHighlight(),this.currentHoveredObject===t&&(this.currentHoveredObject=null));}isPaused(e){return this.pausedEventKeys.has(e)}getHoverableObject(e){return e instanceof O?e:e instanceof C?e.building.visible||e.building.floors.filter(i=>i!==e).every(i=>!i.visible)?null:e:null}};var _=class{constructor(e){this.app=e;this.handleCanvasClick=this.handleCanvasClick.bind(this),this.handleCanvasMouseMove=this.handleCanvasMouseMove.bind(this),this.handleCanvasMouseDown=this.handleCanvasMouseDown.bind(this),this.builtInEventManager=new k(this.app,this);}app;listeners=new Map;isInit=false;builtInEventManager;hoveredObject;latestMouseMoveEvent;hoverDirty=false;doubleClickPending=null;deferredClickTimer;primaryButtonDownPosition=null;rightDoubleClickPending=null;init(){this.isInit||(this.app.renderer.domElement.addEventListener("click",this.handleCanvasClick),this.app.renderer.domElement.addEventListener("mousemove",this.handleCanvasMouseMove),this.app.renderer.domElement.addEventListener("mousedown",this.handleCanvasMouseDown),this.builtInEventManager.init(),this.isInit=true);}on(e,t){let i=this.listeners.get(e);i||(i=new Set,this.listeners.set(e,i)),i.add(t);}off(e,t){let i=this.listeners.get(e);i&&(i.delete(t),i.size===0&&this.listeners.delete(e));}once(e,t){let i=s=>{this.off(e,i),t(s);};this.on(e,i);}tickFrame(){this.processHover(),this.hasListeners("frame-update")&&this.emit("frame-update",void 0);}processHover(){if(!this.hoverDirty||!this.latestMouseMoveEvent)return;this.hoverDirty=false;let t=re(this.app.renderer.domElement,this.app.camera.pcInstance,this.app.scene.children,this.latestMouseMoveEvent)?.object;this.hoveredObject?.userData.customObject!==t?.userData.customObject&&(this.hoveredObject&&this.emit("mouse-leave",{object:this.hoveredObject,customObject:this.hoveredObject.userData.customObject}),t&&this.emit("mouse-enter",{object:t,customObject:t.userData.customObject}),this.hoveredObject=t);}pauseBuiltInEvent(e){this.builtInEventManager.pause(e);}resumeBuiltInEvent(e){this.builtInEventManager.resume(e);}emit(e,t){let i=this.listeners.get(e);i&&i.forEach(s=>{s(t);});}handleCanvasClick(e){let t=this.hasListeners("click"),i=this.hasListeners("double-click");if(!t&&!i)return;let s=this.primaryButtonDownPosition;if(this.primaryButtonDownPosition=null,s){let x=e.clientX-s.x,A=e.clientY-s.y,M=5;if(x*x+A*A>M*M){this.clearDeferredClickTimer(),this.doubleClickPending=null;return}}let n=re(this.app.renderer.domElement,this.app.camera.pcInstance,this.app.scene.children,e),o=Pe(this.app.renderer.domElement,e),a=n?.object?.userData?.customObject,c={position:n?n.point.toArray():[0,0,0],screen:o,object:n?.object,customObject:a};if(!i){t&&this.emit("click",c);return}let l=a??n?.object,h=performance.now(),p=this.doubleClickPending,u=p?.payload.customObject??p?.payload.object,d=200;if(p&&l&&u===l&&h-p.time<=d){this.clearDeferredClickTimer(),this.doubleClickPending=null,this.emit("double-click",c);return}if(p&&(this.clearDeferredClickTimer(),t&&this.emit("click",p.payload),this.doubleClickPending=null),l){this.doubleClickPending={time:h,payload:c},this.scheduleDeferredClickResolution(d);return}this.doubleClickPending=null,t&&this.emit("click",c);}clearDeferredClickTimer(){window.clearTimeout(this.deferredClickTimer),this.deferredClickTimer=void 0;}scheduleDeferredClickResolution(e){this.clearDeferredClickTimer(),this.deferredClickTimer=setTimeout(()=>{this.doubleClickPending&&(this.emit("click",this.doubleClickPending.payload),this.doubleClickPending=null);},e);}handleCanvasMouseDown(e){if(e.button===0){(this.hasListeners("click")||this.hasListeners("double-click"))&&(this.primaryButtonDownPosition={x:e.clientX,y:e.clientY});return}if(e.button!==2||!this.hasListeners("right-double-click"))return;let t=performance.now(),i=200,s=this.rightDoubleClickPending;if(s&&t-s<=i){this.emit("right-double-click",e),this.rightDoubleClickPending=null;return}this.rightDoubleClickPending=t;}handleCanvasMouseMove(e){if(!this.hasListeners("mouse-enter")&&!this.hasListeners("mouse-leave")){this.hoverDirty=false,this.latestMouseMoveEvent=void 0;return}this.latestMouseMoveEvent=e,this.hoverDirty=true;}hasListeners(e){return (this.listeners.get(e)?.size??0)>0}};var z=class{constructor(e){this.app=e;this.init();}app;init(){let e=this.app.scene,t=new HemisphereLight(12572671,9071445,.8);e.add(t);let i=new DirectionalLight(16777215,10);i.position.set(18,60,12),i.target.position.set(0,0,0),e.add(i.target),e.add(i),i.castShadow=true,i.shadow.mapSize.set(2048,2048),i.shadow.camera.near=.5,i.shadow.camera.far=300,i.shadow.camera.left=-120,i.shadow.camera.right=120,i.shadow.camera.top=120,i.shadow.camera.bottom=-120,i.shadow.bias=-2e-4,i.shadow.normalBias=.02;}};var K=class extends m{isFrameUpdateSubscribed=false;pathTweenGroup=null;pathTween=null;isAnimationPlaying=false;animationClips=[];animationMixer=null;animationActions=null;animationTimer=null;constructor(e,t){super({app:t,type:"thing",name:e.name,id:e.id,parent:e.parent,position:e.position,scale:e.scale,rotation:e.rotation,localPosition:e.localPosition}),this.handleFrameUpdate=this.handleFrameUpdate.bind(this),this.handleAnimationFinished=this.handleAnimationFinished.bind(this),this.loadModel(e.url,e.onReady);}get animationNames(){return this.animationClips.map(e=>e.name)}playAnimation(e,t=true){this.ensureAnimation();let i=this.getAnimationAction(e);i&&(i.reset(),i.setLoop(t?LoopRepeat:LoopOnce,t?1/0:1),i.clampWhenFinished=!t,i.play(),this.syncAnimationPlaying());}pauseAnimation(e){if(!this.animationMixer)return;this.ensureAnimation();let t=this.getAnimationAction(e);t?.isRunning()&&(t.paused=true,this.syncAnimationPlaying());}resumeAnimation(e){if(!this.animationMixer)return;this.ensureAnimation();let t=this.getAnimationAction(e);!t?.enabled||!t.paused||(t.paused=false,this.syncAnimationPlaying());}stopAnimation(e){this.animationMixer&&(this.ensureAnimation(),this.getAnimationAction(e)?.stop(),this.syncAnimationPlaying());}setPosition(e){if(super.setPosition(e),!this.object3D)return;let t=new Box3().setFromObject(this.object3D).min.y;this.object3D.position.set(e[0],2*e[1]-t,e[2]);}setLocalPosition(e){if(super.setLocalPosition(e),!this.object3D)return;let t=this.parent?.object3D;if(!t)return;let i=new Box3().setFromObject(this.object3D).min,s=t.worldToLocal(i.clone()).y;this.object3D.position.set(e[0],2*e[1]-s,e[2]),this.object3D.updateMatrixWorld(true);}moveAlongPath(e,t,i=false){if(!this.object3D||e.length===0||t<=0)return Promise.resolve();let s=e.map(p=>new Vector3(...p)),n=F(s);if(n===0)return Promise.resolve();let o=s[0],a=new Vector3;this.setPosition(o.toArray()),S(s,n,0,o,a),this.setPathYaw(o,a),this.stopPathMovement(),this.ensurePathAnimation();let c={t:0},l=new Vector3,h=this.pathTweenGroup;return new Promise(p=>{let u=new Tween(c,h).to({t:1},t*1e3).easing(Easing.Linear.None);i&&u.repeat(1/0).repeatDelay(0),this.pathTween=u.onUpdate(()=>{this.object3D&&(R(s,n,c.t,l),S(s,n,c.t,l,a),this.setPosition(l.toArray()),this.setPathYaw(l,a));}).onComplete(()=>{this.pathTween=null,p();}).onStop(()=>{this.pathTween=null,p();}).start(performance.now());})}stopPathMovement(){this.pathTween?.stop(),this.pathTween=null;}disposeOwnedResources(){this.stopPathMovement(),this.animationMixer?.removeEventListener("finished",this.handleAnimationFinished),this.animationMixer?.stopAllAction(),this.animationActions?.clear(),this.animationMixer=null,this.animationClips=[],this.isAnimationPlaying=false;let e=this.object3D;e&&(this.clearCustomObjectBinding(e),this.detachObject3D(e),this.disposeObject3DSubtree(e),this.object3D=null);}afterDisposeResources(){this.app.sceneEvent.off("frame-update",this.handleFrameUpdate);}setPathYaw(e,t){if(!this.object3D)return;let i=t.x-e.x,s=t.z-e.z;i*i+s*s<=1e-10||this.object3D.rotation.set(MathUtils.degToRad(this.rotation[0]),Math.atan2(i,s),MathUtils.degToRad(this.rotation[2]));}loadModel(e,t){new GLTFLoader().load(e,i=>{if(this.destroyed){T(i.scene);return}i.scene.traverse(o=>{o.userData.customObject=this;}),this.object3D=i.scene,this.animationClips=i.animations,i.animations.length>0&&(this.animationMixer=new AnimationMixer(i.scene),this.animationMixer.addEventListener("finished",this.handleAnimationFinished));let s=this.parent?.object3D,n=this.isUsingLocalPosition()&&s&&this.localPosition;n?s.add(i.scene):this.app.scene.add(i.scene),this.setScale(this.scale),this.setRotation(this.rotation),n&&this.localPosition?this.setLocalPosition(this.localPosition):this.setPosition(this.position),b(this,t,()=>this.destroyed);});}getAnimationAction(e){if(!this.animationMixer)return null;this.ensureAnimation();let t=this.animationActions.get(e);if(!t){let i=this.animationClips.find(s=>s.name===e);if(!i)return null;t=this.animationMixer.clipAction(i),this.animationActions.set(e,t);}return t}syncAnimationPlaying(){let e=false;for(let t of this.animationActions?.values()??[])if(t.isRunning()&&!t.paused){e=true;break}this.isAnimationPlaying=e;}handleAnimationFinished(){this.syncAnimationPlaying();}ensurePathAnimation(){this.pathTweenGroup||(this.pathTweenGroup=new Group),this.ensureFrameUpdate();}ensureAnimation(){this.animationActions||(this.animationActions=new Map,this.animationTimer=new Timer),this.ensureFrameUpdate();}ensureFrameUpdate(){this.isFrameUpdateSubscribed||(this.isFrameUpdateSubscribed=true,this.app.sceneEvent.on("frame-update",this.handleFrameUpdate));}handleFrameUpdate(){this.destroyed||(this.pathTweenGroup&&this.pathTweenGroup.update(performance.now()),this.animationMixer&&this.animationTimer&&(this.animationTimer.update(),this.animationMixer.update(this.animationTimer.getDelta())));}};var He=new Vector3(0,1,0),Lt=4;function ze(r){let e=r.points.map(([t,i,s])=>new Vector3(t,i,s));return r.useTextureUv?Rt(e,r.width,r.cornerRadius,r.cornerSegments,r.texturePeriod):It(e,r.width,r.cornerRadius,r.cornerSegments)}function Rt(r,e,t,i,s){let n=e/2,o=Bt(r,t,i),a={positions:[],uvs:[],indices:[],vertexCount:0},c=0;for(let l of o){if(l.kind==="strip"){let h=l.from.distanceTo(l.to);if(h<1e-6)continue;ke(a,l.from,l.to,n,c,c+h,s),c+=h;continue}if(l.kind==="arc"){for(let h=0;h<l.points.length-1;h++){let p=l.points[h],u=l.points[h+1],d=p.distanceTo(u);d<1e-6||(ke(a,p,u,n,c,c+d,s),c+=d);}continue}$e(l.incomingDir,l.outgoingDir)&&Ft(a,l.point,l.incomingDir,l.outgoingDir,n,c,s);}return We(a)}function It(r,e,t,i){let s=Me(r,t,i),n=Ut(s,e/2),o={positions:[],uvs:[],indices:[],vertexCount:0};for(let a=0;a<n.length;a++)de(o,n[a],0,false,1);for(let a=0;a<n.length-1;a++){let c=a*2,l=a*2+1,h=a*2+2,p=a*2+3;o.indices.push(c,l,h),o.indices.push(l,p,h);}return We(o)}function Bt(r,e,t){let i=[];if(r.length<2)return i;if(e>0&&r.length>=3){let s=r[0];for(let n=1;n<r.length-1;n++){let o=ie(r[n-1],r[n],r[n+1],e,t);if(o){i.push({kind:"strip",from:s,to:o.t1}),i.push({kind:"arc",points:[o.t1,...o.arcPoints,o.t2]}),s=o.t2;continue}i.push({kind:"strip",from:s,to:r[n]}),s=r[n];}return i.push({kind:"strip",from:s,to:r[r.length-1]}),i}for(let s=0;s<r.length-1;s++)if(i.push({kind:"strip",from:r[s],to:r[s+1]}),s<r.length-2){let n=P(r[s],r[s+1]),o=P(r[s+1],r[s+2]);$e(n,o)&&i.push({kind:"corner",point:r[s+1],incomingDir:n,outgoingDir:o});}return i}function ke(r,e,t,i,s,n,o){let a=W(e,t,i,true),c=W(t,e,i,false);Ke(r,a,c,s,n,o);}function Ft(r,e,t,i,s,n,o){let a=_e(e,t,s),c=_e(e,i,s);Ke(r,a,c,n,n,o);}function Ke(r,e,t,i,s,n){let o=r.vertexCount;de(r,e,i,true,n);let a=r.vertexCount;de(r,t,s,true,n),r.indices.push(o,o+1,a),r.indices.push(o+1,a+1,a);}function de(r,e,t,i,s){if(r.positions.push(e.left.x,e.left.y,e.left.z,e.right.x,e.right.y,e.right.z),i){let n=t/s;r.uvs.push(0,n,1,n);}r.vertexCount+=2;}function We(r){let e=new BufferGeometry;return e.setAttribute("position",new BufferAttribute(new Float32Array(r.positions),3)),r.uvs.length>0&&e.setAttribute("uv",new BufferAttribute(new Float32Array(r.uvs),2)),e.setIndex(r.indices),e.computeVertexNormals(),e}function _e(r,e,t){let i=fe(e,e),s=new Vector3().crossVectors(e,i).normalize();return {left:r.clone().addScaledVector(s,t),right:r.clone().addScaledVector(s,-t)}}function $e(r,e){return r.dot(e)<1-1e-6}function Ut(r,e){let t=[],i=r.length;if(i<2)return t;t.push(W(r[0],r[1],e,true));for(let s=1;s<i-1;s++){let n=r[s-1],o=r[s],a=r[s+1];t.push(Vt(n,o,a,e));}return t.push(W(r[i-1],r[i-2],e,false)),t}function W(r,e,t,i){let s=i?P(r,e):P(e,r),n=fe(s,s),o=new Vector3().crossVectors(s,n).normalize();return {left:r.clone().addScaledVector(o,t),right:r.clone().addScaledVector(o,-t)}}function Vt(r,e,t,i){let s=P(r,e),n=P(e,t),o=fe(s,n),a=new Vector3().crossVectors(s,o).normalize(),c=new Vector3().addVectors(s,n);if(c.lengthSq()<1e-10)return {left:e.clone().addScaledVector(a,i),right:e.clone().addScaledVector(a,-i)};c.normalize();let l=new Vector3().crossVectors(c,o).normalize(),h=l.dot(a);Math.abs(h)<1e-6&&(h=1);let p=i*Lt,u=i/h;return u=Math.max(-p,Math.min(p,u)),{left:e.clone().addScaledVector(l,u),right:e.clone().addScaledVector(l,-u)}}function P(r,e){return new Vector3().subVectors(e,r).normalize()}function fe(r,e){let t=new Vector3().crossVectors(r,e);return t.lengthSq()>1e-10?t.normalize():Math.abs(r.dot(He))>.999?new Vector3(0,0,1):He.clone()}function be(r){return Math.max(r,.001)}function ye(r){return Math.max(r,0)}function $(r,e){return r+e}function Xe(r){return new MeshBasicMaterial({color:r,side:DoubleSide,depthWrite:true,transparent:false})}function Qe(r,e){let t=new MeshBasicMaterial({map:r,color:16777215,side:DoubleSide,transparent:true,depthWrite:false});return t.onBeforeCompile=i=>{i.uniforms.uImageFraction=e,i.fragmentShader=`uniform float uImageFraction;
|
|
2
|
+
`+i.fragmentShader,i.fragmentShader=i.fragmentShader.replace("#include <map_fragment>",`#ifdef USE_MAP
|
|
3
|
+
float twLocalV = fract( vMapUv.y );
|
|
4
|
+
vec2 twPatchUv = vec2( vMapUv.x, twLocalV / uImageFraction );
|
|
5
|
+
vec4 sampledDiffuseColor = texture2D( map, twPatchUv );
|
|
6
|
+
if ( twLocalV > uImageFraction ) {
|
|
7
|
+
sampledDiffuseColor.a = 0.0;
|
|
8
|
+
}
|
|
9
|
+
diffuseColor *= sampledDiffuseColor;
|
|
10
|
+
#endif`);},t}var q=class extends m{points;width;cornerRadius;cornerSegments;color;meshMaterial=null;imagePath=null;textureScrollSpeed;textureWorldSize;textureGap;enableTextureScroll;texture=null;textureScrollOffset=0;textureImageFractionUniform={value:1};isFrameUpdateSubscribed=false;frameTimer=null;constructor(e,t){super({app:t,type:"polyline",name:e.name,id:e.id,parent:e.parent}),this.handleFrameUpdate=this.handleFrameUpdate.bind(this),this.points=e.points.map(i=>[...i]),this.width=e.width,this.cornerRadius=e.cornerRadius??0,this.cornerSegments=e.cornerSegments??10,this.color=B(e.color).color,this.imagePath=e.imagePath??null,this.textureScrollSpeed=e.textureScrollSpeed??0,this.textureWorldSize=be(e.textureWorldSize??2),this.textureGap=ye(e.textureGap??0),this.enableTextureScroll=e.enableTextureScroll??false,this.updateTextureImageFraction(),this.buildLine(),this.imagePath?this.loadTexture(e.onReady):b(this,e.onReady,()=>this.destroyed);}setPoints(e){this.destroyed||(this.points=e.map(t=>[...t]),this.rebuildGeometry());}setWidth(e){this.destroyed||(this.width=e,this.rebuildGeometry());}setCornerRadius(e){this.destroyed||(this.cornerRadius=e,this.rebuildGeometry());}setCornerSegments(e){this.destroyed||(this.cornerSegments=e,this.rebuildGeometry());}setColor(e){this.destroyed||!this.meshMaterial||(this.color=B(e).color,this.texture||this.meshMaterial.color.copy(this.color));}setImagePath(e){this.destroyed||(this.imagePath=e,this.rebuildGeometry(),this.loadTexture());}setTextureScrollSpeed(e){this.destroyed||(this.textureScrollSpeed=e);}setTextureWorldSize(e){this.destroyed||(this.textureWorldSize=be(e),this.refreshTextureLayout());}setTextureGap(e){this.destroyed||(this.textureGap=ye(e),this.refreshTextureLayout());}setEnableTextureScroll(e){this.destroyed||(this.enableTextureScroll=e,this.syncFrameSubscription());}disposeOwnedResources(){let e=this.object3D;e&&(this.clearCustomObjectBinding(e),this.detachObject3D(e),e.geometry.dispose(),this.disposeMaterial(),this.texture?.dispose(),this.texture=null,this.object3D=null);}afterDisposeResources(){this.unsubscribeFrameUpdate();}buildLine(){let e=Xe(this.color.getHex()),t=new Mesh(this.createMeshGeometry(),e);t.userData.customObject=this,this.meshMaterial=e,this.object3D=t,this.app.scene.add(t);}rebuildGeometry(){if(!this.object3D)return;let e=this.createMeshGeometry();this.object3D.geometry.dispose(),this.object3D.geometry=e;}createMeshGeometry(){return ze({points:this.points,width:this.width,cornerRadius:this.cornerRadius,cornerSegments:this.cornerSegments,useTextureUv:this.shouldUseTextureUv(),texturePeriod:$(this.textureWorldSize,this.textureGap)})}loadTexture(e){if(!this.imagePath)return;let t=this.imagePath;new TextureLoader().load(t,i=>{if(this.destroyed||this.imagePath!==t){i.dispose();return}this.texture?.dispose(),this.texture=i,i.colorSpace=SRGBColorSpace,this.applyTextureWrap(),this.applyTexturedMaterial(),this.applyTextureOffset(),this.syncFrameSubscription(),b(this,e,()=>this.destroyed);},void 0,()=>{b(this,e,()=>this.destroyed);});}applyTexturedMaterial(){if(!this.texture||!this.object3D)return;let e=Qe(this.texture,this.textureImageFractionUniform);this.disposeMaterial(),this.meshMaterial=e,this.object3D.material=e;}applyTextureOffset(){this.texture&&this.texture.offset.set(0,this.textureScrollOffset/$(this.textureWorldSize,this.textureGap));}applyTextureWrap(){this.texture&&(this.texture.wrapS=ClampToEdgeWrapping,this.texture.wrapT=ClampToEdgeWrapping,this.texture.generateMipmaps=false,this.texture.minFilter=LinearFilter);}syncFrameSubscription(){if(this.enableTextureScroll&&this.texture){this.ensureFrameUpdate();return}this.unsubscribeFrameUpdate();}ensureFrameUpdate(){this.isFrameUpdateSubscribed||(this.isFrameUpdateSubscribed=true,this.frameTimer||(this.frameTimer=new Timer),this.app.sceneEvent.on("frame-update",this.handleFrameUpdate));}unsubscribeFrameUpdate(){this.isFrameUpdateSubscribed&&(this.isFrameUpdateSubscribed=false,this.app.sceneEvent.off("frame-update",this.handleFrameUpdate));}handleFrameUpdate(){this.destroyed||!this.enableTextureScroll||!this.texture||this.textureScrollSpeed===0||this.frameTimer&&(this.frameTimer.update(),this.textureScrollOffset-=this.textureScrollSpeed*this.frameTimer.getDelta(),this.applyTextureOffset());}shouldUseTextureUv(){return !!(this.imagePath||this.texture)}updateTextureImageFraction(){this.textureImageFractionUniform.value=this.textureWorldSize/$(this.textureWorldSize,this.textureGap);}refreshTextureLayout(){this.updateTextureImageFraction(),this.rebuildGeometry(),this.applyTextureOffset();}disposeMaterial(){this.meshMaterial&&(this.meshMaterial.map=null,this.meshMaterial.dispose(),this.meshMaterial=null);}};var Y=class extends m{textureAspect=1;imagePath;is3D;enablePerspectiveScale;size;constructor(e,t){super({app:t,type:"marker",name:e.name,id:e.id,parent:e.parent,position:e.position,scale:e.scale,rotation:e.rotation}),this.imagePath=e.imagePath,this.is3D=e.is3D??false,this.enablePerspectiveScale=e.enablePerspectiveScale??false,this.size=e.size,this.loadTexture(e.onReady);}setScale(e){if(!this.is3D){this.setScaleState(e);return}super.setScale(e);}setRotation(e){if(!this.is3D){this.setRotationState(e);return}super.setRotation(e);}setPosition(e){if(super.setPosition(e),!this.object3D)return;let t=this.object3D.scale.y;this.object3D.position.set(e[0],e[1]+t/2,e[2]);}loadTexture(e){new TextureLoader().load(this.imagePath,i=>{if(this.destroyed){i.dispose();return}i.colorSpace=SRGBColorSpace;let s=i.image;this.textureAspect=s.width>0&&s.height>0?s.width/s.height:1;let n=this.is3D?this.createMeshMarker(i):this.createSpriteMarker(i);this.object3D=n,n.userData.customObject=this,this.is3D&&(this.setScale(this.scale),this.setRotation(this.rotation)),this.setPosition(this.position),this.app.scene.add(n),b(this,e,()=>this.destroyed);},void 0);}disposeOwnedResources(){if(this.object3D){if(this.clearCustomObjectBinding(this.object3D,false),this.detachObject3D(this.object3D),this.object3D instanceof Sprite){let e=this.object3D.material;this.object3D.onBeforeRender=()=>{},e.map?.dispose(),e.dispose();}else if(this.object3D instanceof Mesh){let e=this.object3D.material,t=this.object3D.geometry;if(Array.isArray(e))for(let i of e)i.dispose();else e instanceof MeshStandardMaterial&&e.map?.dispose(),e.dispose();t.dispose();}this.object3D=null;}}applyPixelScale(e,t){let[i,s]=this.size,n=this.app.renderer.domElement.clientHeight;if(n<=0||i<=0||s<=0)return;let a=2*t.position.distanceTo(new Vector3(this.position[0],this.position[1],this.position[2]))*Math.tan(MathUtils.degToRad(t.fov/2)),c=a*(s/n),l=a*(i/n),h=c*this.textureAspect,p=new Vector3(l||h,c,1);e.scale.copy(p);}createSpriteMarker(e){let t=new SpriteMaterial({map:e,transparent:true,depthWrite:false}),i=new Sprite(t);return this.applyPixelScale(i,this.app.camera.pcInstance),this.enablePerspectiveScale||(i.onBeforeRender=(s,n,o)=>{o instanceof PerspectiveCamera&&(this.applyPixelScale(i,o),this.setPosition(this.position));}),i}createMeshMarker(e){let[t,i]=this.size,n=i>0?i:1,o=t>0?t:n*this.textureAspect,a=new PlaneGeometry(o,n),c=new MeshStandardMaterial({map:e,transparent:true,side:DoubleSide}),l=new Mesh(a,c);return l.scale.set(1,1,1),l}};var X=class{constructor(e,t,i){this.renderer=e;this.scene=t;this.camera=i;let s=this.renderer.getSize(new Vector2),n=Math.max(1,s.x),o=Math.max(1,s.y),a=this.renderer.getPixelRatio(),c=new WebGLRenderTarget(n*a,o*a,{samples:4}),l=new EffectComposer(this.renderer,c);l.setPixelRatio(a),l.setSize(n,o);let h=new RenderPass(this.scene,this.camera);l.addPass(h);let p=new OutlinePass(new Vector2(n,o),this.scene,this.camera);p.visibleEdgeColor.set("#ffd400"),p.hiddenEdgeColor.set("#ffd400"),p.edgeStrength=3,p.edgeGlow=1,p.edgeThickness=2,p.pulsePeriod=0,l.addPass(p),l.addPass(new OutputPass),this.composer=l,this.outlinePass=p;}renderer;scene;camera;composer;outlinePass;resize(e,t){this.composer.setSize(e,t),this.outlinePass.setSize(e,t);}render(){this.composer.render();}setSelection(e){this.outlinePass.selectedObjects=[e];}clearSelection(){this.outlinePass.selectedObjects=[];}dispose(){this.composer.dispose();}};var Q=class{constructor(e){this.app=e;}app;level=null;levelHistoryStack=[];get current(){return this.level}changeLevel(e){if(this.level===e)return;let t=this.level;this.level!==null&&this.isImmediateChildLevel(this.level,e)?this.pushCurrentLevelHistory():this.levelHistoryStack=[],this.syncVisibilityByTarget(e),this.level=e;let s=e.type==="campus";this.app.camera.focusObject(e,{distance:s?700:void 0}),s&&(this.levelHistoryStack=[]),this.app.sceneEvent.emit("level-change",{previous:t,current:e});}applyDefault(e){this.level===null&&(this.level=e,this.app.sceneEvent.emit("level-change",{previous:null,current:e}));}goToParentLevel(){let e=this.level;if(!e)return;let t=null;switch(e.type){case "floor":{t=e.building;break}case "building":{t=e.campus;break}}if(!t)return;let i=e;this.syncVisibilityByTarget(t),this.level=t,this.restoreCameraIfHistoryMatch(),this.app.sceneEvent.emit("level-change",{previous:i,current:t});}isImmediateChildLevel(e,t){return pe(e)&&G(t)?t.campus===e:G(e)&&he(t)?t.building===e:false}syncVisibilityByTarget(e){pe(e)?this.showCampus(e):G(e)?this.showBuilding(e):he(e)&&this.showFloor(e);}showCampus(e){for(let t of e.buildings)t.setVisible(true);for(let t of e.otherElements)t.setVisible(true);}showBuilding(e){let t=e.campus;for(let i of t.buildings){if(i===e){i.setVisible(false,false);for(let s of i.floors)s.setVisible(true);continue}i.setVisible(false);}for(let i of t.otherElements)i.setVisible(false);}showFloor(e){this.showBuilding(e.building);for(let t of e.building.floors)t.setVisible(t===e);}pushCurrentLevelHistory(){if(!this.level)return;let e=this.app.camera.getCamera();this.levelHistoryStack.push({levelObject:this.level,cameraOptions:e});}restoreCameraIfHistoryMatch(){let e=this.levelHistoryStack.pop();!e||!this.level||e.levelObject===this.level&&this.app.camera.setCamera({position:e.cameraOptions.position,target:e.cameraOptions.target});}};var Z=class r extends m{static OVERLAY_ROOT_ID="twin3d-ui-anchor-overlay-root-id";anchorContainer=null;offsetPx;uiElement;is3D;meshSize;constructor(e,t){if(!e.element)throw new Error("UIAnchor \u7F3A\u5C11 element");if(super({app:t,type:"ui-anchor",name:e.name,id:e.id,parent:e.parent,position:e.position,scale:e.scale,rotation:e.rotation}),this.handleFrameUpdate=this.handleFrameUpdate.bind(this),this.is3D=e.is3D??false,this.uiElement=e.element,this.meshSize=this.getMeshSize(this.uiElement instanceof HTMLCanvasElement?this.uiElement:void 0),this.is3D){if(!(this.uiElement instanceof HTMLCanvasElement))throw new Error("UIAnchor \u5728 3D \u6A21\u5F0F\u4E0B element \u5FC5\u987B\u662F HTMLCanvasElement");this.create3DAnchor(),this.setScale(this.scale),this.setRotation(this.rotation),this.setPosition(this.position);}else {if(this.uiElement instanceof HTMLCanvasElement)throw new Error("UIAnchor \u5728 2D \u6A21\u5F0F\u4E0B element \u5FC5\u987B\u662F HTMLElement");this.offsetPx=e.offsetPx??[0,-12],this.anchorContainer=this.createAnchorContainer(),this.subscribeFrameUpdate();}b(this,e.onReady,()=>this.destroyed);}setVisible(e){super.setVisible(e),this.anchorContainer&&(this.anchorContainer.style.display=e?"block":"none");}setPosition(e){super.setPosition(e),this.is3D&&this.object3D&&this.object3D.position.set(e[0],e[1]+this.meshSize[1]/2,e[2]);}setScale(e){if(!this.is3D){this.setScaleState(e);return}super.setScale(e);}setRotation(e){if(!this.is3D){this.setRotationState(e);return}super.setRotation(e);}update(){if(!this.visible||!this.anchorContainer)return;let e=this.app.camera.pcInstance,t=this.app.renderer.domElement,i=t.clientWidth,s=t.clientHeight;if(i<=0||s<=0)return;let n=new Vector3().fromArray(this.position).project(e);if(n.z>1||n.z<-1){this.anchorContainer.style.display="none";return}let a=this.offsetPx??[0,0],c=(n.x*.5+.5)*i+a[0],l=(-n.y*.5+.5)*s+a[1];this.anchorContainer.style.transform=`translate3d(${c}px, ${l}px, 0) translate(-50%, -100%)`,this.anchorContainer.style.display="block";}beforeDisposeResources(){if(this.anchorContainer){this.anchorContainer.remove();let e=this.getOverlayRoot();e?.childElementCount===0&&e.remove();}}disposeOwnedResources(){if(this.object3D){this.clearCustomObjectBinding(this.object3D,false),this.detachObject3D(this.object3D);let e=this.object3D.material;if(Array.isArray(e))for(let t of e)t instanceof MeshBasicMaterial&&t.map?.dispose(),t.dispose();else e instanceof MeshBasicMaterial&&e.map?.dispose(),e.dispose();this.object3D.geometry.dispose(),this.object3D=null;}}afterDisposeResources(){this.app.sceneEvent.off("frame-update",this.handleFrameUpdate);}createAnchorContainer(){let e=this.app.renderer.domElement.parentElement;if(!e)throw new Error("UIAnchor \u65E0\u6CD5\u627E\u5230\u6E32\u67D3\u5BB9\u5668");let t=this.getOverlayRoot();t||(t=document.createElement("div"),t.id=r.OVERLAY_ROOT_ID,t.style.position="absolute",t.style.inset="0 auto auto 0",t.style.width="100%",t.style.height="100%",t.style.pointerEvents="none",t.style.overflow="hidden",e.appendChild(t));let i=document.createElement("div");return i.style.position="absolute",i.style.willChange="transform",t.appendChild(i),i.appendChild(this.uiElement),i}subscribeFrameUpdate(){this.app.sceneEvent.on("frame-update",this.handleFrameUpdate);}handleFrameUpdate(){this.destroyed||this.update();}getOverlayRoot(){return document.getElementById(r.OVERLAY_ROOT_ID)}create3DAnchor(){let e=new CanvasTexture(this.uiElement);e.colorSpace=SRGBColorSpace,e.needsUpdate=true;let t=new PlaneGeometry(this.meshSize[0],this.meshSize[1]),i=new MeshBasicMaterial({map:e,transparent:true,side:DoubleSide,depthWrite:false}),s=new Mesh(t,i);s.userData.customObject=this,this.object3D=s,this.app.scene.add(s);}getMeshSize(e){if(!e||e.width<=0||e.height<=0)return [12,6.75];let t=12;return [t,t*(e.height/e.width)]}};var D=class r{selectedItems;constructor(e){this.selectedItems=[...e];}items(){return [...this.selectedItems]}get first(){return this.selectedItems[0]}forEach(e){let t=0;for(let i of this.selectedItems)e(i,t),t+=1;return this}filter(e){let t=[],i=0;for(let s of this.selectedItems)e(s,i)&&t.push(s),i+=1;return new r(t)}setVisible(e){for(let t of this.selectedItems)t.setVisible(e);return this}};var J=class{constructor(e){this.app=e;}app;queryAll(){return new D(this.app.customObjects)}queryByName(e,t={}){let{exact:i=true,caseSensitive:s=true}=t,n=this.normalizeName(e,s),o=[];for(let a of this.app.customObjects){let c=this.normalizeName(a.name,s);(i?c===n:c.includes(n))&&o.push(a);}return new D(o)}queryById(e){let t=[];for(let i of this.app.customObjects)i.id===e&&t.push(i);return new D(t)}queryByType(e){let t=[];for(let i of this.app.customObjects)i.type===e&&t.push(i);return new D(t)}normalizeName(e,t){return t?e:e.toLowerCase()}};var st=class{scene;camera;renderer;sceneLights;sceneEvent;outlineHighlighter;sceneLevel;objectQuery;customObjects=new Set;containerEl;resizeObserver;constructor(){this.handleWindowResize=this.handleWindowResize.bind(this),this.runFrame=this.runFrame.bind(this),this.scene=new Scene,this.sceneLights=new z(this),this.camera=new U(1,1),this.renderer=new WebGLRenderer({antialias:true}),this.sceneEvent=new _(this),this.sceneLevel=new Q(this),this.objectQuery=new J(this),this.initRenderer(),this.outlineHighlighter=new X(this.renderer,this.scene,this.camera.pcInstance);}init(e){if(this.containerEl)return;let t=document.getElementById(e);if(!t)throw new Error(`\u627E\u4E0D\u5230 #${e}`);this.containerEl=t;let i=t.getBoundingClientRect(),s=i.width,n=i.height;this.syncAspect(s,n),this.renderer.setSize(s,n),t.appendChild(this.renderer.domElement),this.sceneEvent.init(),this.camera.init(this.renderer.domElement),this.resizeObserver=new ResizeObserver(this.handleWindowResize),this.resizeObserver.observe(t),requestAnimationFrame(this.runFrame);}unregisterCustomObject(e){this.customObjects.delete(e);}create(e){let t;switch(e.type){case "campus":t=new E(e,this),this.sceneLevel.applyDefault(t);break;case "marker":t=new Y(e,this);break;case "ui-anchor":t=new Z(e,this);break;case "thing":t=new K(e,this);break;case "polyline":t=new q(e,this);break;default:throw new Error("\u672A\u652F\u6301\u7684\u7C7B\u578B\uFF01")}return this.customObjects.add(t),t}setSkyBox(e){new CubeTextureLoader().load(e,i=>{this.scene.background=i;});}syncSize(){if(!this.containerEl)return;let e=this.containerEl.getBoundingClientRect(),t=e.width,i=e.height;t===0||i===0||(this.syncAspect(t,i),this.renderer.setSize(t,i),this.outlineHighlighter.resize(t,i));}runFrame(){requestAnimationFrame(this.runFrame),this.camera.updateCameraTweens(),this.camera.orbitControls?.update(),this.sceneEvent.tickFrame(),this.outlineHighlighter.render();}handleWindowResize(){this.syncSize();}syncAspect(e,t){this.camera.pcInstance.aspect=e/t,this.camera.pcInstance.updateProjectionMatrix();}initRenderer(){this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.shadowMap.enabled=true,this.renderer.shadowMap.type=PCFShadowMap,this.renderer.outputColorSpace=SRGBColorSpace;}};export{st as App,m as BaseObject,N as BaseStyle,Ee as BuiltInEventKey,se as ObjectNamePrefix,f as ObjectType,j as SceneEventType,G as isBuilding,pe as isCampus,ue as isCampusDerivedObject,he as isFloor};
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zf-twin-3d",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Three.js digital twin scene library",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"main": "./dist/index.mjs",
|
|
11
|
+
"module": "./dist/index.mjs",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.mjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"dev": "tsup --watch"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"@tweenjs/tween.js": "^23.1.3",
|
|
28
|
+
"three": "^0.183.2"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@tweenjs/tween.js": "^23.1.3",
|
|
32
|
+
"@types/three": "^0.183.1",
|
|
33
|
+
"three": "^0.183.2",
|
|
34
|
+
"tsup": "^8.5.1",
|
|
35
|
+
"typescript": "^6.0.2"
|
|
36
|
+
}
|
|
37
|
+
}
|