babylon-viewport-gizmo
Version:
A simple Babylonjs camera perspective preview tool.
3 lines (2 loc) • 6.62 kB
JavaScript
import{DynamicTexture as e,MeshBuilder as i,StandardMaterial as a,Color3 as t,AbstractMesh as n,Engine as s,Scene as r,ArcRotateCamera as h,Vector3 as o,HemisphericLight as l,TransformNode as m,Color4 as c}from"@babylonjs/core";const C=(s,r,h,o,l=.2)=>{const m=new e(`${h}Texture`,{width:256,height:256},s),c=m.getContext();c.fillStyle=r,c.fillRect(0,0,256,256),c.font="bold 200px Arial",c.fillStyle="white",c.textAlign="center",c.textBaseline="middle",c.fillText(h,128,128),m.update();const C=i.CreatePlane(`${h}Sprite`,{width:l,height:l},s),d=new a(`${h}Material`,s);return d.diffuseTexture=m,d.emissiveColor=new t(.5,.5,.5),d.specularColor=new t(0,0,0),d.backFaceCulling=!1,C.material=d,C.position=o,C.billboardMode=n.BILLBOARDMODE_ALL,C};class d{constructor(e){this._clickHandler=null,this._mainCameraObserver=null,this._miniCameraObserver=null,this._canvas=this.createCanvas(),this._engine=new s(this._canvas,!0,{preserveDrawingBuffer:!0,stencil:!0}),this._scene=new r(this._engine),this._miniCamera=new h("miniCamera",-Math.PI/2,Math.PI/2.5,20,o.Zero(),this._scene),this._miniCamera.attachControl(this._canvas,!0),this._miniCamera.upperRadiusLimit=12,this._miniCamera.lowerRadiusLimit=12,this._mainCamera=e,this.createHemisphericLight(this._scene),this.createBox(this._scene);const{xPlane:i,yPlane:a,zPlane:t,xPlane2:n,yPlane2:l,zPlane2:m}=this.createAxis(this._scene);this.needClickMeshs={xPlane:i,yPlane:a,zPlane:t,xPlane2:n,yPlane2:l,zPlane2:m},this.onResize(),this.mainToMini(),setTimeout((()=>{this.miniToMain()}),0),this.miniInteraction(this._canvas,this._scene),this.renderer()}createCanvas(){const e=document.createElement("canvas");return e.id="viewportGizmo",e.style.width="200px",e.style.height="200px",e.style.position="absolute",e.style.bottom="20px",e.style.right="20px",e.style.zIndex="9999",e.style.touchAction="none",e.style.borderRadius="100%",e.addEventListener("focus",(()=>{e.style.border="2px solid #ccc"})),e.addEventListener("blur",(()=>{e.style.border="2px solid transparent"})),document.body.appendChild(e),e}createHemisphericLight(e){new l("miniLight",new o(1,1,0),e)}createBox(e){i.CreateBox("box",{size:1.5},e)}createZSQ(e,a,t,n,s=.2){let r;const h=new m("directionGroup",e);h.position.y=1.5,i.CreateCylinder("sp",{diameterTop:.2,diameterBottom:.2,height:3},e).parent=h;const l=C(e,a,t,n,s);l.parent=h;const c=s-.5;if("X"===t){const i=new o(-n.x-2.5,-n.y,-n.z);r=C(e,a,"",i,c),r.parent=h}else if("Y"===t){const i=new o(-n.x,-n.y-2.5,-n.z);r=C(e,a,"",i,c),r.parent=h}else if("Z"===t){const i=new o(-n.x,-n.y,-n.z-2.5);r=C(e,a,"",i,c),r.parent=h}return r&&r.material&&(r.material.alpha=.5),{node:h,plane:l,plane2:r}}createAxis(e){const{node:i,plane:a,plane2:n}=this.createZSQ(e,t.Red().toHexString(),"X",new o(2.2,0,0),1.2);i.position.x=1.5,i.position.y=0,i.rotation.z=Math.PI/2;const{node:s,plane:r,plane2:h}=this.createZSQ(e,t.Green().toHexString(),"Y",new o(0,2.2,0),1.2),{node:l,plane:m,plane2:c}=this.createZSQ(e,t.Blue().toHexString(),"Z",new o(0,0,2.2),1.2);return l.position.z=1.5,l.position.y=0,l.rotation.x=Math.PI/2,{xNode:i,yNode:s,zNode:l,xPlane:a,yPlane:r,zPlane:m,xPlane2:n,yPlane2:h,zPlane2:c}}mainToMini(){this.removeMainCameraListener(),this._mainCameraObserver=this._mainCamera.onViewMatrixChangedObservable.add((()=>{this._miniCamera.alpha=this._mainCamera.alpha,this._miniCamera.beta=this._mainCamera.beta}))}miniToMain(){this.removeMiniCameraListener(),this._miniCameraObserver=this._miniCamera.onViewMatrixChangedObservable.add((()=>{this._mainCamera.alpha=this._miniCamera.alpha,this._mainCamera.beta=this._miniCamera.beta}))}removeMainCameraListener(){this._mainCameraObserver&&this._mainCamera.onViewMatrixChangedObservable&&(this._mainCamera.onViewMatrixChangedObservable.remove(this._mainCameraObserver),this._mainCameraObserver=null)}removeMiniCameraListener(){this._miniCameraObserver&&this._miniCamera.onViewMatrixChangedObservable&&(this._miniCamera.onViewMatrixChangedObservable.remove(this._miniCameraObserver),this._miniCameraObserver=null)}miniInteraction(e,i){this._clickHandler=e=>{const a=i.pick(e.offsetX,e.offsetY);if(a.hit){const e=a.pickedMesh,i=this._mainCamera.position,t=this._mainCamera.target,n=o.Distance(i,t);switch(e){case this.needClickMeshs.xPlane:this._mainCamera.setPosition(new o(t.x+n,t.y,t.z)),this._mainCamera.setTarget(t);break;case this.needClickMeshs.yPlane:this._mainCamera.setPosition(new o(t.x,t.y+n,t.z)),this._mainCamera.setTarget(t);break;case this.needClickMeshs.zPlane:this._mainCamera.setPosition(new o(t.x,t.y,t.z+n)),this._mainCamera.setTarget(t);break;case this.needClickMeshs.xPlane2:this._mainCamera.setPosition(new o(t.x-n,t.y,t.z)),this._mainCamera.setTarget(t);break;case this.needClickMeshs.yPlane2:this._mainCamera.setPosition(new o(t.x,t.y-n,t.z)),this._mainCamera.setTarget(t);break;case this.needClickMeshs.zPlane2:this._mainCamera.setPosition(new o(t.x,t.y,t.z-n)),this._mainCamera.setTarget(t)}}},e.addEventListener("click",this._clickHandler)}setCanvasPosition(e,i){this._canvas.style.left=`${e}px`,this._canvas.style.top=`${i}px`}setCanvasSize(e,i){this._canvas.style.width=`${e}px`,this._canvas.style.height=`${i}px`,this.onResize(),this._clickHandler&&this._canvas.removeEventListener("click",this._clickHandler),this.miniInteraction(this._canvas,this._scene)}setBackgroundColor(e){const i=(e=>{let i=null;if(/^rgb/.test(e)){const a=e.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);i=t.FromInts(parseInt(a[1]),parseInt(a[2]),parseInt(a[3]))}else if(/^#/.test(e))i=t.FromHexString(e);else if(/^hsl/.test(e)){const a=/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/,n=e.match(a);i=((e,i,a)=>{i/=100,a/=100;const n=(1-Math.abs(2*a-1))*i,s=n*(1-Math.abs(e/60%2-1)),r=a-n/2;let h,o,l;return e>=0&&e<60?(h=n,o=s,l=0):e>=60&&e<120?(h=s,o=n,l=0):e>=120&&e<180?(h=0,o=n,l=s):e>=180&&e<240?(h=0,o=s,l=n):e>=240&&e<300?(h=s,o=0,l=n):(h=n,o=0,l=s),h+=r,o+=r,l+=r,new t(h,o,l)})(parseInt(n[1]),parseInt(n[2]),parseInt(n[3]))}return i})(e);i&&(this._scene.clearColor=new c(i.r,i.g,i.b,1))}changeCamera(e){this.removeMainCameraListener(),this.removeMiniCameraListener(),this._mainCamera=e,this.mainToMini(),this.miniToMain(),this._miniCamera.alpha=e.alpha,this._miniCamera.beta=e.beta}onResize(){this._engine.resize()}renderer(){this._engine.runRenderLoop((()=>{this._scene.render()}))}dispose(){this.removeMainCameraListener(),this.removeMiniCameraListener(),this._clickHandler&&(this._canvas.removeEventListener("click",this._clickHandler),this._clickHandler=null),this._engine.dispose(),this._scene.dispose(),this._canvas.remove(),this._miniCamera.dispose()}}export{d as ViewportGizmo};
//# sourceMappingURL=bundle.esm.js.map