0xa89f3db4…071asent to0xecb92cc7…1463·#25,067,885·view on Etherscan
irection(),this._lastDirection=this.direction,this.arrowPhase+=i.arrowSpeed*this.direction}async _updateAudioDirection(){if(void 0===audioEngine)return;const e=audioEngine.hasAudio?audioEngine.hasAudio():audioEngine.isLoaded;!this._audioInitialized&&e&&(await audioEngine.initDirectionalPlayback(),this._audioInitialized=!0),audioEngine.isDirectionalEnabled()&&audioEngine.isPlaying&&audioEngine.setDirection(this.direction)}_updateVideoDirection(){if("undefined"==typeof layerManager)return;const e=layerManager.getLayers();for(const t of e)t.component&&"VideoLayer"===t.component.constructor.name&&this._setVideoDirection(t.component,this.direction)}_setVideoDirection(e,t){if(!e._video)return;const i=e._video.elt;if(!i)return;const a=Math.abs(e.params.playbackRate||1);if(t<0)try{i.playbackRate=-a}catch(e){i.playbackRate=0,this._stepVideoBackward(i)}else i.playbackRate=a}_stepVideoBackward(e){const t=Math.max(0,e.currentTime-1/30);e.currentTime=t}draw(e){const t=this.params;if(!t.showIndicator)return;const i=this.hexToRgb(t.indicatorColor),a=255*t.indicatorOpacity;switch(e.push(),t.indicatorStyle){case"arrows":this.drawArrows(e,i,a);break;case"gradient":this.drawGradient(e,i,a);break;case"line":this.drawCenterLine(e,i,a);break;case"minimal":this.drawMinimal(e,i,a)}e.pop()}drawArrows(e,t,i){const a=this.params,s=this.height/2,o=a.arrowSize,r=1.5*o;e.noFill(),e.strokeWeight(3),e.strokeCap(e.ROUND),e.strokeJoin(e.ROUND);for(let n=0;n<a.arrowCount;n++){const l=((this.arrowPhase+n/a.arrowCount)%1-.5)*r*a.arrowCount,h=i*(.3+.7*Math.abs(this.transitionProgress));if(this.direction>0){const i=.75*this.width+l;e.stroke(t.r,t.g,t.b,h),e.beginShape(),e.vertex(i-o/2,s-o/2),e.vertex(i+o/2,s),e.vertex(i-o/2,s+o/2),e.endShape()}else{const i=.25*this.width-l;e.stroke(t.r,t.g,t.b,h),e.beginShape(),e.vertex(i+o/2,s-o/2),e.vertex(i-o/2,s),e.vertex(i+o/2,s+o/2),e.endShape()}}}drawGradient(e,t,i){const a=100;for(let s=0;s<a;s++){const o=(1-s/a)*i*(this.direction<0?.8:.2);e.stroke(t.r,t.g,t.b,o),e.line(s,0,s,this.height)}for(let s=0;s<a;s++){const o=this.width-a+s,r=s/a*i*(this.direction>0?.8:.2);e.stroke(t.r,t.g,t.b,r),e.line(o,0,o,this.height)}}drawCenterLine(e,t,i){const a=this.params,s=this.width*a.splitPosition;e.stroke(t.r,t.g,t.b,.5*i),e.strokeWeight(2),e.line(s,0,s,this.height);const o=this.direction>0?s+30:s-30;e.noStroke(),e.fill(t.r,t.g,t.b,i),e.ellipse(o,this.height/2,10,10)}drawMinimal(e,t,i){const a=20,s=this.direction>0?this.width-20-a:20,o=20;e.noStroke(),e.fill(t.r,t.g,t.b,i),this.direction>0?e.triangle(s,o,s,40,s+a,30):e.triangle(s+a,o,s+a,40,s,30)}hexToRgb(e){const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?{r:parseInt(t[1],16),g:parseInt(t[2],16),b:parseInt(t[3],16)}:{r:255,g:255,b:255}}dispose(){delete window._playbackDirection,delete window._playbackProgress}}class TemporalTunnel extends BaseComponent{static category="geometric";static isAudioReactive=!0;static displayName="Temporal Tunnel";static description="POV flight through a curving spacetime tunnel — RGB-only with phase-shift";constructor(e,t,i={}){super(e,t,i),this._time=0,this._frame=0,this._rings=[],this._torpedoes=[],this._initRings(),this._cursorX=.5,this._cursorY=.5,this._cursorXSm=.5,this._cursorYSm=.5,this._cursorVel=0,this._lastMouseX=.5,this._lastMouseY=.5,this._mouseWasPressed=!1,this._lakeT=0,this._audio={amplitude:0,bass:0,mid:0,high:0,beat:!1,spectrum:null},this._beatPulse=0,this._keydownHandler=e=>{if(" "!==e.key&&"Space"!==e.code)return;const t=document.activeElement;t&&("INPUT"===t.tagName||"TEXTAREA"===t.tagName||"SELECT"===t.tagName||t.isContentEditable)||(e.preventDefault(),this._fireTorpedo(this._cursorX,this._cursorY))},"undefined"!=typeof document&&document.addEventListener("keydown",this._keydownHandler)}dispose(){this._keydownHandler&&"undefined"!=typeof document&&(document.removeEventListener("keydown",this._keydownHandler),this._keydownHandler=null)}getDefaultParams(){return{ringCount:60,segmentCount:48,tunnelRadius:1,focal:400,ringSpacing:1,maxDepth:50,baseSpeed:.6,cursorReverseHalf:!0,audioSpeedMult:1.5,minForwardMotion:.15,cursorFollowStrength:.7,cursorFollowLag:.08,horizonRange:.12,audioRingDeform:.5,ringWobbleAmount:.02,phaseSpeed:.005,phaseColorMode:"spatial",phaseDepthInfluence:.5,redColorPercent:100,greenColorPercent:100,blueColorPercent:100,enableLakeMode:!0,lakeThresholdSpeed:8e-4,lakeShellZ:1.7,lakeBasinSpread:1.6,showLakeMarker:!1,torpedoSpeed:1.2,torpedoSize:6,distortionDuration:800,distortionAmount:.35,enableChromaticAberration:!0,enableScanlineNoise:!0,artifactSensitivity:1,ringStrokeWeight:1.5,backgroundFade:.18,overallBrightness:1}}getParameters(){return[{name:"ringCount",type:"range",min:10,max:150,step:5,label:"Ring Count"},{name:"segmentCount",type:"range",min:8,max:96,step:4,label:"Ring Segments"},{name:"tunnelRadius",type:"range",min:.15,max:.8,step:.02,label:"Tunnel Radius"},{name:"focal",type:"range",min:100,max:600,step:10,label:"Focal Length"},{name:"ringSpacing",type:"range",min:.3,max:3,step:.1,label:"Ring Spacing"},{name:"maxDepth",type:"range",min:20,max:120,step:5,label:"Max Depth"},{name:"baseSpeed",type:"range",min:0,max:2,step:.05,label:"Base Travel Speed"},{name:"cursorReverseHalf",type:"boolean",label:"Reverse on Left Half"},{name:"minForwardMotion",type:"range",min:0,max:.5,step:.02,label:"Min Forward Motion (cursor center)"},{name:"audioSpeedMult",type:"range",min:0,max:4,step:.1,label:"Audio Speed Multiplier"},{name:"cursorFollowStrength",type:"range",min:0,max:1,step:.05,label:"Cursor Follow Strength"},{name:"cursorFollowLag",type:"range",min:.01,max:.4,step:.01,label:"Cursor Follow Lag"},{name:"horizonRange",type:"range",min:0,max:1,step:.02,label:"Horizon Range (% of canvas)"},{name:"audioRingDeform",type:"range",min:0,max:2,step:.05,label:"Audio Ring Deform"},{name:"ringWobbleAmount",type:"range",min:0,max:.15,step:.005,label:"Tunnel Wobble"},{name:"phaseSpeed",type:"range",min:0,max:.04,step:5e-4,label:"Phase Speed"},{name:"phaseColorMode",type:"select",label:"Phase Color Mode",options:[{value:"spatial",label:"Spatial Stripes (rings cycle by depth)"},{value:"temporal",label:"Temporal Alt (whole frame cycles)"},{value:"r",label:"Red Only"},{value:"g",label:"Green Only"},{value:"b",label:"Blue Only"}]},{name:"phaseDepthInfluence",type:"range",min:0,max:1.5,step:.05,label:"Phase Depth Influence"},{name:"redColorPercent",type:"range",min:0,max:100,step:1,label:"Red In-Color % (rest = gray)"},{name:"greenColorPercent",type:"range",min:0,max:100,step:1,label:"Green In-Color % (rest = gray)"},{name:"blueColorPercent",type:"range",min:0,max:100,step:1,label:"Blue In-Color % (rest = gray)"},{name:"enableLakeMode",type:"boolean",label:"Enable Lake-Time Threshold"},{name:"lakeThresholdSpeed",type:"range",min:1e-4,max:.005,step:1e-4,label:"Lake Trigger Speed"},{name:"lakeShellZ",type:"range",min:.5,max:40,step:.1,label:"Lake Basin Depth (smaller z = bigger rings)"},{name:"lakeBasinSpread",type:"range",min:0,max:15,step:.1,label:"Lake Basin Spread (depth band — bigger = wider nested ring band)"},{name:"showLakeMarker",type:"boolean",label:"Show Lake Marker (debug)"},{name:"torpedoSpeed",type:"range",min:.3,max:4,step:.1,label:"Torpedo Speed"},{name:"torpedoSize",type:"range",min:2,max:18,step:1,label:"Torpedo Size"},{name:"distortionDuration",type:"range",min:200,max:2400,step:100,label:"Distortion Duration (ms)"},{name:"distortionAmount",type:"range",min:.05,max:1,step:.05,label:"Distortion Amount"},{name:"enableChromaticAberration",type:"boolean",label:"Chromatic Aberration on Bass"},{name:"enableScanlineNoise",type:"boolean",label:"Scanline Noise on Treble"},{name:"artifactSensitivity",type:"range",min:0,max:2.5,step:.1,label:"Artifact Sensitivity"},{name:"ringStrokeWeight",type:"range",min:.5,max:6,step:.5,label:"Ring Stroke Weight"},{name:"backgroundFade",type:"range",min:0,max:.6,step:.02,label:"Background Fade (0=clear, higher=trails)"},{name:"overallBrightness",type:"range",min:.2,max:2,step:.05,label:"Overall Brightness"}]}_initRings(){this._rings=[];const e=this.params.ringCount,t=this.params.ringSpacing;for(let i=0;i<e;i++)this._rings.push({z:1+i*t,baseRadius:this.params.tunnelRadius,wobblePhase:Math.random()*Math.PI*2,wobbleFreq:.5+1.2*Math.random(),distortStartMs:-1,distortAmount:0})}onParameterChange(e,t){"ringCount"!==e&&"ringSpacing"!==e||this._initRings()}_channelColor(e,t){const i=this.params;let a;if("temporal"===i.phaseColorMode)a=this._time*i.phaseSpeed*60%1;else{if("r"===i.phaseColorMode)return this._channelTuple(0,Math.floor(255*t));if("g"===i.phaseColorMode)return this._channelTuple(1,Math.floor(255*t));if("b"===i.phaseColorMode)return this._channelTuple(2,Math.floor(255*t));a=(.06*e*i.phaseDepthInfluence+this._time*i.phaseSpeed*60)%1}const s=3*a,o=Math.floor(s),r=s-o,n=Math.sin(r*Math.PI),l=Math.floor(255*t*(.6+.4*n));return this._channelTuple(o,l)}_channelTuple(e,t){const i=this.params,a=0===e?i.redColorPercent:1===e?i.greenColorPercent:i.blueColorPercent;return a<100&&100*Math.random()>=a?[t,t,t]:0===e?[t,0,0]:1===e?[0,t,0]:[0,0,t]}update(e,t){t=Math.min(t,100),this._time+=t/1e3,this._frame++;const i=t/1e3;if(e){this._audio.amplitude=e.amplitude||0,this._audio.bass=e.fftEnergy&&e.fftEnergy.bass||e.bass||0,this._audio.mid=e.fftEnergy&&e.fftEnergy.mid||e.mid||0,this._audio.high=e.fftEnergy&&e.fftEnergy.treble||e.high||0,this._audio.beat=!(!e.beatDetected&&!e.beat),this._audio.spectrum=e.fftSpectrum||null;const t=void 0!==e.mouseXNorm?e.mouseXNorm:.5,a=void 0!==e.mouseYNorm?e.mouseYNorm:.5,s=t-this._lastMouseX,o=a-this._lastMouseY,r=Math.sqrt(s*s+o*o)/Math.max(.001,i);this._cursorVel=.85*this._cursorVel+.15*r,this._cursorX=t,this._cursorY=a,this._lastMouseX=t,this._lastMouseY=a;const n=!!e.mousePressed;n&&!this._mouseWasPressed&&this._fireTorpedo(this._cursorX,this._cursorY),this._mouseWasPressed=n,this._audio.beat&&(this._beatPulse=1),this._beatPulse=Math.max(0,this._beatPulse-3*i)}const a=this.params.cursorFollowLag;if(this._cursorXSm+=(this._curso