-
Notifications
You must be signed in to change notification settings - Fork 21
/
three-story-controls.min.js
2 lines (2 loc) · 37.1 KB
/
three-story-controls.min.js
1
2
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("three"),require("gsap")):"function"==typeof define&&define.amd?define(["exports","three","gsap"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ThreeStoryControls={},t.THREE,t.gsap)}(this,(function(t,e,i){"use strict";function s(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n,a,o,r=s(i);class h{constructor(t){this.epsilon=.001,this.values={},this.targetValues={},this.deltaValues={},Object.assign(this.values,t.values),Object.assign(this.targetValues,t.values),this.deltaValues={};for(const t in this.values)this.deltaValues[t]=0;this.dampingFactor=t.dampingFactor,t.epsilon&&(this.epsilon=t.epsilon),this.hasReached=!0}update(){const t={};let e=!0;for(const i in this.values)t[i]=this.targetValues[i]-this.values[i],e=e&&Math.abs(t[i])<this.epsilon;if(e){for(const e in this.values)this.deltaValues[e]=t[e],this.values[e]=this.targetValues[e];this.hasReached=!0}else for(const e in this.values)this.deltaValues[e]=this.dampingFactor*t[e],this.values[e]+=this.deltaValues[e]}setTarget(t){for(const e in t)this.targetValues[e]=t[e];this.hasReached=!1}addToTarget(t,e){this.targetValues[t]+=e,this.hasReached=!1}resetAll(t){for(const e in this.values)this.targetValues[e]=t,this.values[e]=t,this.deltaValues[e]=0;this.hasReached=!0}resetData(t){for(const e in t)this.targetValues[e]=t[e],this.values[e]=t[e],this.deltaValues[e]=0;this.hasReached=!0}getCurrentValues(){return Object.assign({},this.values)}getDeltaValues(){return Object.assign({},this.deltaValues)}reachedTarget(){return this.hasReached}}t.CameraAction=void 0,(n=t.CameraAction||(t.CameraAction={})).Pan="Pan",n.Tilt="Tilt",n.Roll="Roll",n.Truck="Truck",n.Pedestal="Pedestal",n.Dolly="Dolly",n.Zoom="Zoom",t.RigComponent=void 0,(a=t.RigComponent||(t.RigComponent={})).Body="body",a.Head="head",a.Eyes="eyes",t.Axis=void 0,(o=t.Axis||(t.Axis={})).X="x",o.Y="y",o.Z="z";const d={[t.Axis.X]:new e.Vector3(1,0,0),[t.Axis.Y]:new e.Vector3(0,1,0),[t.Axis.Z]:new e.Vector3(0,0,1)},c={[t.Axis.X]:{[t.CameraAction.Pan]:t.Axis.X,[t.CameraAction.Tilt]:t.Axis.Z,[t.CameraAction.Roll]:t.Axis.Y},[t.Axis.Y]:{[t.CameraAction.Pan]:t.Axis.Y,[t.CameraAction.Tilt]:t.Axis.X,[t.CameraAction.Roll]:t.Axis.Z},[t.Axis.Z]:{[t.CameraAction.Pan]:t.Axis.Z,[t.CameraAction.Tilt]:t.Axis.Y,[t.CameraAction.Roll]:t.Axis.X}};class l extends e.EventDispatcher{constructor(i,s){super(),this.inTransit=!1,this.upAxis=t.Axis.Y,this.actionAxes=c[this.upAxis],this.hasAnimation=!1,this.animationTranslationObjectName="Translation",this.animationRotationObjectName="Rotation",this.translateAlong={[t.CameraAction.Tilt]:!1,[t.CameraAction.Pan]:!0,[t.CameraAction.Roll]:!1},this.camera=i,this.scene=s,this.body=new e.Object3D,this.head=new e.Object3D,this.eyes=new e.Object3D,this.head.name=this.animationRotationObjectName,this.body.name=this.animationTranslationObjectName,this.body.rotation.order=this.getRotationOrder(),this.head.rotation.order=this.getRotationOrder(),this.eyes.rotation.order=this.getRotationOrder(),this.scene.add(this.body.add(this.head.add(this.eyes.add(this.camera)))),this.cameraIsInRig=!0,this.unpackTransform()}getAxisFor(t){return this.actionAxes[t]}getAxisVectorFor(t){return d[this.actionAxes[t]]}do(i,s,n){const a=this[n];switch(i){case t.CameraAction.Pan:case t.CameraAction.Tilt:case t.CameraAction.Roll:{const t=this.getAxisVectorFor(i);a?a.rotateOnAxis(t,s):this.translateAlong[i]?this.body.rotateOnAxis(t,s):this.eyes.rotateOnAxis(t,s);break}case t.CameraAction.Truck:{const e=this.getAxisVectorFor(t.CameraAction.Tilt);(a||this.body).translateOnAxis(e,s);break}case t.CameraAction.Pedestal:{const e=this.getAxisVectorFor(t.CameraAction.Pan);(a||this.body).translateOnAxis(e,s);break}case t.CameraAction.Dolly:{const e=this.getAxisVectorFor(t.CameraAction.Roll);(a||this.body).translateOnAxis(e,s);break}case t.CameraAction.Zoom:this.camera instanceof e.PerspectiveCamera&&(this.camera.fov=s,this.camera.updateProjectionMatrix())}}getWorldCoordinates(){const t=new e.Vector3;this.camera.getWorldPosition(t);const i=new e.Quaternion;return this.camera.getWorldQuaternion(i),{position:t,quaternion:i}}setWorldCoordinates({position:i,quaternion:s}){const n=(new e.Euler).setFromQuaternion(s,this.getRotationOrder()),a=[t.CameraAction.Pan,t.CameraAction.Tilt,t.CameraAction.Roll];this.eyes.position.set(0,0,0),this.eyes.rotation.set(0,0,0),this.head.position.set(0,0,0),this.head.rotation.set(0,0,0),this.body.position.copy(i),a.forEach((t=>{const e=this.getAxisFor(t);this.translateAlong[t]?this.body.rotation[e]=n[e]:this.eyes.rotation[e]=n[e]})),this.camera.rotation.set(0,0,0),this.camera.position.set(0,0,0)}packTransform(){const{position:t,quaternion:e}=this.getWorldCoordinates();this.body.position.copy(t),this.body.rotation.set(0,0,0),this.head.quaternion.copy(e),this.head.position.set(0,0,0),this.eyes.position.set(0,0,0),this.eyes.rotation.set(0,0,0)}unpackTransform(){const{position:t,quaternion:e}=this.getWorldCoordinates();this.setWorldCoordinates({position:t,quaternion:e})}disassemble(){this.cameraIsInRig&&(this.scene.attach(this.camera),this.cameraIsInRig=!1)}assemble(){this.cameraIsInRig||(this.eyes.attach(this.camera),this.unpackTransform(),this.cameraIsInRig=!0)}getRotationOrder(){return Object.values(this.actionAxes).join("").toUpperCase()}isInRig(){return this.cameraIsInRig}isMoving(){return this.inTransit}setUpAxis(t){this.upAxis=t,this.actionAxes=c[this.upAxis],this.body.rotation.order=this.getRotationOrder()}setAnimationClip(t,i,s){this.animationClip=t,i&&(this.animationTranslationObjectName=i),s&&(this.animationRotationObjectName=s),this.hasAnimation=!0,this.animationClip.duration+=.01,this.mixer=new e.AnimationMixer(this.body);const n=this.mixer.clipAction(this.animationClip);n.clampWhenFinished=!0,n.play()}flyTo(t,i,s=1,n="power1",a=!0){if(!this.isMoving()){const o=this.getWorldCoordinates(),h={px:o.position.x,py:o.position.y,pz:o.position.z,qx:o.quaternion.x,qy:o.quaternion.y,qz:o.quaternion.z,qw:o.quaternion.w,slerpAmt:0},d={px:t.x,py:t.y,pz:t.z,qx:i.x,qy:i.y,qz:i.z,qw:i.w,slerpAmt:1},c=new e.Quaternion,l=new e.Quaternion(h.qx,h.qy,h.qz,h.qw),p=()=>{this.inTransit=!0,this.packTransform(),this.dispatchEvent({type:"CameraMoveStart"})},m=t=>{this.body.position.set(h.px,h.py,h.pz),a?(c.slerpQuaternions(l,i,h.slerpAmt),this.head.setRotationFromQuaternion(c)):this.head.quaternion.set(h.qx,h.qy,h.qz,h.qw),this.dispatchEvent({type:"CameraMoveUpdate",progress:t.progress()})},u=()=>{this.inTransit=!1,this.unpackTransform(),this.dispatchEvent({type:"CameraMoveEnd"})};r.default.to(h,Object.assign(Object.assign({duration:s,ease:n},d),{onStart:p,onUpdate:function(){m(this)},onComplete:u}))}}flyToKeyframe(t,e=1,i="power1"){if(this.hasAnimation&&!this.isMoving()){const s={time:this.mixer.time},n={time:this.animationClip.tracks[0].times[t]},a=()=>{this.inTransit=!0,this.dispatchEvent({type:"CameraMoveStart"})},o=t=>{this.mixer.setTime(s.time),this.dispatchEvent({type:"CameraMoveUpdate",progress:t.progress()})},h=()=>{this.inTransit=!1,this.dispatchEvent({type:"CameraMoveEnd"})};r.default.to(s,Object.assign(Object.assign({duration:e,ease:i},n),{onStart:a,onUpdate:function(){o(this)},onComplete:h}))}}setAnimationPercentage(t){if(this.hasAnimation){const e=Math.max(0,Math.min(t*this.animationClip.duration,this.animationClip.duration-1e-4));this.mixer.setTime(e)}}setAnimationTime(t){this.hasAnimation&&this.mixer.setTime(t)}setAnimationKeyframe(t){this.hasAnimation&&this.mixer.setTime(this.animationClip.tracks[0].times[t])}}class p extends e.EventDispatcher{constructor(){super()}}const m={keyMapping:{forward:["ArrowUp","w","W"],backward:["ArrowDown","s","S"],left:["ArrowLeft","a","A"],right:["ArrowRight","d","D"],up:["u","U"],down:["n","N"]},dampingFactor:.5,incrementor:1,preventBubbling:!0};class u extends p{constructor(t){super(),Object.assign(this,m,t);const e={};for(const t in this.keyMapping)e[t]=0;this.damper=new h({values:e,dampingFactor:this.dampingFactor}),this.onKeyUp=this.onKeyUp.bind(this),this.onKeyDown=this.onKeyDown.bind(this)}connect(){document.addEventListener("keyup",this.onKeyUp,!0),document.addEventListener("keydown",this.onKeyDown,!0),this.connected=!0}disconnect(){document.removeEventListener("keyup",this.onKeyUp,!0),document.removeEventListener("keydown",this.onKeyDown,!0),this.connected=!1}update(){"continuous"!==this.type||this.damper.reachedTarget()||(this.damper.update(),this.dispatchEvent({type:"update",values:this.damper.getCurrentValues(),deltas:this.damper.getDeltaValues()}),this.damper.reachedTarget()&&(this.damper.resetAll(0),this.dispatchEvent({type:"inertiacomplete"})))}isEnabled(){return this.connected}onKeyUp(t){if("discrete"===this.type)for(const e in this.keyMapping)if(this.keyMapping[e].includes(t.key)){this.preventBubbling&&t.preventDefault(),this.dispatchEvent({type:"trigger",trigger:e});break}}onKeyDown(t){if("continuous"===this.type)for(const e in this.keyMapping)if(this.keyMapping[e].includes(t.key)){this.preventBubbling&&t.preventDefault(),this.damper.addToTarget(e,this.incrementor);break}}}const g={domElement:document.body,dampingFactor:.5,shouldNormalize:!0,normalizeAroundZero:!0,multipointerThreshold:100};class b extends p{constructor(t){super(),this.domElement=document.body,this.shouldNormalize=!0,this.normalizeAroundZero=!0,this.pointerCount=0,this.recordedPosition=!1,this.cache=[],this.lastDownTime=0,this.lastUpTime=0,Object.assign(this,g,t),this.damper=new h({values:{x:null,y:null},dampingFactor:this.dampingFactor}),this.setDimensions(),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.onPointerDown=this.onPointerDown.bind(this),this.onResize=this.onResize.bind(this)}connect(){this.domElement.addEventListener("pointermove",this.onPointerMove,{passive:!0}),this.domElement.addEventListener("pointerdown",this.onPointerDown,{passive:!0}),this.domElement.addEventListener("pointerleave",this.onPointerUp,{passive:!0}),this.domElement.addEventListener("pointerup",this.onPointerUp,{passive:!0}),window.addEventListener("resize",this.onResize),this.connected=!0}disconnect(){this.domElement.removeEventListener("pointermove",this.onPointerMove),this.domElement.removeEventListener("pointerdown",this.onPointerDown),this.domElement.removeEventListener("pointerleave",this.onPointerUp),this.domElement.removeEventListener("pointerup",this.onPointerUp),this.connected=!1}update(t){this.pointerCount!==this.cache.length&&t-this.lastDownTime>this.multipointerThreshold&&t-this.lastUpTime>this.multipointerThreshold&&(this.pointerCount=this.cache.length,0===this.pointerCount?(this.damper.resetAll(null),this.recordedPosition=!1):(this.damper.resetData(this.getPointerPosition(this.cache[0])),this.recordedPosition=!0)),this.damper.reachedTarget()||(this.damper.update(),this.dispatchEvent({type:"update",values:this.shouldNormalize?this.normalize(this.damper.getCurrentValues(),this.normalizeAroundZero):this.damper.getCurrentValues(),deltas:this.shouldNormalize?this.normalize(this.damper.getDeltaValues(),!1):this.damper.getDeltaValues(),pointerCount:this.pointerCount}),this.damper.reachedTarget()&&this.dispatchEvent({type:"inertiacomplete"}))}isEnabled(){return this.connected}setDimensions(){this.width=this.domElement.getBoundingClientRect().width,this.height=this.domElement.getBoundingClientRect().height}getPointerPosition(t){return{x:Math.max(0,Math.min(this.width,t.x-this.domElement.offsetLeft)),y:Math.max(0,Math.min(this.height,t.y-this.domElement.offsetTop))}}normalize(t,e){let i=t.x/this.width,s=t.y/this.height;return e&&(i=2*i-1,s=2*s-1),{x:i,y:s}}onPointerMove(t){this.pointerCount===this.cache.length&&(0===this.cache.length?this.recordedPosition?this.damper.setTarget(this.getPointerPosition(t)):(this.damper.resetData(this.getPointerPosition(t)),this.recordedPosition=!0):t.pointerId===this.cache[0].pointerId&&this.damper.setTarget(this.getPointerPosition(t)))}onPointerDown(t){0===t.button&&(this.cache.push(t),this.lastDownTime=window.performance.now())}onPointerUp(t){if(0===t.button||"pointerleave"===t.type){for(let e=0;e<this.cache.length;e++)if(this.cache[e].pointerId==t.pointerId){this.cache.splice(e,1);break}this.lastUpTime=window.performance.now()}}onResize(){this.setDimensions()}}const y={startOffset:"0px",endOffset:"0px",buffer:.1,dampingFactor:.5};class f extends p{constructor(t){super(),Object.assign(this,y,t),this.lastSeenScrollValue=window.scrollY||-1,this.previousScrollValue=this.lastSeenScrollValue,this.values={scrollPx:null,scrollPercent:null},this.damper=new h({values:this.values,dampingFactor:this.dampingFactor}),this.calculateDimensions=this.calculateDimensions.bind(this),this.onScroll=this.onScroll.bind(this),this.resizeObserver=new ResizeObserver(this.calculateDimensions),this.calculateDimensions()}connect(){window.addEventListener("scroll",this.onScroll,{passive:!0}),this.resizeObserver.observe(document.body),this.connected=!0}disconnect(){window.removeEventListener("scroll",this.onScroll),this.resizeObserver.unobserve(document.body),this.connected=!1}update(){if(this.lastSeenScrollValue!==this.previousScrollValue&&this.lastSeenScrollValue>=this.bufferedStartPosition&&this.lastSeenScrollValue<=this.bufferedEndPosition){const t=Math.max(0,Math.min(this.distance,this.lastSeenScrollValue-this.startPosition)),e=Math.max(0,Math.min(1,t/this.distance));this.values={scrollPx:t,scrollPercent:e},this.damper.setTarget(this.values),this.previousScrollValue=this.lastSeenScrollValue}this.damper.reachedTarget()||(this.damper.update(),this.dispatchEvent({type:"update",values:this.values,dampenedValues:this.damper.getCurrentValues()}),this.damper.reachedTarget()&&this.dispatchEvent({type:"inertiacomplete"}))}isEnabled(){return this.connected}parseOffset(t){let e=0;return t&&(e=parseInt(t),-1!==t.indexOf("vh")?e=e*window.innerHeight/100:this.distance&&-1!==t.indexOf("%")&&(e=e*this.distance/100)),e}calculateOffset(t){return t?this.calculateOffset(t.offsetParent)+t.offsetTop:0}calculateDimensions(){const t=this.scrollElement.clientHeight,e=this.calculateOffset(this.scrollElement);this.startPosition=e-window.innerHeight+this.parseOffset(this.startOffset),this.endPosition=e+t+this.parseOffset(this.endOffset),this.distance=this.endPosition-this.startPosition,this.bufferedStartPosition=Math.max(0,this.startPosition*(1-this.buffer)),this.bufferedEndPosition=Math.min(this.endPosition*(1+this.buffer),document.body.getBoundingClientRect().height)}onScroll(){this.lastSeenScrollValue=window.scrollY}}const x={domElement:document.body,thresholdX:60,thresholdY:60};class v extends p{constructor(t={}){super(),Object.assign(this,x,t),this.onPointerUp=this.onPointerUp.bind(this),this.onPointerDown=this.onPointerDown.bind(this)}connect(){this.domElement.addEventListener("pointerdown",this.onPointerDown,{passive:!0}),this.domElement.addEventListener("pointerup",this.onPointerUp,{passive:!0}),this.connected=!0}disconnect(){this.domElement.removeEventListener("pointerdown",this.onPointerDown),this.domElement.removeEventListener("pointerup",this.onPointerUp),this.connected=!1}update(){}isEnabled(){return this.connected}onPointerDown(t){"mouse"!==t.pointerType&&t.isPrimary&&(this.startX=t.screenX,this.startY=t.screenY)}onPointerUp(t){if("mouse"!==t.pointerType&&t.isPrimary){const e=t.screenX-this.startX,i=t.screenY-this.startY;(Math.abs(e)>=this.thresholdX||Math.abs(i)>=this.thresholdY)&&this.dispatchEvent({type:"trigger",x:Math.abs(e)>=this.thresholdX?Math.sign(e):0,y:Math.abs(i)>=this.thresholdY?Math.sign(-1*i):0})}}}const E={dampingFactor:.5,thresholdX:15,thresholdY:15,debounceDuration:700};class A extends p{constructor(t){super(),this.lastThresholdTrigger=0,Object.assign(this,E,t),this.damper=new h({values:{x:0,y:0},dampingFactor:this.dampingFactor}),this.onWheel=this.onWheel.bind(this)}connect(){(this.domElement||window).addEventListener("wheel",this.onWheel,{passive:!0}),this.connected=!0}disconnect(){(this.domElement||window).removeEventListener("wheel",this.onWheel),this.connected=!1}update(){"continuous"!==this.type||this.damper.reachedTarget()||(this.damper.update(),this.dispatchEvent({type:"update",values:this.damper.getCurrentValues(),deltas:this.damper.getDeltaValues()}),this.damper.reachedTarget()&&(this.damper.resetAll(0),this.dispatchEvent({type:"inertiacomplete"})))}isEnabled(){return this.connected}onWheel(t){if("continuous"===this.type)this.damper.addToTarget("x",t.deltaX),this.damper.addToTarget("y",t.deltaY);else if("discrete"===this.type&&(Math.abs(t.deltaX)>=this.thresholdX||Math.abs(t.deltaY)>=this.thresholdY)){const e=window.performance.now();e-this.lastThresholdTrigger>this.debounceDuration&&(this.lastThresholdTrigger=e,this.dispatchEvent({type:"trigger",x:Math.abs(t.deltaX)>=this.thresholdX?Math.sign(t.deltaX):0,y:Math.abs(t.deltaY)>=this.thresholdY?Math.sign(t.deltaY):0}))}}}const w={domElement:document.body,pointerDampFactor:.3,pointerScaleFactor:4,keyboardDampFactor:.5,keyboardScaleFactor:.5,wheelDampFactor:.25,wheelScaleFactor:.05,panDegreeFactor:Math.PI/4,tiltDegreeFactor:Math.PI/10};const C={startOffset:"0px",endOffset:"0px",dampingFactor:1,buffer:.1,cameraStart:"0%",cameraEnd:"100%",scrollActions:[]},P=(t,e,i,s,n)=>Math.max(s,Math.min(n,(n-s)/(i-e)*(t-e)+s));const T={cycle:!1,useKeyboard:!0};class S extends e.EventDispatcher{constructor(t,e=[],i={}){super(),this.currentIndex=null,this.upcomingIndex=null,this.enabled=!1,this.cameraRig=t,this.pois=e,Object.assign(this,T,i),this.useKeyboard&&(this.keyboardAdaptor=new u({type:"discrete",keyMapping:{next:["ArrowDown","ArrowRight"],prev:["ArrowUp","ArrowLeft"]}}),this.onKey=this.onKey.bind(this)),this.onCameraStart=this.onCameraStart.bind(this),this.onCameraUpdate=this.onCameraUpdate.bind(this),this.onCameraEnd=this.onCameraEnd.bind(this)}getCurrentIndex(){return this.currentIndex}nextPOI(){const t=this.currentIndex+1;t>=this.pois.length&&!this.cycle?this.dispatchEvent({type:"ExitPOIs",exitFrom:"end"}):this.goToPOI(t%this.pois.length)}prevPOI(){const t=this.currentIndex-1;t<0&&!this.cycle?this.dispatchEvent({type:"ExitPOIs",exitFrom:"start"}):this.goToPOI((t+this.pois.length)%this.pois.length)}goToPOI(t){this.upcomingIndex=t;const e=this.pois[this.upcomingIndex];this.cameraRig.flyTo(e.position,e.quaternion,e.duration,e.ease,e.useSlerp)}enable(){this.useKeyboard&&(this.keyboardAdaptor.connect(),this.keyboardAdaptor.addEventListener("trigger",this.onKey)),this.cameraRig.addEventListener("CameraMoveStart",this.onCameraStart),this.cameraRig.addEventListener("CameraMoveUpdate",this.onCameraUpdate),this.cameraRig.addEventListener("CameraMoveEnd",this.onCameraEnd),this.enabled=!0}disable(){this.useKeyboard&&(this.keyboardAdaptor.disconnect(),this.keyboardAdaptor.removeEventListener("trigger",this.onKey)),this.cameraRig.removeEventListener("CameraMoveStart",this.onCameraStart),this.cameraRig.removeEventListener("CameraMoveUpdate",this.onCameraUpdate),this.cameraRig.removeEventListener("CameraMoveEnd",this.onCameraEnd),this.enabled=!1}update(){}isEnabled(){return this.enabled}updatePois(t){this.dispatchEvent({type:"update",currentIndex:this.currentIndex,upcomingIndex:this.upcomingIndex,progress:t})}onCameraStart(){this.updatePois(0)}onCameraUpdate(t){this.updatePois(t.progress)}onCameraEnd(){this.currentIndex=this.upcomingIndex,this.upcomingIndex=null}onKey(t){"next"===t.trigger?this.nextPOI():"prev"===t.trigger&&this.prevPOI()}}const L={wheelThreshold:15,swipeThreshold:60,duration:1,ease:"power1",useKeyboard:!0};class I extends e.EventDispatcher{constructor(t,e=[],i={}){super(),this.currentIndex=0,this.upcomingIndex=null,this.enabled=!1,this.cameraRig=t,this.pois=e,Object.assign(this,L,i),this.wheelAdaptor=new A({type:"discrete",thresholdY:this.wheelThreshold}),this.swipeAdaptor=new v({thresholdY:this.swipeThreshold}),this.useKeyboard&&(this.keyboardAdaptor=new u({type:"discrete",keyMapping:{next:["ArrowDown","ArrowRight"],prev:["ArrowUp","ArrowLeft"]}}),this.onKey=this.onKey.bind(this)),this.onCameraStart=this.onCameraStart.bind(this),this.onCameraUpdate=this.onCameraUpdate.bind(this),this.onCameraEnd=this.onCameraEnd.bind(this),this.onTrigger=this.onTrigger.bind(this)}getCurrentIndex(){return this.currentIndex}enable(){this.useKeyboard&&(this.keyboardAdaptor.addEventListener("trigger",this.onKey),this.keyboardAdaptor.connect()),this.wheelAdaptor.addEventListener("trigger",this.onTrigger),this.swipeAdaptor.addEventListener("trigger",this.onTrigger),this.cameraRig.addEventListener("CameraMoveStart",this.onCameraStart),this.cameraRig.addEventListener("CameraMoveUpdate",this.onCameraUpdate),this.cameraRig.addEventListener("CameraMoveEnd",this.onCameraEnd),this.wheelAdaptor.connect(),this.swipeAdaptor.connect(),this.enabled=!0}disable(){this.useKeyboard&&(this.keyboardAdaptor.removeEventListener("trigger",this.onKey),this.keyboardAdaptor.disconnect()),this.wheelAdaptor.removeEventListener("trigger",this.onTrigger),this.swipeAdaptor.removeEventListener("trigger",this.onTrigger),this.cameraRig.removeEventListener("CameraMoveStart",this.onCameraStart),this.cameraRig.removeEventListener("CameraMoveUpdate",this.onCameraUpdate),this.cameraRig.removeEventListener("CameraMoveEnd",this.onCameraEnd),this.wheelAdaptor.disconnect(),this.swipeAdaptor.disconnect(),this.enabled=!1}update(){}isEnabled(){return this.enabled}onKey(t){switch(t.trigger){case"prev":this.onTrigger({y:-1});break;case"next":this.onTrigger({y:1})}}onTrigger(t){const e=this.currentIndex+t.y;e>=this.pois.length?this.dispatchEvent({type:"ExitPOIs",exitFrom:"end"}):e<0?this.dispatchEvent({type:"ExitPOIs",exitFrom:"start"}):(this.upcomingIndex=e,this.cameraRig.flyToKeyframe(this.pois[this.upcomingIndex].frame,this.duration,this.ease))}updatePois(t){this.dispatchEvent({type:"update",currentIndex:this.currentIndex,upcomingIndex:this.upcomingIndex,progress:t})}onCameraStart(){this.updatePois(0)}onCameraUpdate(t){this.updatePois(t.progress)}onCameraEnd(){this.currentIndex=this.upcomingIndex,this.upcomingIndex=null}}const R={domElement:document.body,panFactor:Math.PI/20,tiltFactor:Math.PI/20,truckFactor:1,pedestalFactor:1,dampingFactor:.7};!function(t,e){void 0===e&&(e={});var i=e.insertAt;if(t&&"undefined"!=typeof document){var s=document.head||document.getElementsByTagName("head")[0],n=document.createElement("style");n.type="text/css","top"===i&&s.firstChild?s.insertBefore(n,s.firstChild):s.appendChild(n),n.styleSheet?n.styleSheet.cssText=t:n.appendChild(document.createTextNode(t))}}(".tb-ch {\n width: 350px;\n height: 100%;\n position: fixed;\n top: 0;\n left: 0;\n z-index: 99999;\n background-color: rgba(255, 255, 255, 0.8);\n box-sizing: border-box;\n overflow-x: visible;\n transition: all 0.2s ease-in-out;\n}\n .tb-ch.collapsed {\n left: -350px;\n }\n .tb-ch * {\n box-sizing: border-box;\n }\n .tb-ch button {\n text-transform: capitalize;\n cursor: pointer;\n }\n .tb-ch .btn-round {\n font-size: 1.8rem;\n line-height: 1;\n width: 2.5rem;\n height: 2.5rem;\n position: absolute;\n right: -3rem;\n bottom: 0.5rem;\n }\n .tb-ch .btn-round.collapse {\n bottom: 3.5rem;\n }\n .tb-ch .controls {\n position: absolute;\n bottom: 0;\n height: 225px;\n border-top: 1px solid black;\n padding: 0.5rem;\n width: 100%;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n }\n .tb-ch .btn-text {\n padding: 0.5rem;\n text-align: center;\n width: 100%;\n }\n .tb-ch input[type='range'] {\n width: 100%;\n }\n .tb-ch .pois {\n height: calc(100vh - 225px - 1rem);\n overflow: scroll;\n padding: 1rem 1rem 0;\n }\n .tb-ch .poi {\n margin-bottom: 1rem;\n }\n .tb-ch .poi h2 {\n font-size: 1rem;\n }\n .tb-ch .poi .wrapper {\n display: flex;\n flex-direction: row;\n }\n .tb-ch .poi img {\n display: block;\n max-width: 100%;\n min-width: 0;\n margin-right: 0.5rem;\n }\n .tb-ch .poi .poi-controls {\n display: flex;\n flex-direction: column;\n }\n .tb-ch .poi .poi-controls button {\n padding: 0.5rem;\n width: 2rem;\n height: 2rem;\n margin-bottom: 0.25rem;\n }\n .tb-ch .poi .poi-params {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n width: calc(100% - 2.5rem);\n }\n .tb-ch .poi label,\n .tb-ch .poi input,\n .tb-ch .poi select {\n width: 50%;\n font-size: 0.7rem;\n font-family: monospace;\n margin: 0.25rem 0;\n }\n .tb-ch .poi input {\n text-align: center;\n }\n");const O=["none","power1","power2","power3","power4","sine","expo","circ"],k="visit",F="remove",M="duration",D="ease",q="move-up",V="move-down";t.BaseAdaptor=p,t.CameraHelper=class{constructor(t,e,i,s){this.useSlerp=!0,this.rig=t,this.controls=e,this.canvas=i,this.pois=[],this.currentIndex=null,this.doCapture=!1,this.isPlaying=!1,this.initUI(s)}capture(){this.doCapture=!0}update(t){if(this.doCapture){const t=document.createElement("canvas"),e=t.getContext("2d");t.width=640,t.height=360,e.drawImage(this.canvas,0,0,t.width,t.height);const i=t.toDataURL();this.addPoi(i),this.doCapture=!1}if(this.isPlaying){this.playStartTime||(this.playStartTime=t,this.controls.disable(),this.rig.packTransform());const e=(t-this.playStartTime)/1e3;this.rig.setAnimationTime(e),e>this.animationClip.duration&&(this.isPlaying=!1,this.playStartTime=null,this.controls.enable(),this.rig.unpackTransform())}}addPoi(t){this.pois.push(Object.assign(Object.assign({},this.rig.getWorldCoordinates()),{duration:1,ease:"power1",image:t})),this.currentIndex=this.pois.length-1,this.createClip(),this.render()}updatePoi(t,e){this.pois[t]=Object.assign(Object.assign({},this.pois[t]),e)}movePoi(t,e){if(t+e>=0&&t+e<this.pois.length){const i=this.pois[t];this.pois[t]=this.pois[t+e],this.pois[t+e]=i,this.render()}}removePoi(t){this.pois.splice(t,1),this.render()}goToPoi(t){const e=this.pois[t];this.rig.flyTo(e.position,e.quaternion,e.duration,e.ease,this.useSlerp)}createClip(){if(this.pois.length>0){const t=[],i=[],s=[],n=new e.Vector3,a=new e.Quaternion,o=10;let h=0;if(!this.pois[0].quaternion.isQuaternion&&!this.pois[0].position.isVector3)for(let t=0;t<this.pois.length;t++){const i=this.pois[t];i.quaternion=new e.Quaternion(i.quaternion[0],i.quaternion[1],i.quaternion[2],i.quaternion[3]),i.position=new e.Vector3(i.position[0],i.position[1],i.position[2])}for(let e=0;e<this.pois.length-1;e++){const d=this.pois[e],c=this.pois[e+1],l={px:d.position.x,py:d.position.y,pz:d.position.z,qx:d.quaternion.x,qy:d.quaternion.y,qz:d.quaternion.z,qw:d.quaternion.w,slerpAmount:0},p={px:c.position.x,py:c.position.y,pz:c.position.z,qx:c.quaternion.x,qy:c.quaternion.y,qz:c.quaternion.z,qw:c.quaternion.w,slerpAmount:1,duration:c.duration,ease:c.ease},m=r.default.to(l,p);for(let e=0;e<o;e++){const r=c.duration*(e/o);t.push(h+r),m.seek(r),this.useSlerp?a.slerpQuaternions(d.quaternion,c.quaternion,l.slerpAmount):a.set(l.qx,l.qy,l.qz,l.qw),n.set(l.px,l.py,l.pz),a.toArray(s,s.length),n.toArray(i,i.length)}h+=c.duration}const d=this.pois[this.pois.length-1];d.quaternion.toArray(s,s.length),d.position.toArray(i,i.length),t.push(h),this.animationClip=new e.AnimationClip(null,h,[new e.VectorKeyframeTrack("Translation.position",t,i),new e.QuaternionKeyframeTrack("Rotation.quaternion",t,s)]),this.rig.setAnimationClip(this.animationClip)}}scrubClip(t){this.pois.length>0&&this.rig.setAnimationPercentage(t)}playClip(){this.pois.length>0&&(this.isPlaying=!0)}import(){if(this.fileInput){this.fileInput.click();const t=new FileReader;this.fileInput.onchange=()=>{t.readAsText(this.fileInput.files[0]),t.onload=t=>{const e=JSON.parse(t.target.result);this.pois=e.pois,this.animationClip=e.animationClip,this.createClip(),this.render()}}}}export({draft:t}){if(this.pois.length>0){const i={};i.pois=this.pois.map((e=>{const i={position:[e.position.x,e.position.y,e.position.z],quaternion:[e.quaternion.x,e.quaternion.y,e.quaternion.z,e.quaternion.w],duration:e.duration,ease:e.ease};return t&&(i.image=e.image),i})),this.animationClip&&(i.animationClip=e.AnimationClip.toJSON(this.animationClip));const s="text/json;charset=utf-8,"+encodeURIComponent(JSON.stringify(i)),n=document.createElement("a");n.href="data:"+s,n.download=`camera-data${t?"-draft":""}.json`,document.body.appendChild(n),n.click(),n.remove()}}exportImages(){const t=document.createElement("a");document.body.appendChild(t),this.pois.forEach(((e,i)=>{t.href=e.image,t.download=`camera-poi-${i}.png`,t.click()})),t.remove()}initUI(t){this.drawer=document.createElement("div"),this.drawer.classList.add("tb-ch");const e=document.createElement("button");e.classList.add("btn-round","add"),e.innerText="+",e.onclick=this.capture.bind(this),this.collapseBtn=document.createElement("button"),this.collapseBtn.classList.add("btn-round","collapse"),this.collapseBtn.innerText="<",this.collapseBtn.onclick=this.collapse.bind(this);const i=document.createElement("div");i.classList.add("controls"),this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.id="import",this.fileInput.accept="application/json",this.fileInput.style.display="none",this.btnImport=document.createElement("button"),this.btnImport.classList.add("btn-text","import"),this.btnImport.innerText="import draft JSON",this.btnImport.onclick=this.import.bind(this);const s=document.createElement("button");s.classList.add("btn-text","export"),s.innerText="export draft JSON",s.onclick=this.export.bind(this,{draft:!0});const n=document.createElement("button");n.classList.add("btn-text","export"),n.innerText="export production JSON",n.onclick=this.export.bind(this,{draft:!1});const a=document.createElement("button");a.classList.add("btn-text","export-images"),a.innerHTML="export images",a.onclick=this.exportImages.bind(this);const o=document.createElement("button");o.classList.add("btn-text","play"),o.innerText="play",o.onclick=this.playClip.bind(this);const r=document.createElement("input");r.type="range",r.min="0",r.max="1000",r.step="0.1",r.value="0";const h=this.scrubClip.bind(this);r.onmousedown=()=>this.rig.packTransform(),r.onmouseup=()=>this.rig.unpackTransform(),r.oninput=t=>h(parseInt(t.target.value)/1e3),this.domList=document.createElement("div"),this.domList.classList.add("pois"),this.domList.onclick=this.handleEvents.bind(this),this.domList.onchange=this.handleEvents.bind(this),i.append(this.fileInput,this.btnImport,o,r,a,s,n),this.drawer.append(e,this.collapseBtn,this.domList,i);(t||document.body).append(this.drawer)}handleEvents(t){const e=t.target.dataset.index;e&&(t.target.classList.contains(k)?this.goToPoi(parseInt(e)):t.target.classList.contains(F)?this.removePoi(parseInt(e)):t.target.classList.contains(M)?this.updatePoi(parseInt(e),{duration:parseFloat(t.target.value)}):t.target.classList.contains(D)?this.updatePoi(parseInt(e),{ease:t.target.value}):t.target.classList.contains(q)?this.movePoi(parseInt(e),-1):t.target.classList.contains(V)&&this.movePoi(parseInt(e),1),this.createClip())}collapse(){this.drawer.classList.contains("collapsed")?(this.drawer.classList.remove("collapsed"),this.collapseBtn.innerText="<"):(this.drawer.classList.add("collapsed"),this.collapseBtn.innerText=">")}render(){this.domList.innerHTML="",this.pois.forEach(((t,e)=>{const i=document.createElement("div");i.classList.add("poi");const s=document.createElement("h2");s.innerText=`${e+1}.`;const n=document.createElement("div");n.classList.add("wrapper");const a=document.createElement("div");a.classList.add("poi-controls");const o=document.createElement("div");o.classList.add("poi-params");const r=new Image;r.src=t.image;const h=document.createElement("label");h.innerText="Duration";const d=document.createElement("input");d.classList.add(M),d.dataset.index=`${e}`,d.type="number",d.value=String(t.duration);const c=document.createElement("label");c.innerText="Easing";const l=document.createElement("select");l.classList.add(D),l.dataset.index=`${e}`;const p=O.map((e=>{const i=document.createElement("option");return i.innerText=e,i.value=e,i.selected=e===t.ease,i}));l.append(...p);const m=document.createElement("button");m.classList.add(F),m.title="Remove",m.dataset.index=`${e}`,m.innerText="x";const u=document.createElement("button");u.classList.add(k),u.title="Visit",u.dataset.index=`${e}`,u.innerHTML="→";const g=document.createElement("button");g.classList.add(q),g.title="Move up",g.dataset.index=`${e}`,g.innerHTML="↑";const b=document.createElement("button");b.classList.add(V),b.title="Move down",b.dataset.index=`${e}`,b.innerHTML="↓",a.append(m,u,g,b),o.append(h,d,c,l),n.append(r,a),i.append(s,n,o),this.domList.appendChild(i)}))}},t.CameraRig=l,t.Damper=h,t.FreeMovementControls=class{constructor(t,e={}){this.enabled=!1,this.cameraRig=t,this.wheelScaleFactor=e.wheelScaleFactor||w.wheelScaleFactor,this.pointerScaleFactor=e.pointerScaleFactor||w.pointerScaleFactor,this.panDegreeFactor=e.panDegreeFactor||w.panDegreeFactor,this.tiltDegreeFactor=e.tiltDegreeFactor||w.tiltDegreeFactor,this.keyboardAdaptor=new u({type:"continuous",dampingFactor:e.keyboardDampFactor||w.keyboardDampFactor,incrementor:e.keyboardScaleFactor||w.keyboardScaleFactor}),this.wheelAdaptor=new A({type:"continuous",dampingFactor:e.wheelDampFactor||w.wheelDampFactor,domElement:e.domElement||w.domElement}),this.pointerAdaptor=new b({domElement:e.domElement||w.domElement,dampingFactor:e.pointerDampFactor||w.pointerDampFactor}),this.onWheel=this.onWheel.bind(this),this.onKey=this.onKey.bind(this),this.onPointer=this.onPointer.bind(this)}isEnabled(){return this.enabled}enable(){this.wheelAdaptor.connect(),this.keyboardAdaptor.connect(),this.pointerAdaptor.connect(),this.wheelAdaptor.addEventListener("update",this.onWheel),this.keyboardAdaptor.addEventListener("update",this.onKey),this.pointerAdaptor.addEventListener("update",this.onPointer),this.enabled=!0}disable(){this.wheelAdaptor.disconnect(),this.keyboardAdaptor.disconnect(),this.pointerAdaptor.disconnect(),this.wheelAdaptor.removeEventListener("update",this.onWheel),this.keyboardAdaptor.removeEventListener("update",this.onKey),this.pointerAdaptor.removeEventListener("update",this.onPointer),this.enabled=!1}onWheel(e){this.cameraRig.do(t.CameraAction.Dolly,e.deltas.y*this.wheelScaleFactor),this.cameraRig.do(t.CameraAction.Truck,e.deltas.x*this.wheelScaleFactor)}onKey(e){this.cameraRig.do(t.CameraAction.Dolly,e.values.backward-e.values.forward),this.cameraRig.do(t.CameraAction.Truck,e.values.right-e.values.left),this.cameraRig.do(t.CameraAction.Pedestal,e.values.up-e.values.down)}onPointer(e){switch(e.pointerCount){case 1:this.cameraRig.do(t.CameraAction.Pan,e.deltas.x*this.panDegreeFactor),this.cameraRig.do(t.CameraAction.Tilt,e.deltas.y*this.tiltDegreeFactor);break;case 2:this.cameraRig.do(t.CameraAction.Dolly,-e.deltas.y*this.pointerScaleFactor),this.cameraRig.do(t.CameraAction.Truck,-e.deltas.x*this.pointerScaleFactor)}}update(t){this.enabled&&(this.keyboardAdaptor.update(),this.wheelAdaptor.update(),this.pointerAdaptor.update(t))}},t.KeyboardAdaptor=u,t.PathPointsControls=I,t.PointerAdaptor=b,t.ScrollAdaptor=f,t.ScrollControls=class{constructor(t,e){this.enabled=!1,this.cameraRig=t,this.cameraRig.setAnimationTime(0),this.scrollAdaptor=new f({scrollElement:e.scrollElement,dampingFactor:e.dampingFactor||C.dampingFactor,startOffset:e.startOffset||C.startOffset,endOffset:e.endOffset||C.endOffset,buffer:e.buffer||C.buffer}),this.cameraStart=e.cameraStart||C.cameraStart,this.cameraEnd=e.cameraEnd||C.cameraEnd,this.scrollActions=e.scrollActions||C.scrollActions,this.buffer=e.buffer||C.buffer,this.calculateStops(),this.onScroll=this.onScroll.bind(this)}isEnabled(){return this.enabled}enable(){this.scrollAdaptor.connect(),this.scrollAdaptor.addEventListener("update",this.onScroll),this.enabled=!0}disable(){this.scrollAdaptor.disconnect(),this.scrollAdaptor.removeEventListener("update",this.onScroll),this.enabled=!1}update(){this.enabled&&this.scrollAdaptor.update()}calculateStops(){this.cameraStartPx=this.scrollAdaptor.parseOffset(this.cameraStart),this.cameraEndPx=this.scrollAdaptor.parseOffset(this.cameraEnd),this.cameraBufferedStartPx=this.cameraStartPx*(1-this.buffer),this.cameraBufferedEndPx=this.cameraEndPx*(1+this.buffer),this.scrollActions.forEach((t=>{t.startPx=this.scrollAdaptor.parseOffset(t.start),t.endPx=this.scrollAdaptor.parseOffset(t.end),t.bufferedStartPx=t.startPx*(1-this.buffer),t.bufferedEndPx=t.endPx*(1+this.buffer)}))}onScroll(t){const e=t.dampenedValues.scrollPx;e>=this.cameraBufferedStartPx&&e<=this.cameraBufferedEndPx&&this.cameraRig.setAnimationPercentage(P(e,this.cameraStartPx,this.cameraEndPx,0,1)),this.scrollActions.forEach((t=>{e>=t.bufferedStartPx&&e<=t.bufferedEndPx&&t.callback(P(e,t.startPx,t.endPx,0,1))}))}},t.StoryPointsControls=S,t.SwipeAdaptor=v,t.ThreeDOFControls=class{constructor(t,e={}){this.enabled=!1,this.cameraRig=t,Object.assign(this,R,e),this.pointerAdaptor=new b({domElement:e.domElement||R.domElement,dampingFactor:e.dampingFactor||R.dampingFactor}),this.onPointerMove=this.onPointerMove.bind(this)}isEnabled(){return this.enabled}enable(){this.pointerAdaptor.connect(),this.pointerAdaptor.addEventListener("update",this.onPointerMove),this.enabled=!0}disable(){this.pointerAdaptor.disconnect(),this.pointerAdaptor.removeEventListener("update",this.onPointerMove),this.enabled=!1}update(t){this.enabled&&this.pointerAdaptor.update(t)}onPointerMove(e){0===e.pointerCount&&(this.cameraRig.do(t.CameraAction.Pan,-e.deltas.x*this.panFactor,t.RigComponent.Eyes),this.cameraRig.do(t.CameraAction.Tilt,-e.deltas.y*this.tiltFactor,t.RigComponent.Eyes),this.cameraRig.do(t.CameraAction.Truck,e.deltas.x*this.truckFactor,t.RigComponent.Eyes),this.cameraRig.do(t.CameraAction.Pedestal,e.deltas.y*this.pedestalFactor,t.RigComponent.Eyes))}},t.WheelAdaptor=A,Object.defineProperty(t,"__esModule",{value:!0})}));
//# sourceMappingURL=three-story-controls.min.js.map