From 296a8f2b7d70bca33fc400f60f74d7e1b455bf96 Mon Sep 17 00:00:00 2001 From: konekowo Date: Sun, 29 Sep 2024 21:46:31 +0000 Subject: [PATCH] deploy: 983f0b361d88ea7d78d227f899effbf52a3d26cc --- game.622e684f50f0951f444d.js | 2 ++ game.622e684f50f0951f444d.js.map | 1 + game.c52c91455b8f4b9329e2.js | 2 -- game.c52c91455b8f4b9329e2.js.map | 1 - index.html | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 game.622e684f50f0951f444d.js create mode 100644 game.622e684f50f0951f444d.js.map delete mode 100644 game.c52c91455b8f4b9329e2.js delete mode 100644 game.c52c91455b8f4b9329e2.js.map diff --git a/game.622e684f50f0951f444d.js b/game.622e684f50f0951f444d.js new file mode 100644 index 0000000..00993ca --- /dev/null +++ b/game.622e684f50f0951f444d.js @@ -0,0 +1,2 @@ +!function(){"use strict";var e,t={65918:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MapAudio=t.Audio=void 0;const n=i(20825),s=i(15041);class o{audio;source;mediaSource;mediaAudioElement;id;get isPaused(){return!!this._useMediaSource&&this.mediaAudioElement.paused}get isPlaying(){return!this._useMediaSource||!this.mediaAudioElement.paused}nodes=[];tempArrayMain=new Float32Array(256);tempArrayL=new Float32Array(64);tempArrayR=new Float32Array(64);LeftChannel=0;RightChannel=0;FrequencyAmplitudes=new Float32Array(256);_connectedToContext=!1;_useMediaSource=!1;_onEndCallback;timeStarted=0;paused=!1;beatmap;GetMaximumAudioLevel(){return Math.max(this.LeftChannel,this.RightChannel)}GetAverageAudioLevel(){return(this.LeftChannel+this.RightChannel)/2}Create(e,t){if(this._useMediaSource=t||!1,t){if(!this.mediaAudioElement)throw new Error("HTML Audio Element was not initialized!");this.mediaSource=e.createMediaElementSource(this.mediaAudioElement),this.mediaAudioElement.onpause=()=>{this.paused||this.mediaAudioElement.ended||this.Play()}}else this.source=e.createBufferSource(),this.source.buffer=this.audio}AddAudioNode(e){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");this.nodes.push(e)}GetNode(e){let t=this.nodes.filter((t=>t instanceof e));return t.length>0?t:null}ConnectToContext(e,t){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");this._connectedToContext||(this._connectedToContext=!0,this.nodes.length>0?t?t(this.nodes,this._useMediaSource?this.mediaSource:this.source):this.nodes.forEach(((t,i)=>{this.source.connect(t),t instanceof AnalyserNode||t.connect(e.destination)})):this._useMediaSource?this.mediaSource.connect(e.destination):this.source.connect(e.destination))}Play(){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(this.paused=!1,this._useMediaSource){this.mediaAudioElement.play();let e=this.beatmap.Events.Events.find((e=>{if(e.eventType==s.EventTypes.VIDEO)return e}));e&&e.texture&&e.texture.source.resource.startPromise&&e.texture.source.resource.startPromise.then((()=>{e.texture.source.resource.play()}))}else this.source.start()}Pause(){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(!this._useMediaSource)throw new Error("Pause is not supported on AudioSourceBuffer!");this.paused=!0,this.mediaAudioElement.pause();let e=this.beatmap.Events.Events.find((e=>{if(e.eventType==s.EventTypes.VIDEO)return e}));e&&e.texture&&e.texture.source.resource.startPromise&&e.texture.source.resource.startPromise.then((()=>{e.texture.source.resource.pause()}))}Stop(){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(this.paused=!0,this._useMediaSource){this.mediaAudioElement.pause(),this._onEndCallback&&this._onEndCallback();let e=this.beatmap.Events.Events.find((e=>{if(e.eventType==s.EventTypes.VIDEO)return e}));e&&e.texture&&e.texture.source.resource.startPromise&&e.texture.source.resource.startPromise.then((()=>{e.texture.source.resource.pause()}))}else this.source.stop()}SetTime(e){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(!this._useMediaSource)throw new Error("SetTime is not supported on AudioSourceBuffer!");this.mediaAudioElement.currentTime=e/1e3;let t=this.beatmap.Events.Events.find((e=>{if(e.eventType==s.EventTypes.VIDEO)return e}));t&&t.texture&&t.texture.source.resource.startPromise&&t.texture.source.resource.startPromise.then((()=>{let i=t.texture.source.resource,n=e/1e3;n+=t.startTime,n<0?(i.currentTime=0,i.pause(),t.texture.source.resource.startPromise=new Promise((e=>{setTimeout((()=>{i.play()}),Math.abs(n))}))):i.currentTime=n}))}GetDuration(){return this._useMediaSource?1e3*this.mediaAudioElement.duration:this.audio.duration}GetCurrentTime(){return this._useMediaSource?1e3*this.mediaAudioElement.currentTime:0!=this.timeStarted?Date.now()-this.timeStarted:0}RegisterEndCallBack(e){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");this._onEndCallback=e,this._useMediaSource?this.mediaAudioElement.onended=()=>{this.paused=!0,e()}:this.source.onended=()=>{this.isPaused||(this.paused=!0,e())}}}t.Audio=o;t.MapAudio=class extends o{fadingOut=!1;fadeOutTimeout;playingCallback;FadeOut(){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(!this._useMediaSource)throw new Error("FadeOut is not supported on AudioSourceBuffer!");if(this.fadingOut)return;this.fadingOut=!0,clearTimeout(this.fadeOutTimeout);let e=this.GetNode(GainNode);if(null==e)throw new Error("Gain Node doesn't exist on Audio Object!");e[0].gain.linearRampToValueAtTime(0,n.Main.AudioEngine.audioContext.currentTime+1),setTimeout((()=>{this.Stop()}),1e3)}}},85437:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.AudioEngine=void 0;const n=i(14981),s=i(65918),o=i(17898),a=i(20825),r=i(87816),l=i(22331);t.AudioEngine=class{audioContext;_playingAudios;_musicQueue=[];_audioIdTicker=0;_changeCallbacks=[];silentMusic=this.createSilentMusic();useSilentMusic=!0;constructor(){this.audioContext=new AudioContext,this._playingAudios=new n.PlayingAudios,a.Main.app.ticker.add((()=>{this.update()}))}UpdateMusicQueue(){this._musicQueue[0]&&(this._musicQueue[0].fadingOut||0!=this._musicQueue[0].GetCurrentTime()||(this._play(this._musicQueue[0]),this._changeCallbacks.forEach((e=>e(this._musicQueue[0])))),this._musicQueue[0].fadingOut&&this._musicQueue[1]&&this._musicQueue[1]&&(this._play(this._musicQueue[1]),this._changeCallbacks.forEach((e=>e(this._musicQueue[1]))))),this._musicQueue.length>=1?this.useSilentMusic=!1:(this.silentMusic=this.createSilentMusic(),this.useSilentMusic=!0)}createSilentMusic(){let e=new s.MapAudio;e.timeStarted=Date.now(),e.beatmap=new o.BeatmapData;let t=new r.UnInheritedTimingPoint;return t.time=0,t.beatLength=1e3,t.effects=l.Effect.None,e.beatmap.TimingPoints.TimingPoints.push(t),e}addMusicChangeEventListener(e){this._changeCallbacks.push(e)}removeMusicChangeEventListener(e){this._changeCallbacks=this._changeCallbacks.filter((t=>t!=e))}GetCurrentPlayingMusic(){return this.useSilentMusic?this.silentMusic:this._musicQueue[0]}GetCurrentPlayingMusicNoSilent(){return this._musicQueue[0]}PlayEffect(e,t){let i=new s.Audio;i.audio=e,i.id=this._audioIdTicker,this._play(i,t),this._audioIdTicker++}AddToMusicQueue(e,t,i){let n=new s.MapAudio;return n.mediaAudioElement=document.createElement("audio"),n.mediaAudioElement.src=e,n.beatmap=t,n.id=this._audioIdTicker,i&&(n.playingCallback=i),this._musicQueue.push(n),this._audioIdTicker++,this.UpdateMusicQueue(),n.id}PlayMusicImmediately(e,t,i){let n=this.GetCurrentPlayingMusicNoSilent();this._musicQueue=[],n&&n.FadeOut(),this.AddToMusicQueue(e,t,i)}update(){let e=this.GetCurrentPlayingMusic(),t=this.GetCurrentPlayingMusicNoSilent();if(t)if(t.isPaused)this.useSilentMusic=!0;else if(this.useSilentMusic&&(this.useSilentMusic=!1,e=this.GetCurrentPlayingMusic()),!this.useSilentMusic){e.fadingOut||e.GetDuration()-e.GetCurrentTime()<=1e3&&e.FadeOut();let t=e.GetNode(AnalyserNode)[0],i=e.GetNode(AnalyserNode)[1],n=e.GetNode(AnalyserNode)[2];t.getFloatFrequencyData(e.tempArrayMain);for(let t=0;t{s+=(e+1)/2})),e.tempArrayR.forEach((e=>{o+=(e+1)/2})),s/=e.tempArrayL.length,o/=e.tempArrayR.length,e.LeftChannel=s,e.RightChannel=o}}_play(e,t){if(e instanceof s.MapAudio){e.Create(this.audioContext,!0);let t=this.audioContext.createGain();t.gain.value=0;let i=this.audioContext.createAnalyser();i.fftSize=512,i.smoothingTimeConstant=0;let n=this.audioContext.createChannelSplitter(2),s=this.audioContext.createAnalyser();s.smoothingTimeConstant=0,s.fftSize=128;let o=this.audioContext.createAnalyser();o.smoothingTimeConstant=0,o.fftSize=128,e.AddAudioNode(t),e.AddAudioNode(i),e.AddAudioNode(s),e.AddAudioNode(o),e.ConnectToContext(this.audioContext,((e,a)=>{a.connect(t),t.connect(this.audioContext.destination),a.connect(i),a.connect(n),n.connect(s,0),n.connect(o,1)})),e.Play(),this._playingAudios.audios.push(e),e.playingCallback&&e.playingCallback(),t.gain.linearRampToValueAtTime(1,this.audioContext.currentTime+.5)}else e.Create(this.audioContext,!1),e.ConnectToContext(this.audioContext),t&&e.source&&(e.source.playbackRate.value=t),e.Play(),this._playingAudios.audios.push(e);e.RegisterEndCallBack((()=>{e instanceof s.MapAudio&&(this._musicQueue[0]==e&&this._musicQueue.splice(0,1),this.UpdateMusicQueue()),this._playingAudios.audios.forEach(((t,i)=>{t!==e||this._playingAudios.audios.splice(i,1)}))}))}}},14981:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.PlayingAudios=void 0;t.PlayingAudios=class{audios=[]}},9611:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.LogoVisualizer=void 0;const a=i(20825),r=o(i(58687)),l=i(5825),u=i(22331);class c extends r.Container{static size=900;frequencyAmplitudes=new Float32Array(256);audio;temporalAmplitudes=new Float32Array(256);graphics=new r.Graphics;index_change=5;bar_length=600;bars_per_visualiser=200;visualiser_rounds=5;decay_per_millisecond=.0024;time_between_updates=50;amplitude_dead_zone=1/this.bar_length;indexOffset=0;firstDraw=!0;set alpha(e){super.alpha=.2*e}get alpha(){return 5*super.alpha}constructor(){super(),this.alpha=1}start(){this.graphics.blendMode="add",this.addChild(this.graphics),this.graphics.eventMode="none",this.eventMode="none",setInterval((()=>{this.updateAmplitudes()}),this.time_between_updates)}draw(e){if(this.firstDraw)for(let e=0;ethis.frequencyAmplitudes[e]&&(this.frequencyAmplitudes[e]=i)}this.indexOffset=(this.indexOffset+this.index_change)%this.bars_per_visualiser}}t.LogoVisualizer=c},8211:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MenuLogoVisualizer=void 0;const n=i(9611);class s extends n.LogoVisualizer{draw(e){super.draw(e)}}t.MenuLogoVisualizer=s},49323:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.LoadAnim=void 0;const a=o(i(58687)),r=o(i(29172)),l=i(92915);class u extends a.Container{bg;arc;arcContainer;animInterval;container;bgContainer;bgRotation=0;constructor(e,t){super(),this.pivot.set(.5,.5),this.container=new a.Container,this.container.alpha=0,this.rotation=2.5*Math.PI,this.bgContainer=new a.Container,this.bg=new a.Graphics,this.bg.roundRect(-50,-50,100,100,25),this.bg.fill(e),this.arcContainer=new a.Container,this.arc=new a.Graphics,this.arc.arc(0,0,27,Math.PI+.26,2.92*Math.PI),this.arc.stroke({width:8,color:t,cap:"round"}),this.arc.scale.set(-1,1),this.container.scale.set(.5,.5),this.bgContainer.addChild(this.bg),this.arcContainer.addChild(this.arc),this.bgContainer.addChild(this.arcContainer),this.container.addChild(this.bgContainer),this.addChild(this.container),l.Ease.getEase(this.container).ScaleTo(1,400,r.Easing.Quadratic.InOut).FadeIn(400,r.Easing.Quadratic.InOut),this.doAnims(),this.animInterval=setInterval((()=>{this.doAnims()}),800)}doAnims(){this.bgRotation+=90,l.Ease.getEase(this.bgContainer).createTween({value:this.bgContainer.angle},{value:this.bgRotation},!0,"angle",600,r.Easing.Quadratic.InOut)}getWidth(){return 100*this.scale.x}getHeight(){return 100*this.scale.y}draw(e){this.arcContainer.angle+=3*e.deltaTime}destroy(e){l.Ease.getEase(this.container).FadeOut(400,r.Easing.Quadratic.InOut).ScaleTo(.5,400,r.Easing.Quadratic.InOut),setTimeout((()=>{clearInterval(this.animInterval),super.destroy(e)}),400)}}t.LoadAnim=u},70723:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.ButtonSystem=void 0;const a=o(i(58687)),r=o(i(29172)),l=i(92915),u=i(84283),c=i(57853);class d extends a.Container{menuBG=new a.Graphics;isOpened=!1;logo;state=h.Initial;logoTrackingContainer=new c.LogoTrackingContainer;menuHeight=150;get State(){return this.state}set State(e){if(this.state==e)return;const t=this.state;this.state=e,this.updateLogoState(t),console.log(`${this.constructor.name}'s state changed from ${t} to ${e}`)}updateLogoState(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:h.Initial;switch(this.state){case h.Exit:case h.Initial:this.Close();break;case h.TopLevel:case h.Play:switch(e){case h.TopLevel:break;case h.Initial:this.Open(),l.Ease.getEase(this.logo).ClearEasings().ScaleTo(.5*u.Screen.getScaleBasedOffScreenSize(),200,r.Easing.Linear.In);break;default:this.Open(),l.Ease.getEase(this.logo).ClearEasings().ScaleTo(.5*u.Screen.getScaleBasedOffScreenSize(),200,r.Easing.Quintic.Out)}}}constructor(e){super(),this.logo=e,this.drawMenuBG(),this.scale.y=0,this.alpha=0,this.addChild(this.menuBG),this.addChild(this.logoTrackingContainer),this.logo.Action=()=>this.onOsuLogo()}drawMenuBG(){this.menuBG.rect(0,u.Screen.getScaleBasedOffScreenSize()*(-this.menuHeight/2),1,u.Screen.getScaleBasedOffScreenSize()*this.menuHeight),this.menuBG.fill({color:"rgb(50,50,50)"})}onOsuLogo(){switch(this.state){default:return!1;case h.Initial:return this.State=h.TopLevel,!0;case h.TopLevel:case h.Play:case h.Edit:return!1}}Open(){setTimeout((()=>{this.isOpened=!0,l.Ease.getEase(this).ScaleTo(1,400,r.Easing.Quintic.Out).FadeIn(400,r.Easing.Quintic.Out)}),150)}Close(){this.isOpened=!1,l.Ease.getEase(this).ClearEasings().ScaleTo({x:1,y:0},300,r.Easing.Sinusoidal.In).FadeOut(300,r.Easing.Sinusoidal.In)}isOpen(){return this.isOpened}onResize(){this.menuBG.clear(),this.drawMenuBG(),this.position.set(0,window.innerHeight/2),this.menuBG.width=window.innerWidth}}var h;t.ButtonSystem=d,function(e){e.Exit="Exit",e.Initial="Initial",e.TopLevel="TopLevel",e.Play="Play",e.Edit="Edit",e.EnteringMode="EnteringMode"}(h||(h={}))},57853:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.LogoTrackingContainer=void 0;const a=o(i(58687)),r=o(i(29172));class l extends a.Container{Logo=null;easing;startPosition=null;startTime=null;duration;visual_box_size=72;StartTracking(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:r.Easing.Linear.None;if(e.IsTracking&&null==this.Logo)throw new Error("Cannot track an instance of OsuLogo to multiple LogoTrackingContainers");this.Logo!=e&&null!=this.Logo&&(this.Logo.IsTracking=!1),this.Logo=e,this.Logo.IsTracking=!0,this.duration=t,this.easing=i,this.startTime=null,this.startPosition=null}StopTracking(){null!=this.Logo&&(this.Logo.IsTracking=!1,this.Logo=null)}ComputeLogoTrackingPosition(){let e=this.Logo.position;return e.x=window.innerWidth/3,e}Update(){this.Logo}}t.LogoTrackingContainer=l},73703:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.OsuLogo=void 0;const a=o(i(58687)),r=i(44961),l=o(i(29172)),u=i(92915),c=i(20825),d=i(12235),h=i(8211),f=i(9611),g=i(22331),p=i(5825);class m extends a.Container{outline;visualizer=new h.MenuLogoVisualizer;triangles=new r.Triangles;flash;logoContainer=new a.Container;logoBounceContainer=new a.Container;logoBeatContainer=new a.Container;logoAmplitudeContainer=new a.Container;logoHoverContainer=new a.Container;rippleContainer=new a.Container;ripple;defaultVisualizerAlpha=.5;early_activation=60;timeElapsedSinceLastBeat=0;timeUntilNextBeat=0;lastTimeElapasedSinceLastBeat=0;selectSample=d.Loader.GetAudio("mainMenu.osuLogo.select");backToLogoSample=d.Loader.GetAudio("mainMenu.osuLogo.backToLogo");isMouseDown=!1;mouseDownPosition={x:0,y:0};Action=null;IsTracking=!1;get SizeForFlow(){return this.outline.width*this.logoBounceContainer.scale.x*this.logoHoverContainer.scale.x}constructor(){super(),this.visualizer.start(),this.outline=a.Sprite.from("mainMenu.logoOutline"),this.outline.anchor.set(.5,.5);let e=.7;this.visualizer.scale.set(e),this.visualizer.pivot.set(f.LogoVisualizer.size/2,f.LogoVisualizer.size/2),this.visualizer.alpha=this.defaultVisualizerAlpha;let t=new a.Graphics;t.circle(0,0,450),t.fill({color:"white"}),t.scale=e,this.flash=a.Sprite.from("mainMenu.logoMask"),this.flash.anchor.set(.5,.5),this.flash.scale=e,this.flash.blendMode="add",this.flash.alpha=0,this.triangles.flash.anchor.set(.5,.5),this.triangles.flash.scale=e,this.outline.scale.set(e),this.triangles.scale.set(e),this.triangles.position.set(-this.outline.width/2,-this.outline.height/2),this.triangles.mask=t,this.ripple=a.Sprite.from("mainMenu.logoMask"),this.ripple.anchor.set(.5,.5),this.ripple.scale=e,this.ripple.alpha=0,this.ripple.blendMode="add",this.rippleContainer.addChild(this.ripple),this.logoContainer.addChild(this.visualizer),this.logoContainer.addChild(this.triangles),this.logoContainer.addChild(this.triangles.flash),this.logoContainer.addChild(t),this.logoContainer.addChild(this.flash),this.logoContainer.addChild(this.outline),this.logoContainer.hitArea=new a.Circle(0,0,336),this.logoContainer.eventMode="static",this.logoContainer.onmouseenter=this._onmouseenter,this.logoContainer.onmouseleave=this._onmouseleave,this.logoContainer.onmousedown=this._onmousedown,this.logoContainer.onclick=this._onclick,this.logoBeatContainer.addChild(this.logoContainer),this.logoAmplitudeContainer.addChild(this.logoBeatContainer),this.logoBounceContainer.addChild(this.rippleContainer),this.logoBounceContainer.addChild(this.logoAmplitudeContainer),this.logoHoverContainer.addChild(this.logoBounceContainer),this.addChild(this.logoHoverContainer),c.Main.app.stage.addEventListener("mouseup",(e=>{this._onmouseup(e)}))}_onmouseenter=e=>{u.Ease.getEase(this.logoHoverContainer).ScaleTo(1.1,500,l.Easing.Elastic.Out)};_onmouseleave=e=>{u.Ease.getEase(this.logoHoverContainer).ScaleTo(1,500,l.Easing.Elastic.Out)};_onmousedown=e=>{this.isMouseDown=!0,u.Ease.getEase(this.logoBounceContainer).ClearEasings().ScaleTo(.9,1e3,l.Easing.Sinusoidal.Out),this.mouseDownPosition={x:c.Main.mousePos.x,y:c.Main.mousePos.y}};_onclick=e=>{this.flash.alpha=.4,u.Ease.getEase(this.flash).ClearEasings().FadeOut(1500,l.Easing.Exponential.Out),this.Action&&this.Action()&&c.Main.AudioEngine.PlayEffect(d.Loader.GetAudio("mainMenu.osuLogo.select"))};_onmouseup=e=>{this.isMouseDown=!1,u.Ease.getEase(this.logoBounceContainer).ClearEasings().ScaleTo(1,500,l.Easing.Elastic.Out).TransformTo({x:0,y:0},800,l.Easing.Elastic.Out)};draw(e){this.visualizer.draw(e),this.triangles.draw(e);let t=c.Main.AudioEngine.GetCurrentPlayingMusic(),i=t.GetCurrentTime(),n=t.beatmap.TimingPoints.GetCurrentUninheritedTimingPoint(i);if(this.timeUntilNextBeat=(n.time-i)%n.beatLength,this.timeUntilNextBeat<=0&&(this.timeUntilNextBeat+=n.beatLength),this.timeElapsedSinceLastBeat=n.beatLength-this.timeUntilNextBeat,c.Main.AudioEngine.useSilentMusic)this.logoAmplitudeContainer.scale=1,this.triangles.Velocity=p.MathUtil.Damp(this.triangles.Velocity,.5,.9,e.deltaMS);else{let i=t.GetMaximumAudioLevel();this.logoAmplitudeContainer.scale.set(p.MathUtil.Damp(this.logoAmplitudeContainer.scale.x,1-.04*Math.max(0,i-.4),.9,e.deltaMS)),this.triangles.Velocity=p.MathUtil.Damp(this.triangles.Velocity,.5*(n.effects==g.Effect.KiaiTime?4:2),.995,e.deltaMS)}if(this.lastTimeElapasedSinceLastBeat>this.timeElapsedSinceLastBeat&&this.onNewBeat(),this.lastTimeElapasedSinceLastBeat=this.timeElapsedSinceLastBeat,this.isMouseDown){let e={x:c.Main.mousePos.x-this.mouseDownPosition.x,y:c.Main.mousePos.y-this.mouseDownPosition.y},t=Math.sqrt(e.x*e.x+e.y*e.y);e.x*=t<=0?0:Math.pow(t,.6)/t,e.y*=t<=0?0:Math.pow(t,.6)/t,this.logoBounceContainer.x=e.x,this.logoBounceContainer.y=e.y}}onNewBeat(){let e=c.Main.AudioEngine.GetCurrentPlayingMusic(),t=e.GetCurrentTime(),i=e.beatmap.TimingPoints.GetCurrentUninheritedTimingPoint(t).beatLength,n=e.beatmap.TimingPoints.GetCurrentTimingPoints(t)[0],s=c.Main.AudioEngine.useSilentMusic?0:e.GetMaximumAudioLevel(),o=Math.min(1,.2+s);u.Ease.getEase(this.logoBeatContainer).ScaleTo(1-.02*o,this.early_activation,l.Easing.Linear.None).Then().ScaleTo(1,2*i,l.Easing.Quintic.Out),this.rippleContainer.scale=1.02,u.Ease.getEase(this.rippleContainer).ClearEasings().ScaleTo(1.02*(1+.04*o),i,l.Easing.Quintic.Out),this.ripple.alpha=.15*o,u.Ease.getEase(this.ripple).ClearEasings().FadeOut(i,l.Easing.Quintic.Out),n.effects==g.Effect.KiaiTime&&(u.Ease.getEase(this.triangles.flash).ClearEasings().FadeTo(.2*o,this.early_activation,l.Easing.Linear.None).Then().FadeTo(0,i,l.Easing.Linear.None),u.Ease.getEase(this.visualizer).ClearEasings().FadeTo(1.8*this.defaultVisualizerAlpha*o,this.early_activation,l.Easing.Linear.None).Then().FadeTo(this.defaultVisualizerAlpha,i,l.Easing.Linear.None)),setTimeout((()=>{this.triangles.Velocity+=o*(n.effects==g.Effect.KiaiTime?6:3)}),60)}}t.OsuLogo=m},44961:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.Triangles=void 0;const r=o(i(58687)),l=i(20825),u=a(i(46404)),c=a(i(58689)),d=a(i(61630));class h extends r.Container{flash;Velocity=1;bgGradient;triangles=[];graphics=new r.Graphics;timeSinceLastSpawn=0;instancePositionBuffer;totalTriangles=15;constructor(){super();let e=[16737963,13390473];this.bgGradient=new r.FillGradient(0,0,0,1024),e.forEach(((t,i)=>{const n=i/e.length;this.bgGradient.addColorStop(n,t)}));for(let e=0;e{this.mouseButtonClicked=e.button,this.visible&&(this.posMouseDown={x:r.Main.mousePos.x,y:r.Main.mousePos.y},this.mouseIsDown=!0,this.dragRotationState=g.DragStarted,d.Ease.getEase(this.animContainer).ClearEasings().ScaleTo(.9,800,h.Easing.Quintic.Out),d.Ease.getEase(this.mouseCursorAdditive).ClearEasings().FadeIn(800,h.Easing.Quintic.Out),r.Main.AudioEngine.PlayEffect(this.cursorTapSample))})),r.Main.app.stage.addEventListener("mouseup",(e=>{this.visible&&e.button==this.mouseButtonClicked&&(this.mouseIsDown=!1,d.Ease.getEase(this.animContainer).ClearEasings().ScaleTo(1,500,h.Easing.Elastic.Out),d.Ease.getEase(this.mouseCursorAdditive).ClearEasings().FadeOut(500,h.Easing.Quintic.Out),this.dragRotationState!=g.NotDragging&&(this.dragRotationState==g.Rotating&&d.Ease.getEase(this.animRotationContainer).ClearEasings().createTween({value:this.animRotationContainer.angle},{value:0},!0,"angle",800*(.5+Math.abs(this.animRotationContainer.angle/960)),(e=>Math.pow(2,-10*e)*Math.sin((.25*e-this.elastic_const2)*this.elastic_const)+1-this.elastic_offset_quarter*e)),this.dragRotationState=g.NotDragging),r.Main.AudioEngine.PlayEffect(this.cursorTapSample,.8))}))}PopIn(){d.Ease.getEase(this.animRotationContainer).ClearEasings(),this.visible=!0,d.Ease.getEase(this.mouseHideContainer).ClearEasings().FadeIn(250,h.Easing.Quintic.Out).ScaleTo(1,400,h.Easing.Quintic.Out),this.dragRotationState=g.NotDragging}PopOut(){d.Ease.getEase(this.mouseHideContainer).ClearEasings().FadeOut(250,h.Easing.Quintic.Out).ScaleTo(.6,250,h.Easing.Quintic.Out),d.Ease.getEase(this.animRotationContainer).ClearEasings().createTween({value:this.animRotationContainer.angle},{value:0},!0,"angle",400,h.Easing.Quintic.Out),this.dragRotationState=g.NotDragging}updateMouse(){if(this.mouseContainer.scale.set(.07*c.Screen.getScaleBasedOffScreenSize()),this.position.set(r.Main.mousePos.x,r.Main.mousePos.y),this.dragRotationState!=g.NotDragging&&this.visible){let e=Math.sqrt((2^Math.abs(this.posMouseDown.x-r.Main.mousePos.x))+(2^Math.abs(this.posMouseDown.y-r.Main.mousePos.y)));if(this.dragRotationState==g.DragStarted&&e>15&&(this.dragRotationState=g.Rotating,this.lastDragRotationState!=this.dragRotationState&&(this.posMouseDown={x:r.Main.mousePos.x,y:r.Main.mousePos.y})),this.dragRotationState==g.Rotating&&e>0){let e=r.Main.mousePos.x-this.posMouseDown.x,t=r.Main.mousePos.y-this.posMouseDown.y,i=u.MathUtil.RadiansToDegrees(Math.atan2(-e,t))+24.3,n=(i-this.animRotationContainer.angle)%360;n<-180&&(n+=360),n>180&&(n-=360),i=this.animRotationContainer.angle+n,this.animRotationContainer.angle=i,d.Ease.getEase(this.animRotationContainer).createTween({value:this.animRotationContainer.angle},{value:i},!0,"angle",120,h.Easing.Quintic.Out)}}this.lastDragRotationState=this.dragRotationState}}var g;t.MenuCursor=f,function(e){e[e.NotDragging=0]="NotDragging",e[e.DragStarted=1]="DragStarted",e[e.Rotating=2]="Rotating"}(g||(g={}))},67991:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.BackgroundContainer=t.Background=void 0;const a=o(i(58687)),r=i(92915),l=o(i(29172));class u extends a.Sprite{static fadeOutDuration=800;destroying=!1;constructor(e){super(),this.texture=e,this.visible=!1,this.anchor.set(.5,.5)}show(){this.visible=!0}destroy(e){this.destroying=!0,r.Ease.getEase(this).FadeOut(u.fadeOutDuration,l.Easing.Linear.None).Then((()=>{this.visible=!1,super.destroy(e),this.destroying=!1})),this.zIndex=1}}t.Background=u;class c extends a.Container{constructor(){super(),this.visible=!1}show(){this.visible=!0;for(let e=0;e{super.destroy(e)}),u.fadeOutDuration),this.zIndex=1}}t.BackgroundContainer=c},36721:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.RandomBackground=void 0;const a=o(i(58687)),r=i(12235),l=i(84283),u=i(20825),c=i(67991),d=i(15041);class h extends l.Screen{bgContainer=new a.Container;parallaxMultiplier=60;start(){this.bgContainer.pivot.set(.5,.5),this.bgContainer.position.set((u.Main.mousePos.x-this.getScreenWidth()/2)/this.parallaxMultiplier,(u.Main.mousePos.y-this.getScreenHeight()/2)/this.parallaxMultiplier),this.addChild(this.bgContainer),this.newRandomBG(),u.Main.AudioEngine.addMusicChangeEventListener((e=>{let t=e.beatmap.Events.Events.find((e=>{if(e.eventType==d.EventTypes.BACKGROUND)return e})),i=e.beatmap.Events.Events.find((e=>{if(e.eventType==d.EventTypes.VIDEO)return e})),n=new c.BackgroundContainer;if(t&&t.texture&&n.addChild(new c.Background(t.texture)),i&&i.texture){let e=i.texture.source.resource,t=new c.Background(i.texture);n.addChild(t),i.texture.source.resource.startPromise=new Promise((t=>{i.startTime>0?setTimeout((()=>{e.play(),t()}),i.startTime):(e.currentTime=Math.abs(i.startTime)/1e3,e.play(),t())})),e.onended=()=>{t.destroy()}}(t||i)&&this.setBGContainer(n),t||i||this.newRandomBG()})),this.zIndex=-100}setBG(e){let t=new c.Background(e);if(this.bgContainer.addChild(t),t.show(),0==this.bgContainer.children?.length);else{this.bgContainer.children[0].destroy()}this.onResize()}setBGContainer(e){if(this.bgContainer.addChild(e),e.show(),0==this.bgContainer.children?.length);else{this.bgContainer.children[0].destroy()}this.onResize()}newRandomBG(){let e=r.Loader.seasonalBackgroundsNum>0,t=(i=1,n=e?r.Loader.seasonalBackgroundsNum:r.Loader.defaultBackgroundsNum,Math.round(Math.random()*(n-i)+i));var i,n;this.setBG(a.Texture.from((e?"seasonal_bg":"default_bg")+t))}draw(e){this.bgContainer.position.set((u.Main.mousePos.x-this.getScreenWidth()/2)/this.parallaxMultiplier,(u.Main.mousePos.y-this.getScreenHeight()/2)/this.parallaxMultiplier)}onClose(){return Promise.resolve(this)}onResize(){this.bgContainer.children.forEach((e=>{e instanceof c.BackgroundContainer&&e.children?.forEach((e=>{e instanceof c.Background&&this.resizeSprite(e)})),e instanceof c.Background&&this.resizeSprite(e)}))}resizeSprite(e){let t,i=e.texture.width,n=e.texture.height;t=window.innerWidth>window.innerHeight?window.innerWidth/i:window.innerHeight/n,n*t{i.id==e&&(t=i.data)})),!t)throw new Error("Asset not found!");return t}static GetString(e){let t;if(this.loadedList.forEach((i=>{i.id==e&&(t=i.dataString)})),!t)throw new Error("Asset not found or is not a string!");return t}static GetAudio(e){let t;if(this.loadedList.forEach((i=>{i.id==e&&(t=i.dataAudio)})),!t)throw new Error("Asset not found or was not marked as audio during loading!");return t}static addBackgrounds(){return new Promise((e=>{for(let e=1;ee.json())).then((t=>{t.backgrounds.forEach(((e,t)=>{this.loadList.push({id:"seasonal_bg"+(t+1),url:"https://corsproxy.io/?"+encodeURIComponent(e.url),pixiBundleName:"textures",loadParser:"loadTextures"}),this.seasonalBackgroundsNum=t+1})),e()})).catch((t=>{console.warn("Could not fetch seasonal backgrounds.",t),e()}))}))}static Load(e){return this.addToLoadList(),new Promise((t=>{this.addBackgrounds().then((()=>{let i=[],n=[],s=[],o=0,r=0;this.loadList.forEach((e=>{e.pixiBundleName?n.push(e):i.push(e)})),n.forEach((e=>{let t=!1;s.forEach((i=>{i.length>0&&i[0].pixiBundleName==e.pixiBundleName&&(i.push(e),t=!0)})),t||s.push([e])}));const l=e=>{e?r++:o++,r+o>=this.loadList.length&&t()};i.forEach((t=>{fetch(t.url).then((e=>e.blob())).then((i=>{t.isText||t.isAudio?t.isText?i.text().then((e=>{l(),this.loadedList.push({id:t.id,data:i,dataString:e})})):t.isAudio&&i.arrayBuffer().then((t=>e.decodeAudioData(t))).then((e=>{l(),this.loadedList.push({id:t.id,data:i,dataAudio:e})})):(l(),this.loadedList.push({id:t.id,data:i}))})).catch((e=>{l(!0),console.warn("Asset '"+t.id+"' failed to load: "+e)}))})),s.forEach((e=>{if(e.length>0){if(!e[0].pixiBundleName)throw new Error("wtf????");let t=[];e.forEach((e=>{e.loadParser?t.push({alias:e.id,src:e.url,loadParser:e.loadParser}):t.push({alias:e.id,src:e.url})})),a.Assets.addBundle(e[0].pixiBundleName,t),a.Assets.loadBundle(e[0].pixiBundleName).then((()=>{e.forEach((()=>{l()}))}))}}))}))}))}}},25373:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.InteractScreen=void 0;const a=i(84283),r=o(i(58687)),l=i(20825),u=i(94433),c=o(i(29172)),d=i(92915);class h extends a.Screen{text;text2;textContainer=new r.Container;textContainerContainer=new r.Container;introTrack;clickSound;clickArea=new r.Graphics;constructor(e,t){super(),this.introTrack=e,this.clickSound=t,this.text=new r.Text({text:"Click anywhere to play!",style:{fontFamily:"TorusRegular",fontSize:36,fill:"white"}}),this.text2=new r.Text({text:"(this is for enabling audio because it's required by web-browsers\n to have interaction on this webpage before playing audio.)",style:{fontFamily:"TorusRegular",fontSize:26,fill:"gray",align:"center"}})}start(){this.text.anchor.set(.5,.5),this.text2.anchor.set(.5,.5),this.text2.position.set(0,this.text.height+15),this.textContainer.addChild(this.text),this.textContainer.addChild(this.text2),this.textContainer.scale.set(.5),this.textContainer.alpha=0,this.textContainerContainer.addChild(this.textContainer),this.textContainerContainer.scale=a.Screen.getScaleBasedOffScreenSize(),this.textContainerContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.addChild(this.textContainerContainer),this.clickArea.rect(0,0,1,1),this.clickArea.fill("rgba(0,0,0,0)"),this.clickArea.width=this.getScreenWidth(),this.clickArea.height=this.getScreenHeight(),this.clickArea.position.set(0,0),this.addChild(this.clickArea),this.clickArea.eventMode="static",this.clickArea.cursor="pointer";const e=()=>{this.clickArea.eventMode="none",l.Main.AudioEngine.PlayEffect(this.clickSound),l.Main.switchScreen(new u.IntroScreen(this.introTrack)),document.body.style.cursor="none",l.Main.pointerLock(),l.Main.lockKeyboard()};this.clickArea.onclick=()=>{e()},this.clickArea.ontap=()=>{e()},d.Ease.getEase(this.textContainer).FadeIn(400,c.Easing.Quadratic.Out).ScaleTo(1,400,c.Easing.Quadratic.Out)}onClose(){return new Promise((e=>{d.Ease.getEase(this.textContainer).FadeOut(200,c.Easing.Quadratic.Out).ScaleTo(.5,200,c.Easing.Quadratic.InOut),setTimeout((()=>{e(this)}),200)}))}draw(e){}onResize(){this.textContainerContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.clickArea.width=this.getScreenWidth(),this.clickArea.height=this.getScreenHeight(),this.clickArea.position.set(0,0),this.textContainerContainer.scale=a.Screen.getScaleBasedOffScreenSize()}}t.InteractScreen=h},88662:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.GlitchingTriangles=void 0;const a=o(i(58687)),r=i(92915),l=o(i(29172));class u extends a.Container{constructor(e){super();let t=new a.Graphics,i=n(.2,1.2);function n(e,t){return Math.random()*(t-e)+e}t.moveTo(0,0),t.lineTo(-50*i,100*i),t.lineTo(50*i,100*i),t.lineTo(0,0),Math.random()<.5?t.fill("white"):t.stroke({color:"white",width:1});let s=n(e.x1,e.x2),o=n(e.y1,e.y2);t.position.set(s,o),r.Ease.getEase(t,!0).FadeOut(200,l.Easing.Linear.None),setTimeout((()=>{this.destroy()}),200),this.addChild(t)}}t.GlitchingTriangles=u},94433:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.IntroScreen=void 0;const a=i(84283),r=o(i(58687)),l=i(53931),u=i(20825),c=i(88662),d=i(58940),h=i(55402),f=i(9752),g=o(i(29172)),p=i(92915),m=i(5168),v=i(94461),y=i(17898);class b extends a.Screen{introTrackUrl;doTextSpacingAnim=!1;triangles=new r.Container;ruleSetContainer=new r.Container;ruleSetList=new v.CenteredList({});flash=new r.Graphics;logoContainerContainer=new r.Container;logoContainer=new r.Container;lazerLogo=new h.LazerLogo;flashed=!1;standard=r.Sprite.from("icon_ruleset_std");taiko=r.Sprite.from("icon_ruleset_taiko");ctb=r.Sprite.from("icon_ruleset_ctb");mania=r.Sprite.from("icon_ruleset_mania");bg=new r.Graphics;completionPromise;welcomeText=new r.Text({text:"",style:{fontFamily:"TorusThin",fontSize:42,fill:"white",letterSpacing:5}});constructor(e){super(),this.introTrackUrl=URL.createObjectURL(e),this.bg.rect(0,0,1,1),this.bg.fill("black")}start(){this.bg.width=window.innerWidth,this.bg.height=window.innerHeight,this.bg.x=0,this.bg.y=0,this.addChild(this.bg),this.lazerLogo.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.logoContainer.addChild(this.lazerLogo),this.logoContainer.scale.set(1.2),this.logoContainerContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.logoContainerContainer.pivot.set(.5,.5),this.logoContainerContainer.addChild(this.logoContainer),this.logoContainerContainer.alpha=0,this.addChild(this.logoContainerContainer),this.flash.rect(0,0,1,1),this.flash.fill("white"),this.flash.position.set(0,0),this.flash.width=this.getScreenWidth(),this.flash.height=this.getScreenHeight(),this.flash.blendMode="add",this.welcomeText.anchor.set(.5,.5),this.welcomeText.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),(async()=>{const{entries:e}=await(0,l.unzip)(this.introTrackUrl);for(const[t,i]of Object.entries(e))if(t.endsWith(".osu")){i.text().then((async t=>{let i,n=new y.BeatmapData;await new Promise((t=>{for(const[i,s]of Object.entries(e))s.blob().then((s=>{n.files.set(i,s),n.files.size==Object.entries(e).length&&t()}))}));for(const[e,t]of n.files.entries())e.endsWith(".osb")&&(i=await t.text());f.BeatmapParser.Parse(t,n,i),await f.BeatmapParser.LoadFiles(n,u.Main.AudioEngine);let s=n.General.audioFile;if(s){let e=URL.createObjectURL(s);setTimeout((()=>{u.Main.AudioEngine.PlayMusicImmediately(e,n,(()=>{this.afterAudioPlay()}))}),200)}console.log(n)}));break}})()}afterAudioPlay(){this.completionPromise=new Promise((e=>{let t;this.welcomeText.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.addChild(this.welcomeText),setTimeout((()=>{this.welcomeText.text="wel",this.onResize()}),200),setTimeout((()=>{this.welcomeText.text="welcome",this.onResize()}),400),setTimeout((()=>{this.welcomeText.text="welcome to",this.onResize()}),700),this.triangles.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.triangles.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.addChild(this.triangles),setTimeout((()=>{this.welcomeText.text="welcome to kosu!",this.doTextSpacingAnim=!0,t=setInterval((()=>{let e=new c.GlitchingTriangles({x1:-this.welcomeText.width/2-100,x2:this.welcomeText.width/2+100,y1:-this.welcomeText.height/2-150,y2:this.welcomeText.height/2+100});this.triangles.addChild(e)}),30),this.onResize()}),900),this.standard.scale=.5*a.Screen.getScaleBasedOffScreenSize(),this.ctb.scale=.5*a.Screen.getScaleBasedOffScreenSize(),this.mania.scale=.5*a.Screen.getScaleBasedOffScreenSize(),this.taiko.scale=.5*a.Screen.getScaleBasedOffScreenSize(),this.ruleSetList.addChild(this.standard),this.ruleSetList.addChild(this.taiko),this.ruleSetList.addChild(this.ctb),this.ruleSetList.addChild(this.mania),this.ruleSetList.padding=0,this.ruleSetList.elementsMargin=200*a.Screen.getScaleBasedOffScreenSize(),this.ruleSetList.type="horizontal",this.ruleSetList.scale=1,this.ruleSetContainer.addChild(this.ruleSetList),setTimeout((()=>{this.doTextSpacingAnim=!1,this.onResize(),clearInterval(t),this.welcomeText.destroy(),this.triangles.destroy(),this.ruleSetContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.addChild(this.ruleSetContainer),this.ruleSetList.elementsMargin=200*a.Screen.getScaleBasedOffScreenSize(),p.Ease.getEase(this.ruleSetContainer).ScaleTo(.8,1e3,g.Easing.Linear.None)}),1450),setTimeout((()=>{this.ruleSetList.elementsMargin=30*a.Screen.getScaleBasedOffScreenSize(),this.ruleSetList.scale=2,m.UIUtils.centerPivotOfList(this.ruleSetList)}),1650),setTimeout((()=>{this.ruleSetList.elementsMargin=10*a.Screen.getScaleBasedOffScreenSize(),this.ruleSetList.scale=4,p.Ease.getEase(this.ruleSetContainer).ScaleTo(1.3,1e3,g.Easing.Linear.None)}),1850),setTimeout((()=>{this.ruleSetContainer.destroy(),this.lazerLogo.start(),this.logoContainerContainer.alpha=1,this.logoContainerContainer.scale.set(1.2),p.Ease.getEase(this.logoContainerContainer).ScaleTo(1,920,g.Easing.Quadratic.In),setTimeout((()=>{p.Ease.getEase(this.logoContainer).ScaleTo(1.2-.8,276,g.Easing.Quintic.In)}),644)}),2080),setTimeout((()=>{this.addChild(this.flash),this.bg.destroy(),this.flash.eventMode="none",this.flashed=!0,this.logoContainerContainer.visible=!1,p.Ease.getEase(this.flash).FadeOut(1e3,g.Easing.Quadratic.Out).Then((()=>{e()})),u.Main.cursor.PopIn()}),3e3)})),u.Main.switchScreen(new d.MainMenu)}draw(e){this.doTextSpacingAnim&&(this.welcomeText.style.letterSpacing+=.15*e.deltaTime,this.onResize())}onClose(){return new Promise((e=>{this.completionPromise.then((()=>{e(this)}))}))}onResize(){this.bg.destroyed||(this.bg.width=window.innerWidth,this.bg.height=window.innerHeight,this.bg.x=0,this.bg.y=0),this.welcomeText.destroyed||this.welcomeText.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.triangles.destroyed||(this.triangles.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.triangles.scale.set(a.Screen.getScaleBasedOffScreenSize())),this.ruleSetContainer.destroyed||this.ruleSetContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.flash.destroyed||(this.flash.position.set(0,0),this.flash.width=this.getScreenWidth(),this.flash.height=this.getScreenHeight()),this.logoContainerContainer.destroyed||this.logoContainerContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.lazerLogo.destroyed||this.lazerLogo.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.welcomeText.destroyed||this.welcomeText.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.standard.destroyed||this.standard.scale.set(.5*a.Screen.getScaleBasedOffScreenSize()),this.mania.destroyed||this.mania.scale.set(.5*a.Screen.getScaleBasedOffScreenSize()),this.ctb.destroyed||this.ctb.scale.set(.5*a.Screen.getScaleBasedOffScreenSize()),this.taiko.destroyed||this.taiko.scale.set(.5*a.Screen.getScaleBasedOffScreenSize()),this.ruleSetList.destroyed||this.ruleSetList.ReCenter()}}t.IntroScreen=b},55402:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.LazerLogo=void 0;const a=o(i(58687)),r=i(87525),l=o(i(29172)),u=i(92915);class c extends a.Container{highlight;background;textureHighlight=a.Texture.from("intro_triangles_osuLogo_anim_highlight");textureBackground=a.Texture.from("intro_triangles_osuLogo_anim_background");constructor(){super(),this.highlight=new r.LogoAnimation(this.textureHighlight,new a.Color("white")),this.background=new r.LogoAnimation(this.textureBackground,new a.Color("rgb(128, 128, 128)")),this.addChild(this.highlight),this.addChild(this.background)}start(){let e=new a.Container;e.scale.set(0,0),u.Ease.getEase(e).ScaleTo(1,920,l.Easing.Linear.None).OnEach((()=>{this.highlight.setProgress(e.scale.x),this.background.setProgress(e.scale.x)}))}}t.LazerLogo=c},87525:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.LogoAnimation=void 0;const r=o(i(58687)),l=a(i(26045)),u=a(i(44160)),c=a(i(46110));class d extends r.Container{shader;texture;constructor(e,t){super(),this.texture=e,this.shader=r.Shader.from({gl:{vertex:l.default,fragment:u.default},gpu:{vertex:{entryPoint:"mainVert",source:c.default},fragment:{entryPoint:"mainFrag",source:c.default}},resources:{uTexture:this.texture.source,uSampler:this.texture.source.style,uProgress:{progress:{value:0,type:"f32"}}}});const i=new r.Geometry({attributes:{aPosition:[-this.texture.width/2,-this.texture.height/2,this.texture.width/2,-this.texture.height/2,this.texture.width/2,this.texture.width/2,-this.texture.width/2,this.texture.width/2],aUV:[0,0,1,0,1,1,0,1],aColor:[t.red,t.green,t.blue,t.alpha,t.red,t.green,t.blue,t.alpha,t.red,t.green,t.blue,t.alpha,t.red,t.green,t.blue,t.alpha]},indexBuffer:[0,1,2,0,2,3]}),n=new r.Mesh({geometry:i,shader:this.shader});this.addChild(n)}setProgress(e){this.shader.resources.uProgress.uniforms.progress=e}}t.LogoAnimation=d},76969:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.LoadScreen=void 0;const n=i(84283),s=i(49323);class o extends n.Screen{loadAnim=new s.LoadAnim("rgba(255,255,255,0.7)","black");start(){this.loadAnim.scale.set(.8*n.Screen.getScaleBasedOffScreenSize()),this.loadAnim.position.set(this.getScreenWidth()-this.loadAnim.getWidth()-15,this.getScreenHeight()-this.loadAnim.getHeight()-15),this.addChild(this.loadAnim)}draw(e){this.loadAnim?.draw(e)}onClose(){return new Promise((e=>{null!=this.loadAnim&&this.loadAnim.destroy(),setTimeout((()=>{e(this)}),400)}))}onResize(){this.loadAnim.position.set(this.getScreenWidth()-this.loadAnim.getWidth()-20,this.getScreenHeight()-this.loadAnim.getHeight()-20),this.loadAnim.scale.set(.8*n.Screen.getScaleBasedOffScreenSize())}}t.LoadScreen=o},58940:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MainMenu=void 0;const n=i(84283),s=i(36721),o=i(73703),a=i(70723);class r extends n.Screen{bg=new s.RandomBackground;osuCircle=new o.OsuLogo;menu=new a.ButtonSystem(this.osuCircle);start(){this.bg.start(),this.addChild(this.bg),this.osuCircle.scale=n.Screen.getScaleBasedOffScreenSize(),this.addChild(this.menu),this.menu.onResize(),this.addChild(this.osuCircle)}draw(e){this.bg.draw(e),this.osuCircle.draw(e)}onClose(){return new Promise((e=>{this.bg.onClose().then((()=>{e(this)}))}))}onResize(){this.osuCircle.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.bg.onResize(),this.menu.onResize(),this.osuCircle.scale=this.menu.isOpen()?.5*n.Screen.getScaleBasedOffScreenSize():n.Screen.getScaleBasedOffScreenSize()}}t.MainMenu=r},84283:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Screen=void 0;const a=o(i(58687)),r=i(58293),l=i(64681);class u extends a.Container{constructor(){super()}static getScaleBasedOffScreenSize(){const e=r.Settings.getSetting(l.UIScale).getValue();return(window.innerWidth/1920+window.innerHeight/1080)/2*e}getScreenWidth(){return window.innerWidth}getScreenHeight(){return window.innerHeight}}t.Screen=u},75341:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.SettingsCategory=t.Setting=void 0;const n=i(58293);var s;t.Setting=class{info;constructor(e){this.info=e,n.Settings.register({setting:this,info:e})}onValueChanged(){}},function(e){e.General="General",e.Skin="Skin",e.Input="Input",e.UserInterface="User Interface",e.Gameplay="Gameplay",e.Rulesets="Rulesets",e.Audio="Audio",e.Graphics="Graphics",e.Online="Online",e.Maintenance="Maintenance",e.Debug="Debug"}(s||(t.SettingsCategory=s={}))},74975:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.DropdownSetting=void 0;const n=i(75341),s=i(58293);class o extends n.Setting{value;getValue(){if(!this.value)throw new Error("Value is undefined!");return this.value}getDefaultValue(){return this.defaultValue}setValue(e){this.list.find((t=>t.value==e.value&&t.displayName==e.displayName))?(this.value=e,s.Settings.save(),this.onValueChanged()):console.warn("The value provided to this DropDownSetting does not exist in the option list! Ignoring value provided.")}loadFromSaveValue(e){this.list.find((t=>t.value==e.value&&t.displayName==e.displayName))?(this.value=e,this.onValueChanged()):console.warn("The value provided to this DropDownSetting does not exist in the option list! Ignoring value provided.")}}t.DropdownSetting=o},78642:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.RangeSetting=void 0;const n=i(75341),s=i(58293),o=i(5825);class a extends n.Setting{value=0;getValue(){return this.value}getDefaultValue(){return this.defaultValue}setValue(e){this.value=o.MathUtil.clamp(this.minValue,this.maxValue,e),s.Settings.save(),this.onValueChanged()}loadFromSaveValue(e){this.value=o.MathUtil.clamp(this.minValue,this.maxValue,e),this.onValueChanged()}}t.RangeSetting=a},58293:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.Settings=void 0;const n=i(64681),s=i(44256),o=i(59029);t.Settings=class{static settingsList=[];static registerAll(){new n.UIScale,new s.Renderer,new o.MouseSensitivity}static load(){let e=window.localStorage.getItem("settings");if(null==e)return;let t=this.getList();try{JSON.parse(e).forEach((e=>{let i=!1;try{e.value||(console.warn("Setting '"+JSON.stringify(e)+"' may be corrupted, skipping!"),i=!0),e.info?(e.info.name||(console.warn("Setting '"+JSON.stringify(e)+"' may be corrupted, skipping!"),i=!0),e.info.category||(console.warn("Setting '"+JSON.stringify(e)+"' may be corrupted, skipping!"),i=!0)):(console.warn("Setting '"+JSON.stringify(e)+"' may be corrupted, skipping!"),i=!0)}catch(e){console.warn("Something went wrong when validating saved settings!",e),console.warn("The setting may be REALLY corrupted, skipping!"),i=!0}if(!i){let i=t.filter((t=>t.info.name==e.info.name&&t.info.category==e.info.category))[0];i?i.setting.loadFromSaveValue(e.value):console.warn("Could not find setting object '"+e.info.name+"', maybe it has been removed in this version of kosu?, skipping setting")}}))}catch(e){console.warn("Failed to load settings! Resetting Settings due to corrupted save!",e),this.reset()}}static save(){let e=this.getList(),t=[];e.forEach((e=>{e.setting.getValue()!=e.setting.getDefaultValue()&&t.push({info:e.info,value:e.setting.getValue()})})),window.localStorage.setItem("settings",JSON.stringify(t))}static reset(){console.warn("Resetting Settings!"),window.localStorage.removeItem("settings")}static register(e){this.settingsList.push(e)}static getSetting(e){return this.settingsList.filter((t=>t.setting instanceof e))[0].setting}static getSettingData(e){return this.settingsList.filter((t=>t.setting instanceof e))[0]}static getList(){return this.settingsList}}},44256:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.Renderer=void 0;const n=i(75341),s=i(74975);class o extends s.DropdownSetting{list=[];webglOption={displayName:"WebGL",value:"webgl"};webGpuOption={displayName:"WebGPU",value:"webgpu"};defaultValue=this.webglOption;constructor(){super({name:"Renderer",category:n.SettingsCategory.Graphics}),this.list.push(this.webglOption,this.webGpuOption),this.value=this.defaultValue}}t.Renderer=o},64681:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.UIScale=void 0;const n=i(78642),s=i(75341);class o extends n.RangeSetting{maxValue=1.6;minValue=.8;increment=.1;defaultValue=1;constructor(){super({name:"UI scaling",category:s.SettingsCategory.Graphics}),this.value=this.defaultValue}}t.UIScale=o},59029:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MouseSensitivity=void 0;const n=i(78642),s=i(75341),o=i(58687);class a extends n.RangeSetting{defaultValue=1;increment=.01;maxValue=10;minValue=.1;constructor(){super({name:"Sensitivity",category:s.SettingsCategory.Input}),this.value=this.defaultValue,this.onValueChanged()}onValueChanged(){o.EventSystem.cursorSensitivity=this.getValue()}}t.MouseSensitivity=a},17898:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.BeatmapData=void 0;const n=i(85932),s=i(20352),o=i(32007),a=i(78878),r=i(54611),l=i(6386),u=i(43354);t.BeatmapData=class{files=new Map;formatVersion=-1;General=new n.GeneralData;Editor=new s.EditorData;Metadata=new o.Metadata;Difficulty=new a.DifficultyData;Events=new r.EventsData;TimingPoints=new l.TimingPointsData;Colors=new u.ColorsData}},43354:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.ColorsData=void 0;t.ColorsData=class{Colors=[]}},78878:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.DifficultyData=void 0;t.DifficultyData=class{HPDrainRate;CircleSize;OverallDifficulty;ApproachRate;SliderMultiplier;SliderTickRate}},20352:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.EditorData=void 0;t.EditorData=class{Bookmarks=[];DistanceSpacing;BeatDivisor;GridSize;TimelineZoom}},90361:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.Event=void 0;t.Event=class{eventType;startTime=0}},64432:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventBackground=void 0;const n=i(90361),s=i(15041);class o extends n.Event{eventType=s.EventTypes.BACKGROUND;startTime=0;filename;xOffset;yOffset;texture}t.EventBackground=o},21191:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventBreak=void 0;const n=i(90361),s=i(15041);class o extends n.Event{eventType=s.EventTypes.BREAK;endTime=0}t.EventBreak=o},15041:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.EventTypes=void 0,function(e){e.BACKGROUND="Background",e.VIDEO="Video",e.BREAK="Break",e.COLOR="Colour",e.SPRITE="Sprite",e.SAMPLE="Sample",e.ANIMATION="Animation"}(i||(t.EventTypes=i={}))},19437:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventVideo=void 0;const n=i(90361),s=i(15041);class o extends n.Event{eventType=s.EventTypes.VIDEO;filename;xOffset;yOffset;texture}t.EventVideo=o},54611:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.EventsData=void 0;t.EventsData=class{Events=[]}},68403:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventAnimation=void 0;const n=i(59673),s=i(15041);class o extends n.EventStoryboard{eventType=s.EventTypes.ANIMATION;filepaths=[];frameCount;frameDelay;loopType;textures=[]}t.EventAnimation=o},68227:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventSample=void 0;const n=i(59673),s=i(15041);class o extends n.EventStoryboard{eventType=s.EventTypes.SAMPLE;volume=1;audioBuffer}t.EventSample=o},900:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventSprite=void 0;const n=i(59673),s=i(15041);class o extends n.EventStoryboard{eventType=s.EventTypes.SPRITE;texture}t.EventSprite=o},59673:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventStoryboard=void 0;const n=i(90361);class s extends n.Event{startTime=-1;Commands=[];layer;origin;filepath;x=0;y=0}t.EventStoryboard=s},27187:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.convertToLayer=t.Layer=void 0,function(e){e.Background="Background",e.Fail="Fail",e.Pass="Pass",e.Foreground="Foreground"}(i||(t.Layer=i={})),t.convertToLayer=function(e){let t=parseInt(e);if(isNaN(t))return e;switch(t){case 0:default:return i.Background;case 1:return i.Fail;case 2:return i.Pass;case 3:return i.Foreground}}},24155:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.convertToLoopType=t.LoopType=void 0,function(e){e.LoopForever="LoopForever",e.LoopOnce="LoopOnce"}(i||(t.LoopType=i={})),t.convertToLoopType=function(e){let t=parseInt(e);if(isNaN(t))return e;switch(t){case 0:default:return i.LoopForever;case 1:return i.LoopOnce}}},93729:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.convertToOrigin=t.Origin=void 0,function(e){e.TopLeft="TopLeft",e.Center="Centre",e.CenterLeft="CentreLeft",e.TopRight="TopRight",e.BottomCenter="BottomCentre",e.TopCenter="TopCentre",e.Custom="Custom",e.CenterRight="CentreRight",e.BottomLeft="BottomLeft",e.BottomRight="BottomRight"}(i||(t.Origin=i={})),t.convertToOrigin=function(e){let t=parseInt(e);if(isNaN(t))return e;switch(t){case 0:default:return i.TopLeft;case 1:return i.Center;case 2:return i.CenterLeft;case 3:return i.TopRight;case 4:return i.BottomCenter;case 5:return i.TopCenter;case 6:return i.Custom;case 7:return i.CenterRight;case 8:return i.BottomLeft;case 9:return i.BottomRight}}},37940:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.Countdown=void 0,function(e){e[e.NoCountdown=0]="NoCountdown",e[e.Normal=1]="Normal",e[e.Half=2]="Half",e[e.Double=3]="Double"}(i||(t.Countdown=i={}))},85932:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.GeneralData=void 0;const n=i(37940),s=i(41080),o=i(90857),a=i(45274);t.GeneralData=class{audioFile;AudioFilename=null;AudioLeadIn=0;AudioHash=null;PreviewTime=-1;Countdown=n.Countdown.Normal;SampleSet=s.SampleSet.Normal;StackLeniency=.7;Mode=o.Mode.OSU;LetterboxInBreaks=!1;StoryFireInFront=!0;UseSkinSprites=!1;AlwaysShowPlayfield=!1;OverlayPosition=a.OverlayPosition.NoChange;SkinPreference=null;EpilepsyWarning=!1;CountdownOffset=0;SpecialStyle=!1;WidescreenStoryboard=!1;SamplesMatchPlaybackRate=!1}},90857:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.Mode=void 0,function(e){e[e.OSU=0]="OSU",e[e.TAIKO=1]="TAIKO",e[e.CATCH=2]="CATCH",e[e.MANIA=3]="MANIA"}(i||(t.Mode=i={}))},45274:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.OverlayPosition=void 0,function(e){e.NoChange="NoChange",e.Below="Below",e.Above="Above"}(i||(t.OverlayPosition=i={}))},41080:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.SampleSet=void 0,function(e){e.Normal="Normal",e.Soft="Soft",e.Drum="Drum"}(i||(t.SampleSet=i={}))},32007:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.Metadata=void 0;t.Metadata=class{Title;TitleUnicode;Artist;ArtistUnicode;Creator;Version;Source;Tags;BeatmapID;BeatmapSetID}},22331:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.Effect=void 0,function(e){e[e.KiaiTime=1]="KiaiTime",e[e.None=0]="None",e[e.FirstBarLineOmittedInOsuTaikoAndOsuMania=3]="FirstBarLineOmittedInOsuTaikoAndOsuMania"}(i||(t.Effect=i={}))},3143:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.InheritedTimingPoint=void 0;const n=i(52032);class s extends n.TimingPoint{sliderVelocityMultiplier}t.InheritedTimingPoint=s},52032:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.TimingPoint=void 0;t.TimingPoint=class{time;sampleSet;sampleIndex;volume;effects}},6386:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.TimingPointsData=void 0;const n=i(87816),s=i(3143);t.TimingPointsData=class{TimingPoints=[];GetCurrentTimingPoints(e){let t=[],i=this.TimingPoints.filter((t=>{if(t.time<=e)return t}));if(0==i.length&&i.push(this.TimingPoints[0]),t.push(i[i.length-1]),t[0]instanceof s.InheritedTimingPoint){let i=this.TimingPoints.filter((e=>e instanceof n.UnInheritedTimingPoint)).filter((t=>{if(t.time<=e)return t}));if(0==i.length)throw new Error("Could not find a parent timing point for the un-inherited timing point!");t.push(i[i.length-1])}if(0==t.length)throw new Error("Could not find any timing points!");return t}GetCurrentUninheritedTimingPoint(e){let t,i=this.GetCurrentTimingPoints(e);if(i[0]instanceof n.UnInheritedTimingPoint)t=i[0];else{if(!(i[1]instanceof n.UnInheritedTimingPoint))throw new Error("Could not find any UnInherited Timing Points!");t=i[1]}return t}}},87816:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.UnInheritedTimingPoint=void 0;const n=i(52032);class s extends n.TimingPoint{beatLength;meter}t.UnInheritedTimingPoint=s},9752:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.BeatmapParser=void 0;const n=i(17898),s=i(30444),o=i(81347),a=i(23114),r=i(98803),l=i(92880),u=i(25820);class c{static Parse(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:new n.BeatmapData,i=arguments.length>2?arguments[2]:void 0,d=e.split(/\r?\n|\r|\n/g),h=i?.split(/\r?\n|\r|\n/g);for(let e=0;e{let n=0,s=()=>{2==n&&i()};o.GeneralParser.LoadFiles(e),n++,s(),u.EventsParser.LoadFiles(e,t).then((()=>{n++,s()}))}))}static GetSection(e,t,i){let n=[],s=0;t.forEach(((t,i)=>{t=="["+e+"]"&&(s=i)}));for(let e=s+1;e{let i=t.split(":");i[1].startsWith(" ")&&(i[1]=i[1].substring(1,i[1].length)),n.BeatmapParser.AutoParse(s.DifficultyData,i,e.Difficulty)}))}}},23114:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EditorParser=void 0;const n=i(9752),s=i(20352);t.EditorParser=class{static ParseEditor(e,t){t.forEach((t=>{let i=t.split(":");i[1].startsWith(" ")&&(i[1]=i[1].substring(1,i[1].length)),"Bookmarks"!=i[0]?n.BeatmapParser.AutoParse(s.EditorData,i,e.Editor):i[1].split(",").forEach((t=>{e.Editor.Bookmarks.push(parseFloat(t))}))}))}}},25820:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.EventsParser=void 0;const a=i(15041),r=i(64432),l=i(19437),u=i(21191),c=i(81354),d=o(i(58687)),h=i(12235),f=i(900),g=i(27187),p=i(68403),m=i(93729),v=i(24155),y=i(68227),b=i(5825);t.EventsParser=class{static aviTranscodedVideoCache=[];static ParseEvents(e,t){let i;console.log(t),t.forEach((t=>{let n,s=t.split(",");switch(s[0]){case a.EventTypes.BACKGROUND:case"0":n=new r.EventBackground,n.filename=s[2].replaceAll('"',"").replaceAll("\\","/"),n.xOffset=parseFloat(s[3]),n.yOffset=parseFloat(s[4]),isNaN(n.xOffset)&&(n.xOffset=0),isNaN(n.yOffset)&&(n.yOffset=0),i=n;break;case a.EventTypes.VIDEO:case"1":n=new l.EventVideo,n.startTime=parseInt(s[1]),n.filename=s[2].replaceAll('"',"").replaceAll("\\","/"),n.xOffset=parseFloat(s[3]),n.yOffset=parseFloat(s[4]),isNaN(n.xOffset)&&(n.xOffset=0),isNaN(n.yOffset)&&(n.yOffset=0),i=n;break;case a.EventTypes.BREAK:case"2":n=new u.EventBreak,n.startTime=parseInt(s[1]),n.endTime=parseInt(s[2]),i=n;break;case a.EventTypes.COLOR:case"3":i=void 0;break;case a.EventTypes.SPRITE:case"4":n=new f.EventSprite,n.layer=(0,g.convertToLayer)(s[1]),n.origin=(0,m.convertToOrigin)(s[2]),n.filepath=s[3].replaceAll('"',"").replaceAll("\\","/"),n.x=parseFloat(s[4]),n.y=parseFloat(s[5]),isNaN(n.x)&&(n.x=0),isNaN(n.y)&&(n.y=0),i=n;break;case a.EventTypes.SAMPLE:case"5":n=new y.EventSample,n.startTime=parseFloat(s[1]),n.layer=(0,g.convertToLayer)(s[2]),n.filepath=s[3].replaceAll('"',"").replaceAll("\\","/"),n.volume=s.length>4?b.MathUtil.clamp01(parseFloat(s[4])/100):1,i=n;break;case a.EventTypes.ANIMATION:case"6":n=new p.EventAnimation,n.layer=(0,g.convertToLayer)(s[1]),n.origin=(0,m.convertToOrigin)(s[2]),n.filepath=s[3].replaceAll('"',"").replaceAll("\\","/");let t=n.filepath.substring(0,n.filepath.lastIndexOf("."));for(let i of e.files.keys())i.startsWith(t)&&n.filepaths.push(i);n.filepaths.sort(((e,i)=>parseInt(e.substring(t.length,e.lastIndexOf(".")))-parseInt(i.substring(t.length,i.lastIndexOf("."))))),n.x=parseFloat(s[4]),n.y=parseFloat(s[5]),isNaN(n.x)&&(n.x=0),isNaN(n.y)&&(n.y=0),n.frameCount=parseInt(s[6]),n.frameDelay=parseFloat(s[7]),e.formatVersion<6&&(n.frameDelay=1.186*Math.round(.015*n.frameDelay)*(1e3/60)),n.loopType=s.length>8?(0,v.convertToLoopType)(s[8]):v.LoopType.LoopForever,console.log(n),i=n}n&&e.Events.Events.push(n)}))}static async LoadFiles(e,t){await new Promise((async i=>{let n=e.Events.Events.filter((e=>{if("filename"in e&&e.filename||"filepath"in e&&e.filepath)return e})),s=0,o=()=>{s!=n.length||i()};o();for(const i of n)for(let n in i)if("filename"==n||"filepath"==n){let a=e.files.get(i[n]);if(i instanceof p.EventAnimation&&(a=new Blob),a){let u=URL.createObjectURL(a);if(i instanceof r.EventBackground&&d.Assets.load({src:u,loadParser:"loadTextures"}).then((e=>{i.texture=e,s++,o()})).catch((e=>{console.warn(e),s++,o()})),i instanceof l.EventVideo){let t=!1;if(i[n].endsWith(".avi")){let s=this.aviTranscodedVideoCache.find((t=>{if(t.beatmapSID==e.Metadata.BeatmapSetID&&t.filePath==i[n])return t}));try{if(s)e.files.delete(i[n]),i[n]=i[n].substring(0,i[n].length-4)+".mp4",e.files.set(i[n],s.blob),URL.revokeObjectURL(u),u=URL.createObjectURL(s.blob);else{console.warn("AVI video is not natively supported! Transcoding to .mp4, this may take a few minutes!");let t=new c.FFmpeg;t.on("progress",(e=>{let{progress:t,time:i}=e;console.log(`.avi to .mp4 transcoding: ${Math.round(1e3*t)/10}% (transcoded time: ${Math.round(i/1e5)/10}s)`)})),console.log("FFmpeg initialized");let s=h.Loader.Get("workers.ffmpeg"),o=h.Loader.Get("ffmpeg.core"),r=h.Loader.Get("ffmpeg.wasm"),l=h.Loader.Get("ffmpeg.coreWorker");await t.load({classWorkerURL:URL.createObjectURL(s),coreURL:URL.createObjectURL(o),wasmURL:URL.createObjectURL(r),workerURL:URL.createObjectURL(l)}),console.log("FFmpeg loaded"),await t.writeFile("input.avi",new Uint8Array(await a.arrayBuffer())),console.log("Written file to FFmpeg's vfs"),await t.exec(["-i","input.avi","-c:v","libx264","-preset","ultrafast","-an","-movflags","faststart","output.mp4"]),console.log("Transcoding done");const d=await t.readFile("output.mp4");t.terminate(),console.log("FFmpeg terminated");let f=new Blob([d],{type:"video/mp4"});this.aviTranscodedVideoCache.push({beatmapSID:e.Metadata.BeatmapSetID,filePath:i[n],blob:f}),e.files.delete(i[n]),i[n]=i[n].substring(0,i[n].length-4)+".mp4",e.files.set(i[n],f),URL.revokeObjectURL(u),u=URL.createObjectURL(f),console.log("Successfully transcoded from .avi to .mp4!")}}catch(e){console.warn(e),t=!0}}t?(s++,o()):d.Assets.load({src:u,loadParser:"loadVideo"}).then((e=>{i.texture=e,i.texture&&(i.texture.source.resource.volume=0,i.texture.source.resource.pause()),s++,o()})).catch((e=>{console.warn(e),s++,o()}))}if(i instanceof f.EventSprite&&d.Assets.load({src:u,loadParser:"loadTextures"}).then((e=>{i.texture=e,s++,o()})).catch((e=>{console.warn(e),s++,o()})),i instanceof y.EventSample&&a.arrayBuffer().then((e=>{t.audioContext.decodeAudioData(e).then((e=>{i.audioBuffer=e,s++,o()})).catch((e=>{console.warn(e),s++,o()}))})),i instanceof p.EventAnimation){URL.revokeObjectURL(u);let t=0,n=i.filepaths.length,a=()=>{t==n&&(s++,o())};i.filepaths.forEach(((n,s)=>{let o=e.files.get(n);if(o){let e=URL.createObjectURL(o);d.Assets.load({src:e,loadParser:"loadTextures"}).then((e=>{i.textures[s]=e,t++,a()})).catch((e=>{console.warn(e),t++,a()}))}}))}}else console.warn("Could not find referenced file: "+i[n])}}))}}},81347:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.GeneralParser=void 0;const n=i(85932),s=i(9752);t.GeneralParser=class{static ParseGeneral(e,t){t.forEach((t=>{let i=t.split(":");i[1].startsWith(" ")&&(i[1]=i[1].substring(1,i[1].length)),"AudioFilename"!=i[0]?s.BeatmapParser.AutoParse(n.GeneralData,i,e.General):e.General.AudioFilename=i[1].replaceAll("\\","/")}))}static LoadFiles(e){e.General.AudioFilename&&(e.General.audioFile=e.files.get(e.General.AudioFilename))}}},98803:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MetadataParser=void 0;const n=i(9752),s=i(32007);t.MetadataParser=class{static ParseMetadata(e,t){t.forEach((t=>{let i=t.split(":");i[1].startsWith(" ")&&(i[1]=i[1].substring(1,i[1].length)),n.BeatmapParser.AutoParse(s.Metadata,i,e.Metadata)}))}}},30444:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.TimingPointsParser=void 0;const n=i(87816),s=i(3143),o=i(22331);t.TimingPointsParser=class{static ParseTimingPoints(e,t){t.forEach((t=>{let i,a=t.split(",");"1"==a[6]?(i=new n.UnInheritedTimingPoint,i.beatLength=Number.parseFloat(a[1]),i.meter=Number.parseInt(a[2])):(i=new s.InheritedTimingPoint,i.sliderVelocityMultiplier=Number.parseFloat(a[1])),i.time=Number.parseInt(a[0]),i.sampleSet=Number.parseInt(a[3]),i.sampleIndex=Number.parseInt(a[4]),i.volume=Number.parseInt(a[5]),"1"==a[7]||"3"==a[7]?i.effects=Number.parseInt(a[7]):i.effects=o.Effect.None,e.TimingPoints.TimingPoints.push(i)}))}}},5825:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.MathUtil=void 0;class i{static RadiansToDegrees(e){return 180*e/Math.PI}static DegreesToRadians(e){return e*Math.PI/180}static clamp(e,t,i){return Math.min(Math.max(i,e),t)}static clamp01(e){return i.clamp(0,1,e)}static Damp(e,t,n,s){return i.Lerp(e,t,1-Math.pow(n,s))}static Lerp(e,t,i){return e+(t-e)*i}}t.MathUtil=i},92915:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Ease=void 0;const a=o(i(29172));class r{static previousEases=[];easings=[];obj;delay=null;constructor(e,t){this.obj=e,t||r.previousEases.push(this)}static getEase(e,t){null==t&&(t=!1);let i=r.previousEases.filter((t=>t.obj==e));return i.length>0?i[0]:new r(e,t)}createTween(e,t,i,n,s,o){const r={value:0},u=new a.Tween(i?r:e),c=new l(u);return u.to(i?{value:1}:t,s),u.easing(o),u.onUpdate((()=>{this.obj.destroyed||(this.obj[n]=i?r.value*(t.value-e.value)+e.value:e),c.onUpdate()})),u.onStart((()=>{i&&(e.value=this.obj[n])})),null==this.delay?u.start():(this.delay.chain(u),this.delay=null),this.easings.push(c),u.onStop((()=>{this.onDone(u)})),u.onComplete((()=>{this.onDone(u)})),this}TransformTo(e,t,i){return this.createTween(this.obj.position,e,!1,"position",t,i),this}onDone(e){this.easings=this.easings.filter((t=>t.tween!=e))}ScaleTo(e,t,i){let n={x:0,y:0};return"number"==typeof e&&(n.x=e,n.y=e),this.createTween(this.obj.scale,n,!1,"scale",t,i),this}FadeTo(e,t,i){return this.createTween({value:this.obj.alpha},{value:e},!0,"alpha",t,i),this}FadeOut(e,t){return this.FadeTo(0,e,t),this}FadeIn(e,t){return this.FadeTo(1,e,t),this}ClearEasings(){return this.easings.forEach((e=>{e.tween.stop()})),this.easings=[],this}Then(e){let t=this.easings.sort(((e,t)=>e.tween.getDuration()-t.tween.getDuration()));return t.length>0&&(this.delay=t[0].tween,null!=e&&(t[0].tween.onComplete((()=>{this.onDone(t[0].tween),e()})),t[0].tween.onStop((()=>{this.onDone(t[0].tween),e()})))),this}OnEach(e){let t=this.easings.sort(((e,t)=>e.tween.getDuration()-t.tween.getDuration()));t.length>0&&t[0].registerOnUpdate(e)}}t.Ease=r;class l{tween;updateEventListeners=[];constructor(e){this.tween=e}onUpdate(){this.updateEventListeners.forEach((e=>{e()}))}registerOnUpdate(e){this.updateEventListeners.push(e)}unRegisterOnUpdate(e){this.updateEventListeners=this.updateEventListeners.filter((t=>!(e===t)))}}},94461:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.CenteredList=void 0;const n=i(70828),s=i(5168);class o extends n.List{get elementsMargin(){return super.elementsMargin}set elementsMargin(e){super.elementsMargin=e,s.UIUtils.centerPivotOfList(this)}ReCenter(){s.UIUtils.centerPivotOfList(this)}}t.CenteredList=o},5168:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.UIUtils=void 0;t.UIUtils=class{static centerPivotOfList(e){let t=e.leftPadding,i=e.topPadding;for(let n=0;n{const e=o.Settings.getSetting(a.Renderer).getValue().value;d.init({backgroundColor:"black",width:u,height:c,antialias:!0,preference:e,resolution:window.devicePixelRatio,autoDensity:!0}).then((()=>{new s.Main(d)}))},navigator.mediaSession.setActionHandler("play",(()=>{s.Main.AudioEngine.GetCurrentPlayingMusicNoSilent()?.Play()})),navigator.mediaSession.setActionHandler("pause",(()=>{s.Main.AudioEngine.GetCurrentPlayingMusicNoSilent()?.Pause()})),navigator.mediaSession.setActionHandler("stop",(()=>{})),navigator.mediaSession.setActionHandler("seekbackward",(()=>{})),navigator.mediaSession.setActionHandler("seekforward",(()=>{})),navigator.mediaSession.setActionHandler("seekto",(()=>{})),navigator.mediaSession.setActionHandler("previoustrack",(()=>{})),navigator.mediaSession.setActionHandler("nexttrack",(()=>{})),Object.defineProperty(window,"setSensitivity",{value:e=>{o.Settings.getSetting(r.MouseSensitivity).setValue(e)}}),Object.defineProperty(window,"setRenderer",{value:e=>{let t=o.Settings.getSetting(a.Renderer);t.setValue("webgl"==e?t.webglOption:t.webGpuOption),window.location.reload()}}),Object.defineProperty(window,"setUIScale",{value:e=>{o.Settings.getSetting(l.UIScale).setValue(e),window.location.reload()}})},20825:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Main=void 0;const a=o(i(58687)),r=i(76969),l=i(25373),u=i(12235),c=i(55686),d=i(85437),h=o(i(29172)),f=i(29847),g=i(53931),p=i(9752),m=i(17898);class v{static app;static mousePos={x:0,y:0};static pointerLockExitTime;static cursor;static AudioEngine;static currentScreen;static allScreens=[];static clickArea=new a.Graphics;static doPointerLock=!1;static settingsPane;static processingOsuFile=!1;constructor(e){v.app=e,v.setDropEvents(),document.body.appendChild(v.app.canvas),v.settingsPane=new f.SettingsPane,v.settingsPane.zIndex=999998,v.app.stage.addChild(v.settingsPane),document.addEventListener("keydown",(e=>{e.ctrlKey&&"KeyO"==e.code&&v.settingsPane.toggle()})),this.doResize(),window.addEventListener("resize",this.doResize),v.app.ticker.add((()=>{h.update()})),v.app.stage.eventMode="static",v.AudioEngine=new d.AudioEngine,v.app.stage.addEventListener("mousemove",(e=>{v.mousePos.x=e.clientX,v.mousePos.y=e.clientY,v.cursor&&v.cursor.updateMouse()})),document.addEventListener("pointerlockchange",this.pointerLockChanged,!1),v.switchScreen(new r.LoadScreen),u.Loader.Load(v.AudioEngine.audioContext).then((()=>{v.cursor=new c.MenuCursor(!1);let e=u.Loader.GetAudio("sample_dialog_ok"),t=u.Loader.Get("introTrianglesTrack");v.switchScreen(new l.InteractScreen(t,e))}))}static setDropEvents(){Object.defineProperty(window,"onDropEvent",{value:e=>{if(e.preventDefault(),v.processingOsuFile)alert("Another BeatMap is still processing. (Most likely transcoding a .avi file, check the console for progress) Please wait for it to process and start playing before processing another one!");else if(v.processingOsuFile=!0,e.dataTransfer.items){let t=[...e.dataTransfer.items][0];if("file"==t.kind){const e=t.getAsFile();(0,g.unzip)(e).then((e=>{let{entries:t}=e;for(const[e,i]of Object.entries(t))if(e.endsWith(".osu")){i.text().then((async e=>{let i,n=new m.BeatmapData;await new Promise((e=>{for(const[i,s]of Object.entries(t))s.blob().then((s=>{n.files.set(i,s),n.files.size==Object.entries(t).length&&e()}))}));for(const[e,t]of n.files.entries())e.endsWith(".osb")&&(i=await t.text());p.BeatmapParser.Parse(e,n,i),await p.BeatmapParser.LoadFiles(n,v.AudioEngine);let s=n.General.audioFile;if(s){let e=URL.createObjectURL(s);v.AudioEngine.PlayMusicImmediately(e,n,(()=>{console.log("Now playing "+n.Metadata.TitleUnicode+" - "+n.Metadata.ArtistUnicode+" ("+n.Metadata.Title+" - "+n.Metadata.Artist+")")}))}v.processingOsuFile=!1,console.log(n)}));break}}))}}}}),Object.defineProperty(window,"onDragEvent",{value:e=>{e.preventDefault()}}),v.app.canvas.setAttribute("ondrop","window.onDropEvent(event);"),v.app.canvas.setAttribute("ondragover","window.onDragEvent(event);")}static lockKeyboard(){navigator.keyboard&&navigator.keyboard.lock([]).then((()=>{console.log("Locked keyboard!"),document.fullscreenElement||console.warn("Keyboard lock won't work unless the user is in fullscreen (as requested by the game, not if the user just presses F11)!")}))}static pointerLock(){try{this.doPointerLock=!0,v.app.canvas.requestPointerLock({unadjustedMovement:!0})}catch(e){console.warn("Failed to lock cursor, error:",e),this.doPointerLock=!1}}static exitPointerLock(){this.doPointerLock=!1,v.app.canvas.exitPointerLock()}static switchScreen(e){null!=this.currentScreen&&(this.currentScreen.zIndex=1,this.currentScreen.onClose().then((e=>{for(let t=0;t{e.onResize()})),v.settingsPane.resize()}pointerLockChanged(){!document.pointerLockElement&&v.doPointerLock?(a.EventSystem.isPointerLocked=!1,v.pointerLockExitTime=Date.now(),v.clickArea=new a.Graphics,v.clickArea.rect(0,0,1,1),v.clickArea.fill("rgba(0,0,0,0.1)"),v.clickArea.width=window.innerWidth,v.clickArea.height=window.innerHeight,v.clickArea.position.set(0,0),v.app.stage.addChild(v.clickArea),v.clickArea.eventMode="static",v.clickArea.cursor="pointer",v.cursor.PopOut(),v.clickArea.zIndex=9999999,v.clickArea.onclick=()=>{Date.now()-v.pointerLockExitTime<1500||(v.clickArea.removeFromParent(),v.clickArea.destroy(),v.pointerLock(),v.cursor.PopIn())}):a.EventSystem.isPointerLocked=!0}}t.Main=v},11307:function(e,t,i){i.r(t)},58689:function(e,t,i){i.r(t),t.default="in vec2 vUV;\nin vec2 vPositionOffset;\nin vec2 vPosition;\nin vec4 vColorTint;\nuniform sampler2D uTexture;\nuniform float time;\n\nvoid main() {\n float a = ((vPositionOffset.y + vPosition.y)/1200.0) - 0.1;\n vec4 color = texture(uTexture, vUV);\n if (a > 1.0) {\n a = 1.0;\n }\n gl_FragColor = (color*vColorTint)*a;\n}"},46404:function(e,t,i){i.r(t),t.default="in vec2 aPosition;\nin vec2 aUV;\nin vec2 aPositionOffset;\nin vec4 aColorTint;\n\nout vec2 vUV;\nout vec2 vPositionOffset;\nout vec2 vPosition;\nout vec4 vColorTint;\n\nuniform mat3 uProjectionMatrix;\nuniform mat3 uWorldTransformMatrix;\nuniform mat3 uTransformMatrix;\n\n\nvoid main() {\n\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n gl_Position = vec4((mvp * vec3(aPosition + aPositionOffset, 1.0)).xy, 0.0, 1.0);\n vPositionOffset = aPositionOffset;\n vUV = aUV;\n vPosition = aPosition;\n vColorTint = aColorTint;\n}"},61630:function(e,t,i){i.r(t),t.default="struct GlobalUniforms {\n uProjectionMatrix:mat3x3,\n uWorldTransformMatrix:mat3x3,\n uWorldColorAlpha: vec4,\n uResolution: vec2,\n}\n\nstruct LocalUniforms {\n uTransformMatrix:mat3x3,\n uColor:vec4,\n uRound:f32,\n}\n\n\n@group(0) @binding(0) var globalUniforms : GlobalUniforms;\n@group(1) @binding(0) var localUniforms : LocalUniforms;\n\nstruct VertexOutput {\n @builtin(position) position: vec4,\n @location(0) vUV: vec2,\n @location(1) vPositionOffset: vec2,\n @location(2) vPosition: vec2,\n @location(3) vColorTint: vec4\n};\n\n\n@vertex\nfn mainVert(\n @location(0) aPosition : vec2,\n @location(1) aUV : vec2,\n @location(2) aColorTint : vec4,\n @location(3) aPositionOffset : vec2,\n) -> VertexOutput {\n var mvp = globalUniforms.uProjectionMatrix\n * globalUniforms.uWorldTransformMatrix\n * localUniforms.uTransformMatrix;\n\n var output: VertexOutput;\n\n output.position = vec4(mvp * vec3(aPosition+aPositionOffset, 1.0), 1.0);\n output.vUV = aUV;\n output.vPosition = aPosition;\n output.vPositionOffset = aPositionOffset;\n output.vColorTint = aColorTint;\n\n return output;\n};\n\nstruct WaveUniforms {\n time:f32,\n}\n\n@group(2) @binding(1) var uTexture : texture_2d;\n@group(2) @binding(2) var uSampler : sampler;\n@group(2) @binding(3) var waveUniforms : WaveUniforms;\n\n@fragment\nfn mainFrag(\n @location(0) vUV: vec2,\n @location(1) vPositionOffset: vec2,\n @location(2) vPosition: vec2,\n @location(3) vColorTint: vec4\n) -> @location(0) vec4 {\n var a: f32 = ((vPositionOffset.y + vPosition.y)/1200.0) - 0.1;\n let color: vec4 = textureSample(uTexture, uSampler, vUV);\n if (a > 1.0){\n a = 1.0;\n }\n return (color*vColorTint)*a;\n};"},44160:function(e,t,i){i.r(t),t.default="in vec4 vColor;\nin vec2 vUV;\n\nuniform sampler2D uTexture;\nuniform float progress;\n\nvoid main() {\n vec4 color = texture2D(uTexture, vUV);\n float a = vColor.a * color.a;\n vec4 _vColor = vec4(smoothstep(0.88, 1.0, color.a))*vColor;\n vec4 outColor = (color.r < progress) ? vec4(_vColor.rgb * a, a) : vec4(0.0);\n gl_FragColor = outColor;\n}\n"},26045:function(e,t,i){i.r(t),t.default="in vec2 aPosition;\nin vec4 aColor;\nin vec2 aUV;\n\nout vec4 vColor;\nout vec2 vUV;\n\nuniform mat3 uProjectionMatrix;\nuniform mat3 uWorldTransformMatrix;\n\nuniform mat3 uTransformMatrix;\n\n\nvoid main() {\n\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n gl_Position = vec4((mvp * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\n\n vColor = aColor;\n vUV = aUV;\n}\n"},46110:function(e,t,i){i.r(t),t.default="struct GlobalUniforms {\n uProjectionMatrix:mat3x3,\n uWorldTransformMatrix:mat3x3,\n uWorldColorAlpha: vec4,\n uResolution: vec2,\n}\n\nstruct LocalUniforms {\n uTransformMatrix:mat3x3,\n uColor:vec4,\n uRound:f32,\n}\n\n\n@group(0) @binding(0) var globalUniforms : GlobalUniforms;\n@group(1) @binding(0) var localUniforms : LocalUniforms;\n\nstruct VertexOutput {\n @builtin(position) position: vec4,\n @location(0) vUV: vec2,\n @location(1) vColor: vec4,\n};\n\n\n@vertex\nfn mainVert(@location(0) aPosition : vec2, @location(1) aUV : vec2, @location(2) aColor: vec4\n) -> VertexOutput {\n var mvp = globalUniforms.uProjectionMatrix\n * globalUniforms.uWorldTransformMatrix\n * localUniforms.uTransformMatrix;\n\n var output: VertexOutput;\n\n output.position = vec4(mvp * vec3(aPosition, 1.0), 1.0);\n output.vUV = aUV;\n output.vColor = aColor;\n\n return output;\n};\n\nstruct ProgressUniform {\n progress:f32\n}\n\n@group(2) @binding(1) var uTexture : texture_2d;\n@group(2) @binding(2) var uSampler : sampler;\n@group(2) @binding(3) var uProgress : ProgressUniform;\n\n@fragment\nfn mainFrag(@location(0) vUV: vec2, @location(1) vColor: vec4) -> @location(0) vec4 {\n let color: vec4 = textureSample(uTexture, uSampler, vUV);\n let a: f32 = color.a;\n let _vColor: vec4 = smoothstep(0.88, 1.0, color.a) * vColor;\n var outColor: vec4 = vec4(0.0);\n if (color.r < uProgress.progress) {\n outColor = vec4(_vColor.rgb * a, a);\n }\n return outColor;\n};\n"}},i={};function n(e){var s=i[e];if(void 0!==s)return s.exports;var o=i[e]={id:e,loaded:!1,exports:{}};return t[e].call(o.exports,o,o.exports,n),o.loaded=!0,o.exports}n.m=t,e=[],n.O=function(t,i,s,o){if(!i){var a=1/0;for(c=0;c=o)&&Object.keys(n.O).every((function(e){return n.O[e](i[l])}))?i.splice(l--,1):(r=!1,o0&&e[c-1][2]>o;c--)e[c]=e[c-1];e[c]=[i,s,o]},n.d=function(e,t){for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.hmd=function(e){return(e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},function(){var e={179:0};n.O.j=function(t){return 0===e[t]};var t=function(t,i){var s,o,a=i[0],r=i[1],l=i[2],u=0;if(a.some((function(t){return 0!==e[t]}))){for(s in r)n.o(r,s)&&(n.m[s]=r[s]);if(l)var c=l(n)}for(t&&t(i);u 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","import {BeatmapData} from \"../Util/Beatmap/Data/BeatmapData\";\nimport {Main} from \"../main\";\nimport {EventTypes} from \"../Util/Beatmap/Data/Sections/Events/EventTypes\";\nimport {EventVideo} from \"../Util/Beatmap/Data/Sections/Events/EventVideo\";\n\nexport class Audio {\n public audio!: AudioBuffer;\n public source?: AudioBufferSourceNode;\n public mediaSource?: MediaElementAudioSourceNode;\n public mediaAudioElement!: HTMLAudioElement;\n public id!: number;\n public get isPaused() {\n return this._useMediaSource ? this.mediaAudioElement.paused : false;\n }\n public get isPlaying() {\n return this._useMediaSource ? !this.mediaAudioElement.paused : true;\n }\n public nodes: AudioNode[] = [];\n public tempArrayMain = new Float32Array(256);\n public tempArrayL = new Float32Array(64);\n public tempArrayR = new Float32Array(64);\n public LeftChannel: number = 0;\n public RightChannel: number = 0;\n public FrequencyAmplitudes = new Float32Array(256);\n protected _connectedToContext = false;\n protected _useMediaSource = false;\n protected _onEndCallback?: () => void;\n public timeStarted = 0; // only for silent audio when real music is paused\n protected paused = false; // used to check if music was paused outside of Audio class (i.e. pressing stop media button on the keyboard)\n public beatmap!: BeatmapData;\n\n public GetMaximumAudioLevel() {\n return Math.max(this.LeftChannel, this.RightChannel);\n }\n\n public GetAverageAudioLevel() {\n return (this.LeftChannel + this.RightChannel) / 2;\n }\n\n public Create(audioContext: AudioContext, useMediaSource?: boolean) {\n this._useMediaSource = useMediaSource ? useMediaSource : false;\n if (!useMediaSource) {\n this.source = audioContext.createBufferSource();\n this.source.buffer = this.audio;\n }\n else {\n if (!this.mediaAudioElement) {\n throw new Error(\"HTML Audio Element was not initialized!\")\n }\n this.mediaSource = audioContext.createMediaElementSource(this.mediaAudioElement);\n this.mediaAudioElement.onpause = () => {\n if (!this.paused && !this.mediaAudioElement.ended) { // check if music was paused outside of Audio class\n this.Play();\n }\n }\n }\n }\n\n public AddAudioNode(node: AudioNode) {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n this.nodes.push(node);\n }\n\n public GetNode(type: new (...args: any[]) => T): T[] | null {\n let nodes = this.nodes.filter(node => node instanceof type) as T[];\n if (nodes.length > 0) {\n return nodes;\n } else {\n return null;\n }\n }\n\n public ConnectToContext(audioContext: AudioContext, howToConnectFunction?: (nodes: AudioNode[], source: AudioBufferSourceNode | MediaElementAudioSourceNode) => void) {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (this._connectedToContext) {\n return;\n }\n this._connectedToContext = true;\n if (this.nodes.length > 0) {\n if (howToConnectFunction) {\n howToConnectFunction(this.nodes, (!this._useMediaSource ? this.source : this.mediaSource)!);\n } else {\n this.nodes.forEach((node, index) => {\n this.source!.connect(node);\n if (!(node instanceof AnalyserNode)) {\n node.connect(audioContext.destination);\n }\n });\n }\n } else {\n if (!this._useMediaSource) {\n this.source!.connect(audioContext.destination);\n }\n else {\n this.mediaSource!.connect(audioContext.destination);\n }\n }\n }\n\n public Play() {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n this.paused = false;\n if (!this._useMediaSource) {\n this.source!.start();\n }\n else {\n this.mediaAudioElement!.play();\n let backgroundVideo = this.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n if (backgroundVideo.texture.source.resource.startPromise) {\n backgroundVideo.texture.source.resource.startPromise.then(() => {\n let video = backgroundVideo.texture!.source.resource as HTMLVideoElement;\n video.play();\n });\n }\n }\n }\n }\n }\n\n public Pause() {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n if (!this._useMediaSource) {\n throw new Error(\"Pause is not supported on AudioSourceBuffer!\");\n }\n this.paused = true;\n this.mediaAudioElement!.pause();\n let backgroundVideo = this.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n if (backgroundVideo.texture.source.resource.startPromise) {\n backgroundVideo.texture.source.resource.startPromise.then(() => {\n let video = backgroundVideo.texture!.source.resource as HTMLVideoElement;\n video.pause();\n });\n }\n }\n }\n }\n\n public Stop() {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n this.paused = true;\n if (!this._useMediaSource) {\n this.source!.stop();\n }\n else {\n this.mediaAudioElement!.pause();\n if (this._onEndCallback) {\n this._onEndCallback();\n }\n let backgroundVideo = this.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n if (backgroundVideo.texture.source.resource.startPromise) {\n backgroundVideo.texture.source.resource.startPromise.then(() => {\n let video = backgroundVideo.texture!.source.resource as HTMLVideoElement;\n video.pause();\n });\n }\n }\n }\n }\n }\n\n public SetTime(timeMS: number) {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n if (!this._useMediaSource) {\n throw new Error(\"SetTime is not supported on AudioSourceBuffer!\");\n }\n this.mediaAudioElement.currentTime = timeMS/1000;\n let backgroundVideo = this.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n if (backgroundVideo.texture.source.resource.startPromise) {\n backgroundVideo.texture.source.resource.startPromise.then(() => {\n let video = backgroundVideo.texture!.source.resource as HTMLVideoElement;\n let time = timeMS/1000;\n time += backgroundVideo.startTime;\n if (time < 0) {\n video.currentTime = 0;\n video.pause();\n backgroundVideo.texture!.source.resource.startPromise = new Promise((resolve) => {\n setTimeout(() => {\n video.play();\n }, Math.abs(time));\n });\n } else {\n video.currentTime = time;\n }\n\n });\n }\n }\n }\n }\n\n public GetDuration() {\n return (!this._useMediaSource ? this.audio.duration : this.mediaAudioElement.duration * 1000)\n }\n\n public GetCurrentTime() {\n return this._useMediaSource ? this.mediaAudioElement.currentTime * 1000 : (this.timeStarted != 0 ? Date.now() - this.timeStarted : 0);\n }\n\n public RegisterEndCallBack(callback: () => void) {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n this._onEndCallback = callback;\n if (!this._useMediaSource) {\n this.source!.onended = () => {\n if (!this.isPaused) {\n this.paused = true;\n callback();\n }\n }\n }\n else {\n this.mediaAudioElement.onended = () => {\n this.paused = true;\n callback();\n }\n }\n }\n\n}\n\nexport class MapAudio extends Audio {\n public fadingOut: boolean = false;\n // @ts-ignore\n public fadeOutTimeout!: Timeout\n public playingCallback?: () => void;\n\n public FadeOut() {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n if (!this._useMediaSource) {\n throw new Error(\"FadeOut is not supported on AudioSourceBuffer!\");\n }\n if (this.fadingOut) {\n return;\n }\n this.fadingOut = true;\n clearTimeout(this.fadeOutTimeout);\n let gainNodes = this.GetNode(GainNode);\n if (gainNodes == null) {\n throw new Error(\"Gain Node doesn't exist on Audio Object!\");\n }\n let gain = gainNodes[0];\n gain.gain.linearRampToValueAtTime(0, Main.AudioEngine.audioContext.currentTime + 1)\n setTimeout(() => {\n this.Stop();\n }, 1000);\n }\n}\n","import {PlayingAudios} from \"./PlayingAudios\";\nimport {Audio, MapAudio} from \"./Audio\";\nimport {BeatmapData} from \"../Util/Beatmap/Data/BeatmapData\";\nimport {Main} from \"../main\";\nimport {UnInheritedTimingPoint} from \"../Util/Beatmap/Data/Sections/TimingPoints/UnInheritedTimingPoint\";\nimport {Effect} from \"../Util/Beatmap/Data/Sections/TimingPoints/Effect\";\n\nexport class AudioEngine {\n public readonly audioContext: AudioContext;\n private readonly _playingAudios: PlayingAudios;\n private _musicQueue: MapAudio[] = [];\n private _audioIdTicker: number = 0;\n private _changeCallbacks: ((mapAudio: MapAudio) => void)[] = [];\n private silentMusic = this.createSilentMusic();\n public useSilentMusic = true;\n\n public constructor() {\n this.audioContext = new AudioContext();\n this._playingAudios = new PlayingAudios();\n Main.app.ticker.add(() => {\n this.update();\n });\n }\n\n public UpdateMusicQueue() {\n if (this._musicQueue[0]) {\n if (!this._musicQueue[0].fadingOut && this._musicQueue[0].GetCurrentTime() == 0) {\n this._play(this._musicQueue[0]);\n this._changeCallbacks.forEach((cb) => cb(this._musicQueue[0]));\n }\n if (this._musicQueue[0].fadingOut && this._musicQueue[1]) {\n if (this._musicQueue[1]) {\n this._play(this._musicQueue[1]);\n this._changeCallbacks.forEach((cb) => cb(this._musicQueue[1]));\n }\n }\n }\n if (!(this._musicQueue.length >= 1)) {\n this.silentMusic = this.createSilentMusic();\n this.useSilentMusic = true;\n }\n else {\n this.useSilentMusic = false;\n }\n }\n\n public createSilentMusic() {\n let mapAudio = new MapAudio();\n mapAudio.timeStarted = Date.now();\n mapAudio.beatmap = new BeatmapData();\n let timingPoint = new UnInheritedTimingPoint();\n timingPoint.time = 0;\n timingPoint.beatLength = 1000;\n timingPoint.effects = Effect.None;\n mapAudio.beatmap.TimingPoints.TimingPoints.push(timingPoint);\n return mapAudio;\n }\n\n public addMusicChangeEventListener(cb: (() => void) | ((mapAudio: MapAudio) => void)) {\n this._changeCallbacks.push(cb);\n }\n\n public removeMusicChangeEventListener(cb: (() => void) | ((mapAudio: MapAudio) => void)) {\n this._changeCallbacks = this._changeCallbacks.filter(callback => callback != cb);\n }\n\n public GetCurrentPlayingMusic(): MapAudio {\n return this.useSilentMusic ? this.silentMusic : this._musicQueue[0];\n }\n\n public GetCurrentPlayingMusicNoSilent(): MapAudio {\n return this._musicQueue[0];\n }\n\n public PlayEffect(audio: AudioBuffer, pitch?: number) {\n let audioObj = new Audio();\n audioObj.audio = audio;\n audioObj.id = this._audioIdTicker;\n this._play(audioObj, pitch);\n this._audioIdTicker++;\n }\n\n public AddToMusicQueue(mapAudio: string, beatMapData: BeatmapData, musicPlayingCallback?: () => void) {\n let mapAudioObj = new MapAudio();\n mapAudioObj.mediaAudioElement = document.createElement(\"audio\");\n mapAudioObj.mediaAudioElement.src = mapAudio;\n mapAudioObj.beatmap = beatMapData;\n mapAudioObj.id = this._audioIdTicker;\n if (musicPlayingCallback) {\n mapAudioObj.playingCallback = musicPlayingCallback;\n }\n this._musicQueue.push(mapAudioObj);\n this._audioIdTicker++;\n this.UpdateMusicQueue();\n return mapAudioObj.id;\n }\n\n public PlayMusicImmediately(mapAudio: string, beatMapData: BeatmapData, musicPlayingCallback?: () => void) {\n let currentPlaying = this.GetCurrentPlayingMusicNoSilent();\n this._musicQueue = [];\n if (currentPlaying) {\n currentPlaying.FadeOut();\n }\n this.AddToMusicQueue(mapAudio, beatMapData, musicPlayingCallback);\n }\n\n public update() {\n let currentPlaying = this.GetCurrentPlayingMusic();\n let currentPlayingNoSilent = this.GetCurrentPlayingMusicNoSilent();\n if (!currentPlayingNoSilent)\n return;\n if (currentPlayingNoSilent.isPaused) {\n this.useSilentMusic = true;\n return;\n }\n else if (this.useSilentMusic) {\n this.useSilentMusic = false;\n currentPlaying = this.GetCurrentPlayingMusic();\n }\n if (!this.useSilentMusic) {\n if (!currentPlaying.fadingOut) {\n if (currentPlaying.GetDuration() - currentPlaying.GetCurrentTime() <= 1000){\n currentPlaying.FadeOut();\n }\n }\n let analyzerMain = currentPlaying.GetNode(AnalyserNode)![0];\n let analyzerL = currentPlaying.GetNode(AnalyserNode)![1];\n let analyzerR = currentPlaying.GetNode(AnalyserNode)![2];\n\n analyzerMain.getFloatFrequencyData(currentPlaying.tempArrayMain);\n for (let i = 0; i < currentPlaying.FrequencyAmplitudes.length; i++) {\n currentPlaying.tempArrayMain[i] += 140;\n currentPlaying.tempArrayMain[i] /= 340;\n if (i < 3) {\n currentPlaying.tempArrayMain[i] *= (12 * currentPlaying.tempArrayMain[i]);\n } else if (i < 6) {\n currentPlaying.tempArrayMain[i] *= (9 * currentPlaying.tempArrayMain[i]);\n } else if (i < 100) {\n currentPlaying.tempArrayMain[i] *= (6 * currentPlaying.tempArrayMain[i]);\n }\n currentPlaying.tempArrayMain[i] /= 2;\n if (currentPlaying.tempArrayMain[i] == Infinity || currentPlaying.tempArrayMain[i] == -Infinity) {\n currentPlaying.FrequencyAmplitudes[i] = 0;\n }\n else {\n currentPlaying.FrequencyAmplitudes[i] = currentPlaying.tempArrayMain[i];\n }\n }\n\n analyzerL.getFloatTimeDomainData(currentPlaying.tempArrayL);\n analyzerR.getFloatTimeDomainData(currentPlaying.tempArrayR);\n let avgL = 0;\n let avgR = 0;\n currentPlaying.tempArrayL.forEach((value) => {\n avgL += (value + 1)/2;\n });\n currentPlaying.tempArrayR.forEach((value) => {\n avgR += (value + 1)/2;\n });\n avgL /= currentPlaying.tempArrayL.length;\n avgR /= currentPlaying.tempArrayR.length;\n currentPlaying.LeftChannel = avgL;\n currentPlaying.RightChannel = avgR;\n }\n }\n\n private _play(audio: Audio | MapAudio, pitch?: number) {\n // check if audio is type of MapAudio\n if (audio instanceof MapAudio) {\n audio.Create(this.audioContext, true);\n let gain = this.audioContext.createGain();\n gain.gain.value = 0;\n let analyzer = this.audioContext.createAnalyser();\n analyzer.fftSize = 512;\n analyzer.smoothingTimeConstant = 0;\n let splitter = this.audioContext.createChannelSplitter(2);\n let analyzerL = this.audioContext.createAnalyser();\n analyzerL.smoothingTimeConstant = 0;\n analyzerL.fftSize = 128;\n let analyzerR = this.audioContext.createAnalyser();\n analyzerR.smoothingTimeConstant = 0;\n analyzerR.fftSize = 128;\n audio.AddAudioNode(gain);\n audio.AddAudioNode(analyzer);\n audio.AddAudioNode(analyzerL);\n audio.AddAudioNode(analyzerR);\n audio.ConnectToContext(this.audioContext, (nodes, source) => {\n source.connect(gain);\n gain.connect(this.audioContext.destination);\n source.connect(analyzer);\n source.connect(splitter);\n splitter.connect(analyzerL, 0);\n splitter.connect(analyzerR, 1);\n });\n audio.Play();\n this._playingAudios.audios.push(audio);\n if (audio.playingCallback) {\n audio.playingCallback();\n }\n gain.gain.linearRampToValueAtTime(1, this.audioContext.currentTime + 0.5);\n\n } else {\n audio.Create(this.audioContext, false);\n audio.ConnectToContext(this.audioContext);\n if (pitch) {\n if (audio.source) {\n audio.source.playbackRate.value = pitch;\n }\n }\n audio.Play();\n this._playingAudios.audios.push(audio);\n }\n\n\n audio.RegisterEndCallBack(() => {\n if (audio instanceof MapAudio) {\n if (this._musicQueue[0] == audio) {\n this._musicQueue.splice(0, 1);\n }\n this.UpdateMusicQueue();\n }\n this._playingAudios.audios.forEach((audioInArr, index) => {\n if (audioInArr === audio) {\n this._playingAudios.audios.splice(index, 1);\n return;\n }\n });\n });\n }\n\n}\n","import {Audio, MapAudio} from \"./Audio\";\n\nexport class PlayingAudios {\n public audios: (Audio | MapAudio)[] = [];\n}\n","import {Main} from \"../../main\";\nimport {MapAudio} from \"../../Audio/Audio\";\nimport * as PIXI from \"pixi.js\";\nimport {MathUtil} from \"../../Util/MathUtil\";\nimport {Effect} from \"../../Util/Beatmap/Data/Sections/TimingPoints/Effect\";\nimport {UnInheritedTimingPoint} from \"../../Util/Beatmap/Data/Sections/TimingPoints/UnInheritedTimingPoint\";\n\nexport class LogoVisualizer extends PIXI.Container {\n\n public static readonly size = 900;\n public frequencyAmplitudes: Float32Array = new Float32Array(256);\n protected audio!: MapAudio;\n protected temporalAmplitudes: Float32Array = new Float32Array(256);\n protected graphics: PIXI.Graphics = new PIXI.Graphics();\n // The number of bars to jump each update iteration.\n private readonly index_change = 5;\n // The maximum length of each bar in the visualiser. Will be reduced when kiai is not activated.\n private readonly bar_length = 600;\n // The number of bars in one rotation of the visualiser.\n private bars_per_visualiser = 200;\n // How many times we should stretch around the circumference (overlapping overselves).\n private readonly visualiser_rounds = 5;\n // How much should each bar go down each millisecond (based on a full bar).\n private readonly decay_per_millisecond = 0.0024;\n // Number of milliseconds between each amplitude update.\n private readonly time_between_updates = 50;\n // The minimum amplitude to show a bar.\n private readonly amplitude_dead_zone = 1 / this.bar_length;\n private indexOffset = 0;\n private firstDraw = true;\n\n public set alpha(number: number) {\n super.alpha = number * 0.2;\n }\n public get alpha() {\n return super.alpha * 5;\n }\n\n public constructor() {\n super();\n this.alpha = 1;\n }\n\n public start() {\n this.graphics.blendMode = \"add\";\n this.addChild(this.graphics);\n this.graphics.eventMode = \"none\";\n this.eventMode = \"none\";\n setInterval(() => {\n this.updateAmplitudes()\n }, this.time_between_updates);\n\n }\n\n public draw(ticker: PIXI.Ticker) {\n if (this.firstDraw) {\n for (let i = 0; i < this.frequencyAmplitudes.length; i++) {\n this.frequencyAmplitudes[i] = 0;\n }\n }\n this.graphics.clear();\n let decayFactor = ticker.deltaMS * this.decay_per_millisecond;\n for (let i = 0; i < this.bars_per_visualiser; i++) {\n //3% of extra bar length to make it a little faster when bar is almost at it's minimum\n this.frequencyAmplitudes[i] -= decayFactor * (this.frequencyAmplitudes[i] + 0.03);\n if (this.frequencyAmplitudes[i] < 0) {\n this.frequencyAmplitudes[i] = 0;\n }\n }\n\n for (let j = 0; j < this.visualiser_rounds; j++) {\n for (let i = 0; i < this.bars_per_visualiser; i++) {\n if (this.frequencyAmplitudes[i] < this.amplitude_dead_zone) {\n continue;\n }\n\n let rotation = MathUtil.DegreesToRadians(i / this.bars_per_visualiser * 360 + j * 360 / this.visualiser_rounds);\n let rotationCos = Math.cos(rotation);\n let rotationSin = Math.sin(rotation);\n // taking the cos and sin to the 0..1 range\n let barPosition = {\n x: (rotationCos / 2 + 0.5) * LogoVisualizer.size,\n y: (rotationSin / 2 + 0.5) * LogoVisualizer.size\n };\n\n let barSize = {\n x: LogoVisualizer.size * Math.sqrt(2 * (1 - Math.cos(MathUtil.DegreesToRadians(360 / this.bars_per_visualiser)))) / 2,\n y: this.bar_length * this.frequencyAmplitudes[i]\n };\n // The distance between the bottom side of the bar and the top side.\n let amplitudeOffset = {x: rotationCos * barSize.y, y: rotationSin * barSize.y};\n\n this.graphics.moveTo(barPosition.x, barPosition.y);\n this.graphics.lineTo(barPosition.x + amplitudeOffset.x, barPosition.y + amplitudeOffset.y);\n this.graphics.stroke({color: \"rgb(255, 255, 255)\", width: 14});\n }\n }\n this.firstDraw = false;\n }\n\n private updateAmplitudes() {\n this.audio = Main.AudioEngine.GetCurrentPlayingMusic();\n for (let i = 0; i < this.audio.FrequencyAmplitudes.length; i++) {\n this.temporalAmplitudes[i] = this.audio.FrequencyAmplitudes[i];\n }\n let audioTime = this.audio.GetCurrentTime();\n let timingPoint = this.audio.beatmap.TimingPoints.GetCurrentTimingPoints(audioTime)[0];\n for (let i = 0; i < this.bars_per_visualiser; i++) {\n let targetAmplitude = (this.temporalAmplitudes[(i + this.indexOffset) % this.bars_per_visualiser]) *\n (timingPoint.effects == Effect.KiaiTime ? 1 : 0.5);\n if (targetAmplitude > this.frequencyAmplitudes[i]) {\n this.frequencyAmplitudes[i] = targetAmplitude;\n }\n }\n this.indexOffset = (this.indexOffset + this.index_change) % this.bars_per_visualiser;\n }\n}\n","import {LogoVisualizer} from \"../LogoVisualizer\";\nimport * as PIXI from \"pixi.js\";\n\nexport class MenuLogoVisualizer extends LogoVisualizer {\n\n\n public draw(ticker: PIXI.Ticker) {\n super.draw(ticker);\n\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\n\nexport class LoadAnim extends PIXI.Container {\n private readonly bg: PIXI.Graphics;\n private readonly arc: PIXI.Graphics;\n private readonly arcContainer: PIXI.Container;\n private readonly animInterval: NodeJS.Timeout;\n private readonly container: PIXI.Container;\n private readonly bgContainer: PIXI.Container;\n private bgRotation: number = 0;\n\n public constructor(bgColor: string, arcColor: string) {\n super();\n this.pivot.set(0.5, 0.5);\n this.container = new PIXI.Container();\n this.container.alpha = 0;\n this.rotation = Math.PI * 2.5;\n this.bgContainer = new PIXI.Container();\n this.bg = new PIXI.Graphics();\n this.bg.roundRect(-50, -50, 100, 100, 25);\n this.bg.fill(bgColor);\n this.arcContainer = new PIXI.Container();\n this.arc = new PIXI.Graphics();\n this.arc.arc(0, 0, 27, Math.PI + .26, 2.92 * Math.PI);\n this.arc.stroke({\n width: 8,\n color: arcColor,\n cap: \"round\"\n });\n this.arc.scale.set(-1, 1);\n this.container.scale.set(0.5, 0.5);\n this.bgContainer.addChild(this.bg);\n this.arcContainer.addChild(this.arc);\n this.bgContainer.addChild(this.arcContainer);\n this.container.addChild(this.bgContainer);\n this.addChild(this.container);\n Ease.getEase(this.container).ScaleTo(1, 400, TWEEN.Easing.Quadratic.InOut)\n .FadeIn(400, TWEEN.Easing.Quadratic.InOut)\n this.doAnims();\n\n this.animInterval = setInterval(() => {\n this.doAnims();\n }, 800);\n }\n\n public doAnims() {\n this.bgRotation += 90;\n Ease.getEase(this.bgContainer).createTween({value: this.bgContainer.angle},\n {value: this.bgRotation}, true, \"angle\", 600, TWEEN.Easing.Quadratic.InOut);\n }\n\n public getWidth() {\n return 100 * this.scale.x;\n }\n\n public getHeight() {\n return 100 * this.scale.y;\n }\n\n public draw(deltaTime: PIXI.Ticker) {\n this.arcContainer.angle += (3 * deltaTime.deltaTime);\n }\n\n public destroy(_options?: PIXI.DestroyOptions | boolean) {\n Ease.getEase(this.container).FadeOut(400, TWEEN.Easing.Quadratic.InOut)\n .ScaleTo(0.5, 400, TWEEN.Easing.Quadratic.InOut);\n setTimeout(() => {\n clearInterval(this.animInterval);\n super.destroy(_options);\n }, 400);\n }\n\n}\n","import * as PIXI from \"pixi.js\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../../../Util/TweenWrapper/Ease\";\nimport {OsuLogo} from \"../OsuLogo\";\nimport {Screen} from \"../../../../Screens/Screen\";\nimport {LogoTrackingContainer} from \"./LogoTrackingContainer\";\n\nexport class ButtonSystem extends PIXI.Container {\n\n private menuBG = new PIXI.Graphics();\n private isOpened = false;\n private logo: OsuLogo;\n private state = ButtonSystemState.Initial;\n private logoTrackingContainer = new LogoTrackingContainer();\n private readonly menuHeight = 150;\n\n private get State() {\n return this.state;\n }\n\n private set State(state: ButtonSystemState) {\n if (this.state == state) return;\n\n const lastState = this.state;\n this.state = state;\n\n this.updateLogoState(lastState);\n\n console.log(`${this.constructor.name}'s state changed from ${lastState} to ${state}`)\n }\n\n private updateLogoState(lastState = ButtonSystemState.Initial) {\n switch (this.state) {\n case ButtonSystemState.Exit:\n case ButtonSystemState.Initial:\n this.Close();\n break;\n case ButtonSystemState.TopLevel:\n case ButtonSystemState.Play:\n switch (lastState) {\n case ButtonSystemState.TopLevel: // coming from toplevel to play\n break;\n\n case ButtonSystemState.Initial:\n this.Open();\n Ease.getEase(this.logo).ClearEasings().ScaleTo(Screen.getScaleBasedOffScreenSize() * 0.5, 200, TWEEN.Easing.Linear.In);\n break;\n\n default:\n this.Open();\n Ease.getEase(this.logo).ClearEasings().ScaleTo(Screen.getScaleBasedOffScreenSize() * 0.5, 200, TWEEN.Easing.Quintic.Out);\n break;\n }\n break;\n }\n }\n\n public constructor(logo: OsuLogo) {\n super();\n this.logo = logo;\n this.drawMenuBG();\n this.scale.y = 0;\n this.alpha = 0;\n this.addChild(this.menuBG);\n this.addChild(this.logoTrackingContainer);\n this.logo.Action = () => {return this.onOsuLogo();};\n }\n\n private drawMenuBG() {\n this.menuBG.rect(0, Screen.getScaleBasedOffScreenSize() * -(this.menuHeight/2), 1, Screen.getScaleBasedOffScreenSize() * this.menuHeight);\n this.menuBG.fill({color: \"rgb(50,50,50)\"});\n }\n\n private onOsuLogo(): boolean {\n switch (this.state) {\n default:\n return false;\n\n case ButtonSystemState.Initial:\n this.State = ButtonSystemState.TopLevel;\n return true;\n\n case ButtonSystemState.TopLevel:\n\n return false;\n\n case ButtonSystemState.Play:\n\n return false;\n\n case ButtonSystemState.Edit:\n\n return false;\n }\n }\n\n private Open() {\n setTimeout(() => {\n this.isOpened = true;\n Ease.getEase(this).ScaleTo(1, 400, TWEEN.Easing.Quintic.Out)\n .FadeIn(400, TWEEN.Easing.Quintic.Out);\n }, 150);\n }\n\n private Close() {\n this.isOpened = false;\n Ease.getEase(this).ClearEasings().ScaleTo({x: 1, y: 0}, 300, TWEEN.Easing.Sinusoidal.In)\n .FadeOut(300, TWEEN.Easing.Sinusoidal.In);\n }\n\n public isOpen() {\n return this.isOpened;\n }\n\n public onResize() {\n this.menuBG.clear();\n this.drawMenuBG();\n this.position.set(0, window.innerHeight/2);\n this.menuBG.width = window.innerWidth;\n }\n}\n\nenum ButtonSystemState {\n Exit = \"Exit\",\n Initial = \"Initial\",\n TopLevel = \"TopLevel\",\n Play = \"Play\",\n Edit = \"Edit\",\n EnteringMode = \"EnteringMode\",\n}\n","import * as PIXI from \"pixi.js\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {OsuLogo} from \"../OsuLogo\";\n\nexport class LogoTrackingContainer extends PIXI.Container {\n protected Logo: OsuLogo | null = null;\n\n private easing!: (amount: number) => number;\n private startPosition: {x: number, y: number} | null = null;\n private startTime: number | null = null;\n private duration!: number;\n\n private readonly visual_box_size = 72;\n\n public StartTracking(logo: OsuLogo, duration: number = 0, easing: (amount: number) => number = TWEEN.Easing.Linear.None) {\n if (logo.IsTracking && this.Logo == null)\n throw new Error(\"Cannot track an instance of OsuLogo to multiple LogoTrackingContainers\");\n\n if (this.Logo != logo && this.Logo != null)\n {\n // If we're replacing the logo to be tracked, the old one no longer has a tracking container\n this.Logo.IsTracking = false;\n }\n\n this.Logo = logo;\n this.Logo.IsTracking = true;\n\n this.duration = duration;\n this.easing = easing;\n\n this.startTime = null;\n this.startPosition = null;\n }\n\n public StopTracking() {\n if (this.Logo != null)\n {\n this.Logo.IsTracking = false;\n this.Logo = null;\n }\n }\n\n protected ComputeLogoTrackingPosition() {\n let pos = this.Logo!.position;\n pos.x = window.innerWidth/3;\n return pos;\n }\n\n public Update() {\n if (this.Logo == null)\n return;\n }\n\n}\n","import * as PIXI from \"pixi.js\";\nimport {Triangles} from \"./Triangles\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../../Util/TweenWrapper/Ease\";\nimport {Main} from \"../../../main\";\nimport {Loader} from \"../../../Loader\";\nimport {ButtonSystem} from \"./Menu/ButtonSystem\";\nimport {MenuLogoVisualizer} from \"../../AudioVisualizers/impl/MenuLogoVisualizer\";\nimport {LogoVisualizer} from \"../../AudioVisualizers/LogoVisualizer\";\nimport {Effect} from \"../../../Util/Beatmap/Data/Sections/TimingPoints/Effect\";\nimport {UnInheritedTimingPoint} from \"../../../Util/Beatmap/Data/Sections/TimingPoints/UnInheritedTimingPoint\";\nimport {MathUtil} from \"../../../Util/MathUtil\";\n\nexport class OsuLogo extends PIXI.Container {\n\n private readonly outline: PIXI.Sprite;\n private readonly visualizer: MenuLogoVisualizer = new MenuLogoVisualizer();\n private readonly triangles: Triangles = new Triangles();\n private readonly flash;\n private readonly logoContainer = new PIXI.Container;\n private readonly logoBounceContainer = new PIXI.Container();\n private readonly logoBeatContainer = new PIXI.Container();\n private readonly logoAmplitudeContainer = new PIXI.Container();\n private readonly logoHoverContainer = new PIXI.Container();\n private readonly rippleContainer = new PIXI.Container();\n private readonly ripple;\n private readonly defaultVisualizerAlpha = 0.5;\n private readonly early_activation = 60;\n private timeElapsedSinceLastBeat = 0;\n private timeUntilNextBeat = 0;\n private lastTimeElapasedSinceLastBeat = 0;\n\n private selectSample = Loader.GetAudio(\"mainMenu.osuLogo.select\");\n private backToLogoSample = Loader.GetAudio(\"mainMenu.osuLogo.backToLogo\");\n\n private isMouseDown = false;\n private mouseDownPosition = {x: 0, y: 0};\n\n public Action: (() => boolean) | null = null;\n\n public IsTracking: boolean = false;\n\n public get SizeForFlow() {\n return this.outline.width * this.logoBounceContainer.scale.x * this.logoHoverContainer.scale.x;\n }\n\n\n public constructor() {\n super();\n this.visualizer.start();\n\n\n this.outline = PIXI.Sprite.from(\"mainMenu.logoOutline\");\n this.outline.anchor.set(0.5, 0.5);\n //approximation of size in actual osu!lazer\n let scale = 0.7;\n this.visualizer.scale.set(scale);\n this.visualizer.pivot.set(LogoVisualizer.size/2, LogoVisualizer.size/2);\n this.visualizer.alpha = this.defaultVisualizerAlpha;\n\n let mask = new PIXI.Graphics();\n mask.circle(0,0,450);\n mask.fill({color:\"white\"});\n mask.scale = scale;\n\n\n this.flash = PIXI.Sprite.from(\"mainMenu.logoMask\");\n this.flash.anchor.set(0.5, 0.5);\n this.flash.scale = scale;\n this.flash.blendMode = \"add\";\n this.flash.alpha = 0;\n\n this.triangles.flash.anchor.set(0.5, 0.5);\n this.triangles.flash.scale = scale;\n\n this.outline.scale.set(scale);\n this.triangles.scale.set(scale);\n this.triangles.position.set(-(this.outline.width / 2), -(this.outline.height / 2));\n this.triangles.mask = mask;\n\n this.ripple = PIXI.Sprite.from(\"mainMenu.logoMask\");\n this.ripple.anchor.set(0.5, 0.5);\n this.ripple.scale = scale;\n this.ripple.alpha = 0;\n this.ripple.blendMode = \"add\";\n\n this.rippleContainer.addChild(this.ripple);\n this.logoContainer.addChild(this.visualizer);\n this.logoContainer.addChild(this.triangles);\n this.logoContainer.addChild(this.triangles.flash);\n this.logoContainer.addChild(mask);\n this.logoContainer.addChild(this.flash);\n this.logoContainer.addChild(this.outline);\n this.logoContainer.hitArea = new PIXI.Circle(0, 0, 480 * scale);\n this.logoContainer.eventMode = \"static\";\n\n this.logoContainer.onmouseenter = this._onmouseenter;\n this.logoContainer.onmouseleave = this._onmouseleave;\n this.logoContainer.onmousedown = this._onmousedown;\n this.logoContainer.onclick = this._onclick;\n\n this.logoBeatContainer.addChild(this.logoContainer);\n this.logoAmplitudeContainer.addChild(this.logoBeatContainer);\n this.logoBounceContainer.addChild(this.rippleContainer);\n this.logoBounceContainer.addChild(this.logoAmplitudeContainer);\n this.logoHoverContainer.addChild(this.logoBounceContainer);\n this.addChild(this.logoHoverContainer)\n\n // register event listeners\n Main.app.stage.addEventListener(\"mouseup\", (e) => {\n this._onmouseup(e);\n });\n\n }\n\n\n public _onmouseenter = (e: PIXI.FederatedMouseEvent) => {\n Ease.getEase(this.logoHoverContainer).ScaleTo(1.1, 500, TWEEN.Easing.Elastic.Out);\n }\n\n public _onmouseleave = (e: PIXI.FederatedMouseEvent) => {\n Ease.getEase(this.logoHoverContainer).ScaleTo(1, 500, TWEEN.Easing.Elastic.Out);\n }\n\n public _onmousedown = (e: PIXI.FederatedMouseEvent) => {\n this.isMouseDown = true;\n Ease.getEase(this.logoBounceContainer).ClearEasings().ScaleTo(0.9, 1000, TWEEN.Easing.Sinusoidal.Out);\n this.mouseDownPosition = {x: Main.mousePos.x, y: Main.mousePos.y};\n }\n\n public _onclick = (e: PIXI.FederatedMouseEvent) => {\n this.flash.alpha = 0.4;\n Ease.getEase(this.flash).ClearEasings()\n .FadeOut(1500, TWEEN.Easing.Exponential.Out);\n if (this.Action) {\n if(this.Action()){\n Main.AudioEngine.PlayEffect(Loader.GetAudio(\"mainMenu.osuLogo.select\"));\n }\n }\n }\n\n public _onmouseup = (e: PIXI.FederatedMouseEvent) => {\n this.isMouseDown = false;\n Ease.getEase(this.logoBounceContainer).ClearEasings().ScaleTo(1, 500, TWEEN.Easing.Elastic.Out)\n .TransformTo({x: 0, y: 0}, 800, TWEEN.Easing.Elastic.Out);\n }\n\n public draw(ticker: PIXI.Ticker) {\n this.visualizer.draw(ticker);\n this.triangles.draw(ticker);\n //this.timeElapsedSinceLastBeat += ticker.deltaMS;\n let audio = Main.AudioEngine.GetCurrentPlayingMusic();\n let audioTime = audio.GetCurrentTime();\n let timingPoint = audio.beatmap.TimingPoints.GetCurrentUninheritedTimingPoint(audioTime);\n this.timeUntilNextBeat = (timingPoint.time - audioTime) % timingPoint.beatLength;\n if (this.timeUntilNextBeat <= 0) {\n this.timeUntilNextBeat += timingPoint.beatLength;\n }\n this.timeElapsedSinceLastBeat = timingPoint.beatLength - this.timeUntilNextBeat;\n if (!Main.AudioEngine.useSilentMusic) {\n let maxAmplitude = audio.GetMaximumAudioLevel();\n this.logoAmplitudeContainer.scale.set(MathUtil.Damp(this.logoAmplitudeContainer.scale.x,\n 1 - Math.max(0, maxAmplitude - 0.4) * 0.04, 0.9, ticker.deltaMS))\n this.triangles.Velocity = MathUtil.Damp(this.triangles.Velocity,\n 0.5 * (timingPoint.effects == Effect.KiaiTime ? 4 : 2), 0.995, ticker.deltaMS);\n } else {\n this.logoAmplitudeContainer.scale = 1;\n this.triangles.Velocity = MathUtil.Damp(this.triangles.Velocity, 0.5, 0.9, ticker.deltaMS);\n }\n if (this.lastTimeElapasedSinceLastBeat > this.timeElapsedSinceLastBeat) {\n this.onNewBeat();\n }\n\n this.lastTimeElapasedSinceLastBeat = this.timeElapsedSinceLastBeat;\n\n if (this.isMouseDown) {\n let change = {x: Main.mousePos.x - this.mouseDownPosition.x, y: Main.mousePos.y - this.mouseDownPosition.y};\n let length = Math.sqrt(change.x * change.x + change.y * change.y);\n // Diminish the drag distance as we go further to simulate \"rubber band\" feeling.\n change.x *= length <= 0 ? 0 : Math.pow(length, 0.6) / length;\n change.y *= length <= 0 ? 0 : Math.pow(length, 0.6) / length;\n this.logoBounceContainer.x = change.x;\n this.logoBounceContainer.y = change.y;\n }\n\n\n }\n\n private onNewBeat() {\n let audio = Main.AudioEngine.GetCurrentPlayingMusic();\n let audioTime = audio.GetCurrentTime();\n let timingPointUninherited = audio.beatmap.TimingPoints.GetCurrentUninheritedTimingPoint(audioTime);\n let beatLength = timingPointUninherited.beatLength;\n let timingPoint = audio.beatmap.TimingPoints.GetCurrentTimingPoints(audioTime)[0];\n let maxAmplitude = !Main.AudioEngine.useSilentMusic ? audio.GetMaximumAudioLevel() : 0;\n let amplitudeAdjust = Math.min(1, 0.2 + maxAmplitude);\n Ease.getEase(this.logoBeatContainer).ScaleTo(1 - 0.02 * amplitudeAdjust, this.early_activation, TWEEN.Easing.Linear.None).Then()\n .ScaleTo(1, beatLength * 2, TWEEN.Easing.Quintic.Out);\n this.rippleContainer.scale = 1.02;\n Ease.getEase(this.rippleContainer).ClearEasings().ScaleTo(1.02 * (1 + 0.04 * amplitudeAdjust), beatLength, TWEEN.Easing.Quintic.Out);\n this.ripple.alpha = 0.15 * amplitudeAdjust;\n Ease.getEase(this.ripple).ClearEasings().FadeOut(beatLength, TWEEN.Easing.Quintic.Out);\n\n\n if (timingPoint.effects == Effect.KiaiTime) {\n Ease.getEase(this.triangles.flash).ClearEasings()\n .FadeTo(0.2 * amplitudeAdjust, this.early_activation, TWEEN.Easing.Linear.None).Then()\n .FadeTo(0, beatLength, TWEEN.Easing.Linear.None);\n Ease.getEase(this.visualizer).ClearEasings()\n .FadeTo(this.defaultVisualizerAlpha * 1.8 * amplitudeAdjust, this.early_activation, TWEEN.Easing.Linear.None).Then()\n .FadeTo(this.defaultVisualizerAlpha, beatLength, TWEEN.Easing.Linear.None);\n }\n setTimeout(() => {\n this.triangles.Velocity += amplitudeAdjust * (timingPoint.effects == Effect.KiaiTime ? 6 : 3);\n }, 60)\n\n }\n\n}\n","import * as PIXI from \"pixi.js\";\nimport {Main} from \"../../../main\";\nimport glVertShader from \"./osuCircleTriangles.vert\";\nimport glFragShader from \"./osuCircleTriangles.frag\";\nimport gpuShader from \"./osuCircleTriangles.wgsl\";\n\nexport class Triangles extends PIXI.Container {\n\n public flash: PIXI.Sprite;\n public Velocity: number = 1;\n private readonly bgGradient: PIXI.FillGradient;\n private triangles: Triangle[] = [];\n private graphics: PIXI.Graphics = new PIXI.Graphics();\n private timeSinceLastSpawn = 0;\n private instancePositionBuffer;\n private readonly totalTriangles = 15;\n\n public constructor() {\n super();\n\n let colorStops = [0xff66ab, 0xcc5289];\n this.bgGradient = new PIXI.FillGradient(0, 0, 0, 1024);\n colorStops.forEach((number, index) => {\n const ratio = index / colorStops.length;\n this.bgGradient.addColorStop(ratio, number);\n });\n\n for (let i = 0; i < this.totalTriangles; i++) {\n this.triangles.push({x: this.random(0, 1024), y: this.random(0, 1024), velocity: this.randVelocity()});\n }\n this.timeSinceLastSpawn = Date.now();\n\n this.graphics.rect(0, 0, 1024, 1024);\n this.graphics.fill(this.bgGradient);\n this.addChild(this.graphics);\n\n this.flash = PIXI.Sprite.from(\"mainMenu.logoMask\");\n //this.flash.anchor.set(0.5, 0.5);\n this.flash.alpha = 0;\n this.flash.blendMode = \"add\";\n\n this.instancePositionBuffer = new PIXI.Buffer({\n data: new Float32Array(this.totalTriangles * 2),\n usage: PIXI.BufferUsage.VERTEX | PIXI.BufferUsage.COPY_DST\n });\n const color = new PIXI.Color(\"rgb(182, 52, 111)\");\n const size = 30;\n const geometry = new PIXI.Geometry({\n attributes: {\n aPosition: [\n -10*size,\n -10*size, // x, y\n 10*size,\n -10*size, // x, y\n 10*size,\n 7.5*size, // x, y,\n -10*size,\n 7.5*size, // x, y,\n ],\n aUV: [0, 0, 1, 0, 1, 1, 0, 1],\n aColorTint: [\n color.red, color.green, color.blue, 1,\n color.red, color.green, color.blue, 1,\n color.red, color.green, color.blue, 1,\n color.red, color.green, color.blue, 1\n ],\n aPositionOffset: {\n buffer: this.instancePositionBuffer,\n instance: true\n }\n },\n indexBuffer: [0, 1, 2, 0, 2, 3],\n instanceCount: this.totalTriangles\n });\n const gl = {\n vertex: glVertShader,\n fragment: glFragShader\n };\n\n const gpu = {\n vertex: {\n entryPoint: \"mainVert\",\n source: gpuShader\n },\n fragment: {\n entryPoint: \"mainFrag\",\n source: gpuShader\n }\n };\n\n const triangleGraphic = new PIXI.Graphics();\n triangleGraphic.moveTo(0, 0);\n triangleGraphic.lineTo(-256, 512);\n triangleGraphic.lineTo(256, 512);\n triangleGraphic.lineTo(0, 0);\n triangleGraphic.stroke({color: \"white\", width: 4});\n\n const triangleTexture = Main.app.renderer.generateTexture(triangleGraphic);\n\n const shader = PIXI.Shader.from({\n gl,\n gpu,\n resources: {\n uTexture: triangleTexture.source,\n uSampler: triangleTexture.source.style,\n waveUniforms: {\n time: { value: 1, type: \"f32\" }\n }\n }\n });\n\n const triangleMesh = new PIXI.Mesh({\n geometry,\n shader\n });\n\n this.addChild(triangleMesh);\n\n\n\n }\n\n public destroy(options?: PIXI.DestroyOptions) {\n super.destroy(options);\n }\n\n public draw(ticker: PIXI.Ticker) {\n const data = this.instancePositionBuffer.data;\n let count = 0;\n\n for (let i = 0; i < this.totalTriangles; i++) {\n const triangle = this.triangles[i];\n\n triangle.y -= ((ticker.deltaTime * this.Velocity * triangle.velocity)*1.2);\n\n if (triangle.y + 100 < 0) {\n triangle.y = 1024 + 250;\n }\n\n data[count++] = triangle.x;\n data[count++] = triangle.y;\n }\n\n this.instancePositionBuffer.update();\n }\n\n private random(min: number, max: number) {\n return Math.random() * (max - min) + min;\n }\n\n private randVelocity() {\n let u1 = 1 - this.random(0, 1);\n let u2 = 1 - this.random(0, 1);\n let randStdNormal = (Math.sqrt(-2.0 * Math.log(u1)) * Math.sin(2.0 * Math.PI * u2));\n return Math.max(0.5 + 0.16 * randStdNormal, 0.1);\n }\n}\n\nexport interface Triangle {\n x: number;\n y: number;\n velocity: number;\n}\n","import * as PIXI from \"pixi.js\";\nimport {Main} from \"../../main\";\nimport {Loader} from \"../../Loader\";\nimport {MathUtil} from \"../../Util/MathUtil\";\nimport {Screen} from \"../../Screens/Screen\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\n\nexport class MenuCursor extends PIXI.Container {\n private mouseCursor = PIXI.Sprite.from(\"menu.cursor\");\n private mouseCursorAdditive = PIXI.Sprite.from(\"menu.cursor.additive\");\n private mouseContainer = new PIXI.Container();\n private animContainer = new PIXI.Container();\n private animRotationContainer = new PIXI.Container();\n private dragRotationState: DragRotationState = DragRotationState.NotDragging;\n private lastDragRotationState: DragRotationState = DragRotationState.NotDragging;\n private mouseHideContainer = new PIXI.Container();\n private readonly elastic_const2 = 0.075;\n private readonly elastic_const = 20.943951023931955;\n private readonly elastic_offset_quarter = Math.pow(2, -10) * Math.sin((.25 - this.elastic_const2) * this.elastic_const);\n\n private posMouseDown: { x: number, y: number } = {x: 0, y: 0};\n\n private mouseIsDown = false;\n\n private cursorTapSample = Loader.GetAudio(\"menu.cursor.sample.tap\");\n\n private mouseButtonClicked: number = -9999;\n\n public constructor(visible: boolean) {\n super();\n this.updateMouse();\n this.mouseContainer.scale.set(0.07 * Screen.getScaleBasedOffScreenSize());\n this.mouseCursorAdditive.alpha = 0;\n this.mouseCursorAdditive.blendMode = \"add\";\n this.mouseCursorAdditive.tint = \"0xFF66AA\"\n this.mouseContainer.addChild(this.mouseCursor);\n this.mouseContainer.addChild(this.mouseCursorAdditive);\n this.animContainer.addChild(this.mouseContainer);\n this.animRotationContainer.addChild(this.animContainer);\n this.mouseHideContainer.addChild(this.animRotationContainer);\n this.addChild(this.mouseHideContainer);\n if (!visible) {\n this.mouseHideContainer.scale.set(0.6);\n this.mouseHideContainer.alpha = 0;\n this.animRotationContainer.angle = 0;\n }\n this.zIndex = 999999;\n this.eventMode = \"none\";\n Main.app.stage.addChild(this);\n this.addEventListeners();\n }\n\n public addEventListeners() {\n Main.app.stage.addEventListener(\"mousedown\", (e) => {\n this.mouseButtonClicked = e.button;\n if (this.visible) {\n this.posMouseDown = {x: Main.mousePos.x, y: Main.mousePos.y};\n this.mouseIsDown = true;\n this.dragRotationState = DragRotationState.DragStarted;\n Ease.getEase(this.animContainer).ClearEasings().ScaleTo(0.9, 800, TWEEN.Easing.Quintic.Out);\n Ease.getEase(this.mouseCursorAdditive).ClearEasings().FadeIn(800, TWEEN.Easing.Quintic.Out);\n Main.AudioEngine.PlayEffect(this.cursorTapSample);\n }\n });\n Main.app.stage.addEventListener(\"mouseup\", (e) => {\n if (this.visible && e.button == this.mouseButtonClicked) {\n this.mouseIsDown = false;\n Ease.getEase(this.animContainer).ClearEasings().ScaleTo(1, 500, TWEEN.Easing.Elastic.Out);\n Ease.getEase(this.mouseCursorAdditive).ClearEasings().FadeOut(500, TWEEN.Easing.Quintic.Out);\n if (this.dragRotationState != DragRotationState.NotDragging) {\n if (this.dragRotationState == DragRotationState.Rotating) {\n Ease.getEase(this.animRotationContainer).ClearEasings().createTween({value: this.animRotationContainer.angle},\n {value: 0}, true, \"angle\", 800 * (0.5 + Math.abs(this.animRotationContainer.angle / 960)), (time: number) => {\n return Math.pow(2, -10 * time) * \n Math.sin((.25 * time - this.elastic_const2) * this.elastic_const) + 1 - this.elastic_offset_quarter * time;\n });\n }\n this.dragRotationState = DragRotationState.NotDragging;\n }\n Main.AudioEngine.PlayEffect(this.cursorTapSample, 0.8);\n }\n });\n }\n\n public PopIn() {\n Ease.getEase(this.animRotationContainer).ClearEasings();\n this.visible = true;\n Ease.getEase(this.mouseHideContainer).ClearEasings().FadeIn(250, TWEEN.Easing.Quintic.Out)\n .ScaleTo(1, 400, TWEEN.Easing.Quintic.Out);\n this.dragRotationState = DragRotationState.NotDragging\n }\n\n public PopOut() {\n Ease.getEase(this.mouseHideContainer).ClearEasings().FadeOut(250, TWEEN.Easing.Quintic.Out)\n .ScaleTo(0.6, 250, TWEEN.Easing.Quintic.Out);\n Ease.getEase(this.animRotationContainer).ClearEasings().createTween({value: this.animRotationContainer.angle},\n {value: 0}, true, \"angle\", 400, TWEEN.Easing.Quintic.Out);\n this.dragRotationState = DragRotationState.NotDragging;\n }\n\n public updateMouse() {\n this.mouseContainer.scale.set(0.07 * Screen.getScaleBasedOffScreenSize());\n this.position.set(Main.mousePos.x, Main.mousePos.y);\n if (this.dragRotationState != DragRotationState.NotDragging && this.visible) {\n let distance = Math.sqrt((((Math.abs(this.posMouseDown.x - Main.mousePos.x)) ^ 2) +\n ((Math.abs(this.posMouseDown.y - Main.mousePos.y)) ^ 2)));\n if (this.dragRotationState == DragRotationState.DragStarted && distance > 15) {\n this.dragRotationState = DragRotationState.Rotating;\n if (this.lastDragRotationState != this.dragRotationState) {\n this.posMouseDown = {x: Main.mousePos.x, y: Main.mousePos.y};\n }\n }\n\n if (this.dragRotationState == DragRotationState.Rotating && distance > 0) {\n let offsetX = Main.mousePos.x - this.posMouseDown.x;\n let offsetY = Main.mousePos.y - this.posMouseDown.y;\n let degrees = MathUtil.RadiansToDegrees(Math.atan2(-offsetX, offsetY)) + 24.3;\n\n let diff = (degrees - this.animRotationContainer.angle) % 360;\n if (diff < -180) {\n diff += 360;\n }\n if (diff > 180) {\n diff -= 360;\n }\n degrees = this.animRotationContainer.angle + diff;\n this.animRotationContainer.angle = degrees\n Ease.getEase(this.animRotationContainer).createTween({value: this.animRotationContainer.angle},\n {value: degrees}, true, \"angle\", 120, TWEEN.Easing.Quintic.Out);\n }\n }\n this.lastDragRotationState = this.dragRotationState;\n\n }\n\n\n}\n\nenum DragRotationState {\n NotDragging,\n DragStarted,\n Rotating\n}\n","import * as PIXI from \"pixi.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {DestroyOptions} from \"pixi.js\";\n\nexport class Background extends PIXI.Sprite {\n public static readonly fadeOutDuration = 800;\n public destroying = false;\n\n public constructor(texture: PIXI.Texture) {\n super();\n this.texture = texture;\n this.visible = false;\n this.anchor.set(0.5, 0.5);\n\n }\n\n public show() {\n this.visible = true;\n }\n\n public destroy(options?: PIXI.DestroyOptions) {\n this.destroying = true;\n Ease.getEase(this).FadeOut(Background.fadeOutDuration, TWEEN.Easing.Linear.None).Then(() => {\n this.visible = false;\n super.destroy(options);\n this.destroying = false;\n });\n this.zIndex = 1;\n }\n}\n\nexport class BackgroundContainer extends PIXI.Container {\n public constructor() {\n super();\n this.visible = false;\n }\n\n public show() {\n this.visible = true;\n for (let i = 0; i < this.children?.length; i++) {\n let child = this.children[i];\n if (child instanceof Background) {\n child.show();\n }\n }\n }\n\n public destroy(options?: DestroyOptions) {\n for (let i = 0; i < this.children?.length; i++) {\n let child = this.children[i];\n if (child instanceof Background) {\n if (!child.destroyed && !child.destroying) {\n child.destroy(options);\n }\n }\n }\n setTimeout(() => {\n super.destroy(options);\n }, Background.fadeOutDuration);\n this.zIndex = 1;\n }\n\n\n}","import * as PIXI from \"pixi.js\";\nimport {Loader} from \"../../Loader\";\nimport {Screen} from \"../../Screens/Screen\";\nimport {Main} from \"../../main\";\nimport {Background, BackgroundContainer} from \"./Background\";\nimport {EventTypes} from \"../../Util/Beatmap/Data/Sections/Events/EventTypes\";\nimport {EventVideo} from \"../../Util/Beatmap/Data/Sections/Events/EventVideo\";\nimport {EventBackground} from \"../../Util/Beatmap/Data/Sections/Events/EventBackground\";\n\nexport class RandomBackground extends Screen {\n\n private bgContainer = new PIXI.Container;\n\n private readonly parallaxMultiplier = 60;\n\n public start() {\n this.bgContainer.pivot.set(0.5, 0.5);\n this.bgContainer.position.set((Main.mousePos.x - (this.getScreenWidth() / 2)) / this.parallaxMultiplier,\n (Main.mousePos.y - (this.getScreenHeight() / 2)) / this.parallaxMultiplier);\n this.addChild(this.bgContainer);\n this.newRandomBG();\n Main.AudioEngine.addMusicChangeEventListener((audio) => {\n let background = audio.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.BACKGROUND){\n return e;\n }\n }) as EventBackground;\n\n let backgroundVideo = audio.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n\n let bgContainer = new BackgroundContainer();\n\n if (background) {\n if (background.texture) {\n bgContainer.addChild(new Background(background.texture));\n }\n }\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n let video = backgroundVideo.texture.source.resource as HTMLVideoElement;\n let bg = new Background(backgroundVideo.texture);\n bgContainer.addChild(bg);\n backgroundVideo.texture.source.resource.startPromise = new Promise((resolve) => {\n if (backgroundVideo.startTime > 0) {\n setTimeout(() => {\n video.play();\n resolve();\n }, backgroundVideo.startTime);\n } else {\n video.currentTime = Math.abs(backgroundVideo.startTime)/1000;\n video.play();\n resolve();\n }\n });\n video.onended = () => {\n bg.destroy();\n }\n }\n }\n if (background || backgroundVideo) {\n this.setBGContainer(bgContainer);\n }\n if (!background && !backgroundVideo) {\n this.newRandomBG();\n }\n });\n this.zIndex = -100;\n }\n\n public setBG(texture: PIXI.Texture) {\n let bgSprite = new Background(texture);\n this.bgContainer.addChild(bgSprite);\n bgSprite.show();\n if (this.bgContainer.children?.length == 0) {\n } else {\n let previous = this.bgContainer.children[0] as Background;\n previous.destroy();\n }\n this.onResize();\n }\n\n public setBGContainer(container: BackgroundContainer) {\n this.bgContainer.addChild(container);\n container.show();\n if (this.bgContainer.children?.length == 0) {\n } else {\n let previous = this.bgContainer.children[0] as Background;\n previous.destroy();\n }\n this.onResize();\n }\n\n public newRandomBG() {\n function random(min: number, max: number) {\n return Math.round(Math.random() * (max - min) + min);\n }\n\n let useSeasonalBackgrounds = Loader.seasonalBackgroundsNum > 0;\n let randomNum = random(1, useSeasonalBackgrounds ? Loader.seasonalBackgroundsNum : Loader.defaultBackgroundsNum);\n this.setBG(PIXI.Texture.from((useSeasonalBackgrounds ? \"seasonal_bg\" : \"default_bg\") + randomNum));\n }\n\n public draw(deltaTime: PIXI.Ticker) {\n this.bgContainer.position.set((Main.mousePos.x - (this.getScreenWidth() / 2)) / this.parallaxMultiplier,\n (Main.mousePos.y - (this.getScreenHeight() / 2)) / this.parallaxMultiplier);\n }\n\n public onClose(): Promise {\n return Promise.resolve(this);\n }\n\n public onResize() {\n this.bgContainer.children.forEach((sprite) => {\n if (sprite instanceof BackgroundContainer) {\n sprite.children?.forEach((sprite) => {\n if (sprite instanceof Background) {\n this.resizeSprite(sprite);\n }\n });\n }\n if (sprite instanceof Background) {\n this.resizeSprite(sprite)\n }\n });\n }\n\n private resizeSprite(sprite: Background) {\n let texWidth = sprite.texture.width;\n let texHeight = sprite.texture.height;\n\n let scaleFactor: number;\n if (window.innerWidth > window.innerHeight) {\n scaleFactor = window.innerWidth / texWidth;\n } else {\n scaleFactor = window.innerHeight / texHeight;\n }\n\n if (texHeight * scaleFactor < window.innerHeight) {\n scaleFactor = window.innerHeight / texHeight;\n } else if (texWidth * scaleFactor < window.innerWidth) {\n\n }\n\n sprite.scale.set(scaleFactor + 0.05);\n sprite.position.set((this.getScreenWidth() / 2) - (this.getScreenWidth() / (this.parallaxMultiplier * 2)),\n this.getScreenHeight() / 2 - (this.getScreenHeight() / (this.parallaxMultiplier * 2)));\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Screen} from \"../../Screens/Screen\";\n\nexport class SettingsPane extends PIXI.Container {\n private bg: PIXI.Graphics = new PIXI.Graphics();\n private isOpen = false;\n\n public constructor() {\n super();\n this.bg.rect(0, 0, 1, 1);\n this.bg.fill({color: \"rgb(20,20,20)\"});\n this.addChild(this.bg);\n this.resize();\n }\n\n public open() {\n Ease.getEase(this).TransformTo({x: 0, y: 0}, 400, TWEEN.Easing.Cubic.Out);\n this.isOpen = true;\n }\n\n public toggle() {\n if (this.isOpen) {this.close()} else {this.open()}\n }\n\n public close() {\n Ease.getEase(this).TransformTo({x: -this.getWidth(), y: 0}, 400, TWEEN.Easing.Cubic.Out);\n this.isOpen = false;\n }\n\n private getWidth() {\n return 500 * Screen.getScaleBasedOffScreenSize();\n }\n\n public resize() {\n this.width = this.getWidth();\n this.height = window.innerHeight;\n this.x = this.isOpen ? 0 : -this.getWidth();\n this.y = 0;\n }\n}","import * as PIXI from \"pixi.js\";\n\nexport class Loader {\n private static loadList: LoaderObject[] = [];\n private static loadedList: LoadedObject[] = [];\n public static readonly defaultBackgroundsNum = 8;\n public static seasonalBackgroundsNum: number = 0;\n\n private static addToLoadList() {\n // intro and interaction screen\n this.loadList.push({id: \"introTrianglesTrack\", url: \"assets/osu-assets/osu.Game.Resources/Tracks/triangles.osz\"});\n this.loadList.push({id: \"sample_dialog_ok\", url: \"assets/osu-assets/osu.Game.Resources/Samples/UI/dialog-ok-select.wav\", isAudio: true});\n this.loadList.push({id: \"TorusRegular\", url: \"assets/fonts/TorusRegular.otf\", pixiBundleName: \"fonts\"});\n this.loadList.push({id: \"TorusLight\", url: \"assets/fonts/TorusLight.otf\", pixiBundleName: \"fonts\"});\n this.loadList.push({id: \"TorusThin\", url: \"assets/fonts/TorusThin.otf\", pixiBundleName: \"fonts\"});\n this.loadList.push({id: \"icon_ruleset_std\", url: \"assets/icons/ruleset-standard.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"icon_ruleset_mania\", url: \"assets/icons/ruleset-mania.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"icon_ruleset_taiko\", url: \"assets/icons/ruleset-taiko.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"icon_ruleset_ctb\", url: \"assets/icons/ruleset-ctb.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"intro_triangles_osuLogo_anim_highlight\",\n url: \"assets/osu-assets/osu.Game.Resources/Textures/Intro/Triangles/logo-highlight.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"intro_triangles_osuLogo_anim_background\",\n url: \"assets/osu-assets/osu.Game.Resources/Textures/Intro/Triangles/logo-background.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"mainMenu.logoOutline\", url: \"assets/osu-assets/osu.Game.Resources/Textures/Menu/logo.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"mainMenu.logoMask\", url: \"assets/menu/logo-mask.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"mainMenu.osuLogo.select\", url: \"assets/osu-assets/osu.Game.Resources/Samples/Menu/osu-logo-select.wav\", isAudio: true});\n this.loadList.push({id: \"mainMenu.osuLogo.backToLogo\", url: \"assets/osu-assets/osu.Game.Resources/Samples/Menu/back-to-logo.wav\", isAudio: true});\n this.loadList.push({id: \"menu.cursor\", url: \"assets/osu-assets/osu.Game.Resources/Textures/Cursor/menu-cursor.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"menu.cursor.additive\", url: \"assets/osu-assets/osu.Game.Resources/Textures/Cursor/menu-cursor-additive.png\",\n pixiBundleName: \"textures\"});\n this.loadList.push({id: \"menu.cursor.sample.tap\", url: \"assets/osu-assets/osu.Game.Resources/Samples/UI/cursor-tap.wav\", isAudio: true});\n this.loadList.push({id: \"menu.kiaiFountains.star\", url: \"assets/osu-assets/osu.Game.Resources/Textures/Menu/fountain-star.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"workers.ffmpeg\", url: \"assets/workers/814.ffmpeg.js\"});\n this.loadList.push({id: \"ffmpeg.core\", url: \"https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm/ffmpeg-core.js\"});\n this.loadList.push({id: \"ffmpeg.wasm\", url: \"https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm/ffmpeg-core.wasm\"});\n this.loadList.push({id: \"ffmpeg.coreWorker\", url: \"https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm/ffmpeg-core.worker.js\"});\n }\n\n public static Get(id: string): Blob {\n let result;\n this.loadedList.forEach((loadedObj) => {\n if (loadedObj.id == id){\n result = loadedObj.data;\n }\n });\n if (!result){\n throw new Error(\"Asset not found!\");\n }\n return result;\n }\n\n public static GetString(id: string): string {\n let result;\n this.loadedList.forEach((loadedObj) => {\n if (loadedObj.id == id){\n result = loadedObj.dataString;\n }\n });\n if (!result){\n throw new Error(\"Asset not found or is not a string!\");\n }\n return result;\n }\n\n public static GetAudio(id: string): AudioBuffer {\n let result;\n this.loadedList.forEach((loadedObj) => {\n if (loadedObj.id == id){\n result = loadedObj.dataAudio;\n }\n });\n if (!result){\n throw new Error(\"Asset not found or was not marked as audio during loading!\");\n }\n return result;\n }\n\n private static addBackgrounds() {\n return new Promise(resolve => {\n for (let i = 1; i < this.defaultBackgroundsNum + 1; i++) {\n this.loadList.push({id: \"default_bg\"+i, url: \"assets/osu-assets/osu.Game.Resources/Textures/Menu/menu-background-\"+i+\".jpg\", pixiBundleName: \"textures\"});\n }\n fetch(\"https://corsproxy.io/?\"+ encodeURIComponent(\"https://osu.ppy.sh/api/v2/seasonal-backgrounds\"))\n .then(res => res.json()).then(res => {\n res.backgrounds.forEach((background: any, index: number) => {\n this.loadList.push({id: \"seasonal_bg\"+(index+1), url: \"https://corsproxy.io/?\"+ encodeURIComponent(background.url),\n pixiBundleName: \"textures\", loadParser: \"loadTextures\"});\n this.seasonalBackgroundsNum = index+1;\n });\n resolve();\n }).catch(error => {\n console.warn(\"Could not fetch seasonal backgrounds.\", error);\n resolve();\n });\n });\n }\n\n public static Load(audioContext: AudioContext) {\n this.addToLoadList();\n return new Promise((resolve) => {\n this.addBackgrounds().then(() => {\n let nonPixi: LoaderObject[] = [];\n let pixi: LoaderObject[] = [];\n let pixiwithBundles: LoaderObject[][] = [];\n\n let loadedAssets: number = 0;\n let erroredAssets: number = 0;\n\n this.loadList.forEach((loadObj) => {\n if (loadObj.pixiBundleName){\n pixi.push(loadObj);\n }\n else {\n nonPixi.push(loadObj);\n }\n });\n\n pixi.forEach((loadObj) => {\n let added = false;\n pixiwithBundles.forEach((loadObjs) => {\n if (loadObjs.length > 0){\n if (loadObjs[0].pixiBundleName == loadObj.pixiBundleName){\n loadObjs.push(loadObj);\n added = true;\n }\n }\n });\n if (!added){\n pixiwithBundles.push([loadObj]);\n }\n });\n\n const incrementLoadAssetNumber = (errored?: boolean) => {\n if (errored){\n erroredAssets++;\n }\n else {\n loadedAssets++;\n }\n\n if (erroredAssets + loadedAssets >= this.loadList.length){\n resolve();\n }\n }\n\n nonPixi.forEach((loadObj) => {\n fetch(loadObj.url)\n .then(response => response.blob())\n .then((response) => {\n if (!loadObj.isText && !loadObj.isAudio){\n incrementLoadAssetNumber();\n this.loadedList.push({id: loadObj.id, data: response});\n }\n else if (loadObj.isText) {\n response.text().then((text) => {\n incrementLoadAssetNumber();\n this.loadedList.push({id: loadObj.id, data: response, dataString: text});\n });\n }\n else if (loadObj.isAudio){\n response.arrayBuffer().then(arrBuff => audioContext.decodeAudioData(arrBuff))\n .then((audioBuff) => {\n incrementLoadAssetNumber();\n this.loadedList.push({id: loadObj.id, data: response, dataAudio: audioBuff});\n });\n }\n\n })\n .catch((error) => {\n incrementLoadAssetNumber(true);\n console.warn(\"Asset '\"+loadObj.id+\"' failed to load: \"+error);\n });\n });\n\n pixiwithBundles.forEach((bundle) => {\n if (bundle.length > 0){\n if (!bundle[0].pixiBundleName){\n throw new Error(\"wtf????\");\n }\n let assets: PIXI.UnresolvedAsset[] = [];\n bundle.forEach((loadObj) => {\n if (loadObj.loadParser){\n assets.push({alias: loadObj.id, src: loadObj.url, loadParser: loadObj.loadParser});\n }\n else {\n assets.push({alias: loadObj.id, src: loadObj.url});\n }\n\n });\n PIXI.Assets.addBundle(bundle[0].pixiBundleName, assets);\n PIXI.Assets.loadBundle(bundle[0].pixiBundleName).then(() => {\n bundle.forEach(() => {\n incrementLoadAssetNumber();\n });\n });\n }\n\n })\n });\n });\n }\n}\n\ninterface LoaderObject {\n id: string;\n url: string;\n pixiBundleName?: string;\n isText?: boolean;\n isAudio?: boolean;\n loadParser?: PIXI.LoadParserName;\n}\n\ninterface LoadedObject {\n id: string;\n data: Blob;\n dataString?: string;\n dataAudio?: AudioBuffer;\n}\n","import {Screen} from \"../Screen\";\nimport * as PIXI from \"pixi.js\";\nimport {Ticker} from \"pixi.js\";\nimport {Main} from \"../../main\";\nimport {IntroScreen} from \"../IntroScreen/IntroScreen\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\n\nexport class InteractScreen extends Screen {\n\n private readonly text: PIXI.Text;\n private readonly text2: PIXI.Text;\n private readonly textContainer = new PIXI.Container();\n private readonly textContainerContainer = new PIXI.Container();\n\n private readonly introTrack: Blob;\n private clickSound: AudioBuffer;\n\n private readonly clickArea: PIXI.Graphics = new PIXI.Graphics();\n\n public constructor(introTrack: Blob, clickSound: AudioBuffer) {\n super();\n this.introTrack = introTrack;\n this.clickSound = clickSound;\n\n this.text = new PIXI.Text({\n text: \"Click anywhere to play!\",\n style: {\n fontFamily: 'TorusRegular',\n fontSize: 36,\n fill: \"white\"\n }\n });\n this.text2 = new PIXI.Text({\n text: \"(this is for enabling audio because it's required by web-browsers\\n to have interaction on this webpage before playing audio.)\",\n style: {\n fontFamily: 'TorusRegular',\n fontSize: 26,\n fill: \"gray\",\n align: \"center\"\n }\n });\n }\n\n public start() {\n this.text.anchor.set(0.5, 0.5);\n this.text2.anchor.set(0.5, 0.5);\n this.text2.position.set(0, this.text.height + 15);\n this.textContainer.addChild(this.text);\n this.textContainer.addChild(this.text2);\n this.textContainer.scale.set(0.5);\n this.textContainer.alpha = 0;\n this.textContainerContainer.addChild(this.textContainer);\n this.textContainerContainer.scale = Screen.getScaleBasedOffScreenSize();\n this.textContainerContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.addChild(this.textContainerContainer);\n\n this.clickArea.rect(0, 0, 1, 1);\n this.clickArea.fill(\"rgba(0,0,0,0)\");\n this.clickArea.width = this.getScreenWidth();\n this.clickArea.height = this.getScreenHeight();\n this.clickArea.position.set(0, 0);\n this.addChild(this.clickArea);\n\n this.clickArea.eventMode = \"static\";\n this.clickArea.cursor = \"pointer\";\n\n const clicked = () => {\n this.clickArea.eventMode = \"none\";\n Main.AudioEngine.PlayEffect(this.clickSound);\n Main.switchScreen(new IntroScreen(this.introTrack));\n document.body.style.cursor = \"none\";\n Main.pointerLock();\n Main.lockKeyboard();\n }\n\n this.clickArea.onclick = () => {\n clicked();\n\n }\n this.clickArea.ontap = () => {\n clicked();\n }\n Ease.getEase(this.textContainer).FadeIn(400, TWEEN.Easing.Quadratic.Out)\n .ScaleTo(1, 400, TWEEN.Easing.Quadratic.Out);\n }\n\n public onClose(): Promise {\n return new Promise((resolve) => {\n Ease.getEase(this.textContainer).FadeOut(200, TWEEN.Easing.Quadratic.Out)\n .ScaleTo(0.5, 200, TWEEN.Easing.Quadratic.InOut);\n setTimeout(() => {\n resolve(this);\n }, 200);\n });\n }\n\n public draw(deltaTime: Ticker) {\n\n }\n\n public onResize() {\n this.textContainerContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.clickArea.width = this.getScreenWidth();\n this.clickArea.height = this.getScreenHeight();\n this.clickArea.position.set(0, 0);\n this.textContainerContainer.scale = Screen.getScaleBasedOffScreenSize();\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\n\nexport class GlitchingTriangles extends PIXI.Container {\n public constructor(bounds: GlitchingTrianglesBounds) {\n super();\n let triangle = new PIXI.Graphics();\n let scale = random(0.2, 1.2);\n triangle.moveTo(0, 0);\n triangle.lineTo(-50 * scale, 100 * scale);\n triangle.lineTo(50 * scale, 100 * scale);\n triangle.lineTo(0, 0);\n if (Math.random() < 0.5) {\n triangle.fill(\"white\");\n } else {\n triangle.stroke({color: \"white\", width: 1});\n }\n\n //triangle.anchor.set(0.5, 0.5)\n function random(min: number, max: number) {\n return Math.random() * (max - min) + min;\n }\n\n let randX = random(bounds.x1, bounds.x2);\n let randY = random(bounds.y1, bounds.y2);\n\n triangle.position.set(randX, randY);\n\n Ease.getEase(triangle, true).FadeOut(200, TWEEN.Easing.Linear.None);\n setTimeout(() => {\n this.destroy();\n }, 200);\n\n this.addChild(triangle);\n }\n\n}\n\nexport interface GlitchingTrianglesBounds {\n x1: number;\n x2: number;\n y1: number;\n y2: number;\n}\n","import {Screen} from \"../Screen\";\nimport * as PIXI from \"pixi.js\";\nimport {Ticker} from \"pixi.js\";\nimport {unzip} from 'unzipit';\nimport {Main} from \"../../main\";\nimport {GlitchingTriangles} from \"./GlitchingTriangles\";\nimport {MainMenu} from \"../MainMenu/MainMenu\";\nimport {LazerLogo} from \"./LazerLogo\";\nimport {BeatmapParser} from \"../../Util/Beatmap/Parser/BeatmapParser\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport {UIUtils} from \"../../Util/UI/UIUtils\";\nimport {CenteredList} from \"../../Util/UI/CenteredList\";\nimport {BeatmapData} from \"../../Util/Beatmap/Data/BeatmapData\";\n\nexport class IntroScreen extends Screen {\n\n private readonly introTrackUrl: string;\n\n private doTextSpacingAnim = false;\n private triangles = new PIXI.Container();\n private ruleSetContainer = new PIXI.Container();\n private ruleSetList = new CenteredList({});\n private flash = new PIXI.Graphics();\n\n private logoContainerContainer = new PIXI.Container();\n\n private logoContainer = new PIXI.Container();\n\n private lazerLogo = new LazerLogo();\n\n private flashed = false;\n\n private standard = PIXI.Sprite.from('icon_ruleset_std');\n private taiko = PIXI.Sprite.from('icon_ruleset_taiko');\n private ctb = PIXI.Sprite.from('icon_ruleset_ctb');\n private mania = PIXI.Sprite.from('icon_ruleset_mania');\n\n private bg: PIXI.Graphics = new PIXI.Graphics();\n\n private completionPromise!: Promise;\n\n private welcomeText: PIXI.Text = new PIXI.Text({\n text: \"\",\n style: {\n fontFamily: \"TorusThin\",\n fontSize: 42,\n fill: \"white\",\n letterSpacing: 5\n }\n });\n\n public constructor(introTrack: Blob) {\n super();\n this.introTrackUrl = URL.createObjectURL(introTrack);\n this.bg.rect(0, 0, 1, 1,);\n this.bg.fill(\"black\");\n }\n\n public start() {\n this.bg.width = window.innerWidth;\n this.bg.height = window.innerHeight;\n this.bg.x = 0;\n this.bg.y = 0;\n this.addChild(this.bg);\n this.lazerLogo.scale.set(Screen.getScaleBasedOffScreenSize());\n this.logoContainer.addChild(this.lazerLogo);\n this.logoContainer.scale.set(1.2);\n\n this.logoContainerContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.logoContainerContainer.pivot.set(0.5, 0.5);\n this.logoContainerContainer.addChild(this.logoContainer);\n this.logoContainerContainer.alpha = 0;\n this.addChild(this.logoContainerContainer);\n\n this.flash.rect(0, 0, 1, 1);\n this.flash.fill(\"white\");\n this.flash.position.set(0, 0);\n this.flash.width = this.getScreenWidth();\n this.flash.height = this.getScreenHeight();\n this.flash.blendMode = \"add\";\n this.welcomeText.anchor.set(0.5, 0.5);\n this.welcomeText.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n (async () => {\n const {entries} = await unzip(this.introTrackUrl);\n for (const [name, entry] of Object.entries(entries)) {\n if (name.endsWith(\".osu\")) {\n entry.text().then(async (osuFile) => {\n let beatmapData = new BeatmapData();\n await new Promise((resolve) => {\n for (const [name, entry] of Object.entries(entries)) {\n entry.blob().then((blob) => {\n beatmapData.files.set(name, blob);\n if (beatmapData.files.size == Object.entries(entries).length){\n resolve();\n }\n })\n }\n });\n let SBFile: string | undefined;\n for (const [name, entry] of beatmapData.files.entries()) {\n if (name.endsWith(\".osb\")){\n SBFile = await entry.text();\n }\n }\n BeatmapParser.Parse(osuFile, beatmapData, SBFile);\n await BeatmapParser.LoadFiles(beatmapData, Main.AudioEngine);\n let audioFile = beatmapData.General.audioFile;\n if (audioFile) {\n let url = URL.createObjectURL(audioFile);\n setTimeout(() => {\n Main.AudioEngine.PlayMusicImmediately(url, beatmapData, () => {\n this.afterAudioPlay();\n });\n }, 200);\n }\n console.log(beatmapData);\n });\n break;\n }\n }\n })();\n }\n\n public afterAudioPlay() {\n this.completionPromise = new Promise((resolve) => {\n this.welcomeText.scale.set(Screen.getScaleBasedOffScreenSize());\n this.addChild(this.welcomeText);\n setTimeout(() => {\n this.welcomeText.text = \"wel\";\n this.onResize();\n }, 200);\n setTimeout(() => {\n this.welcomeText.text = \"welcome\";\n this.onResize();\n }, 400);\n setTimeout(() => {\n this.welcomeText.text = \"welcome to\";\n this.onResize();\n }, 700);\n let glitchingInterval: NodeJS.Timeout;\n\n this.triangles.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.triangles.scale.set(Screen.getScaleBasedOffScreenSize());\n this.addChild(this.triangles);\n setTimeout(() => {\n this.welcomeText.text = \"welcome to kosu!\";\n this.doTextSpacingAnim = true;\n glitchingInterval = setInterval(() => {\n let triangle = new GlitchingTriangles({\n x1: -(this.welcomeText.width / 2) - 100,\n x2: (this.welcomeText.width / 2) + 100,\n y1: -(this.welcomeText.height / 2) - 150,\n y2: (this.welcomeText.height / 2) + 100\n });\n this.triangles.addChild(triangle);\n }, 30);\n this.onResize();\n }, 900);\n\n this.standard.scale = 0.5 * Screen.getScaleBasedOffScreenSize();\n this.ctb.scale = 0.5 * Screen.getScaleBasedOffScreenSize();\n this.mania.scale = 0.5 * Screen.getScaleBasedOffScreenSize();\n this.taiko.scale = 0.5 * Screen.getScaleBasedOffScreenSize();\n\n\n this.ruleSetList.addChild(this.standard);\n this.ruleSetList.addChild(this.taiko);\n this.ruleSetList.addChild(this.ctb);\n this.ruleSetList.addChild(this.mania);\n this.ruleSetList.padding = 0;\n this.ruleSetList.elementsMargin = 200 * Screen.getScaleBasedOffScreenSize();\n this.ruleSetList.type = \"horizontal\";\n this.ruleSetList.scale = 1;\n this.ruleSetContainer.addChild(this.ruleSetList);\n\n setTimeout(() => {\n this.doTextSpacingAnim = false;\n this.onResize();\n clearInterval(glitchingInterval);\n this.welcomeText.destroy();\n this.triangles.destroy();\n this.ruleSetContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.addChild(this.ruleSetContainer);\n this.ruleSetList.elementsMargin = 200 * Screen.getScaleBasedOffScreenSize();\n Ease.getEase(this.ruleSetContainer).ScaleTo(0.8, 1000, TWEEN.Easing.Linear.None);\n }, 1450);\n\n setTimeout(() => {\n this.ruleSetList.elementsMargin = 30 * Screen.getScaleBasedOffScreenSize();\n this.ruleSetList.scale = 2;\n UIUtils.centerPivotOfList(this.ruleSetList);\n }, 1650);\n\n setTimeout(() => {\n this.ruleSetList.elementsMargin = 10 * Screen.getScaleBasedOffScreenSize();\n this.ruleSetList.scale = 4;\n Ease.getEase(this.ruleSetContainer).ScaleTo(1.3, 1000, TWEEN.Easing.Linear.None);\n }, 1850);\n\n setTimeout(() => {\n this.ruleSetContainer.destroy();\n this.lazerLogo.start();\n\n this.logoContainerContainer.alpha = 1;\n\n this.logoContainerContainer.scale.set(1.2);\n Ease.getEase(this.logoContainerContainer).ScaleTo(1.2 - 0.8 * 0.25, 920, TWEEN.Easing.Quadratic.In);\n\n setTimeout(() => {\n Ease.getEase(this.logoContainer).ScaleTo(1.2 - 0.8, 920 * 0.3, TWEEN.Easing.Quintic.In);\n }, 920 * 0.7);\n }, 2080);\n\n setTimeout(() => {\n this.addChild(this.flash);\n this.bg.destroy();\n this.flash.eventMode = \"none\";\n this.flashed = true;\n this.logoContainerContainer.visible = false;\n Ease.getEase(this.flash).FadeOut(1000, TWEEN.Easing.Quadratic.Out).Then(() => {\n resolve();\n });\n Main.cursor.PopIn();\n }, 3000);\n });\n Main.switchScreen(new MainMenu());\n }\n\n public draw(deltaTime: Ticker) {\n if (this.doTextSpacingAnim) {\n this.welcomeText.style.letterSpacing += 0.15 * deltaTime.deltaTime;\n this.onResize();\n }\n }\n\n public onClose(): Promise {\n return new Promise((resolve) => {\n this.completionPromise.then(() => {\n resolve(this);\n })\n });\n }\n\n public onResize() {\n if (!this.bg.destroyed) {\n this.bg.width = window.innerWidth;\n this.bg.height = window.innerHeight;\n this.bg.x = 0;\n this.bg.y = 0;\n }\n if (!this.welcomeText.destroyed) {\n this.welcomeText.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n }\n if (!this.triangles.destroyed) {\n this.triangles.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.triangles.scale.set(Screen.getScaleBasedOffScreenSize());\n }\n if (!this.ruleSetContainer.destroyed) {\n this.ruleSetContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n }\n if (!this.flash.destroyed) {\n this.flash.position.set(0, 0);\n this.flash.width = this.getScreenWidth();\n this.flash.height = this.getScreenHeight();\n }\n if (!this.logoContainerContainer.destroyed) {\n this.logoContainerContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n }\n if (!this.lazerLogo.destroyed) {\n this.lazerLogo.scale.set(Screen.getScaleBasedOffScreenSize());\n }\n if (!this.welcomeText.destroyed) {\n this.welcomeText.scale.set(Screen.getScaleBasedOffScreenSize());\n }\n if (!this.standard.destroyed) {\n this.standard.scale.set(0.5 * Screen.getScaleBasedOffScreenSize());\n }\n if (!this.mania.destroyed) {\n this.mania.scale.set(0.5 * Screen.getScaleBasedOffScreenSize());\n }\n if (!this.ctb.destroyed) {\n this.ctb.scale.set(0.5 * Screen.getScaleBasedOffScreenSize());\n }\n if (!this.taiko.destroyed) {\n this.taiko.scale.set(0.5 * Screen.getScaleBasedOffScreenSize());\n }\n if (!this.ruleSetList.destroyed) {\n this.ruleSetList.ReCenter();\n }\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport {LogoAnimation} from \"./LogoAnimation\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\n\nexport class LazerLogo extends PIXI.Container {\n private readonly highlight: LogoAnimation;\n private readonly background: LogoAnimation;\n private textureHighlight = PIXI.Texture.from(\"intro_triangles_osuLogo_anim_highlight\");\n private textureBackground = PIXI.Texture.from(\"intro_triangles_osuLogo_anim_background\");\n\n public constructor() {\n super();\n this.highlight = new LogoAnimation(this.textureHighlight, new PIXI.Color(\"white\"));\n this.background = new LogoAnimation(this.textureBackground, new PIXI.Color(\"rgb(128, 128, 128)\"));\n this.addChild(this.highlight);\n this.addChild(this.background);\n }\n\n public start() {\n let dummy = new PIXI.Container();\n dummy.scale.set(0.0, 0.0);\n Ease.getEase(dummy).ScaleTo(1, 920, TWEEN.Easing.Linear.None).OnEach(() => {\n this.highlight.setProgress(dummy.scale.x);\n this.background.setProgress(dummy.scale.x);\n });\n }\n}\n","import * as PIXI from \"pixi.js\"\nimport glVertShader from \"./logoAnimation.vert\";\nimport glFragShader from \"./logoAnimation.frag\";\nimport gpuShader from \"./logoAnimation.wgsl\";\n\nexport class LogoAnimation extends PIXI.Container {\n private shader: PIXI.Shader;\n private texture: PIXI.Texture;\n\n public constructor(texture: PIXI.Texture, color: PIXI.Color) {\n super();\n this.texture = texture\n this.shader = PIXI.Shader.from({\n gl: {\n vertex: glVertShader,\n fragment: glFragShader,\n },\n gpu: {\n vertex: {\n entryPoint: 'mainVert',\n source: gpuShader\n },\n fragment: {\n entryPoint: 'mainFrag',\n source: gpuShader\n }\n },\n resources: {\n uTexture: this.texture.source,\n uSampler: this.texture.source.style,\n uProgress: {\n progress: {value: 0.0, type: 'f32'},\n },\n },\n });\n const quadGeometry = new PIXI.Geometry({\n attributes: {\n aPosition: [\n -this.texture.width / 2,\n -this.texture.height / 2, // x, y\n this.texture.width / 2,\n -this.texture.height / 2, // x, y\n this.texture.width / 2,\n this.texture.width / 2, // x, y,\n -this.texture.width / 2,\n this.texture.width / 2, // x, y,\n ],\n aUV: [0, 0, 1, 0, 1, 1, 0, 1],\n aColor: [\n color.red, color.green, color.blue, color.alpha,\n color.red, color.green, color.blue, color.alpha,\n color.red, color.green, color.blue, color.alpha,\n color.red, color.green, color.blue, color.alpha\n ]\n },\n indexBuffer: [0, 1, 2, 0, 2, 3],\n });\n const quad = new PIXI.Mesh({\n geometry: quadGeometry,\n shader: this.shader,\n });\n this.addChild(quad);\n }\n\n public setProgress(progress: number) {\n this.shader.resources.uProgress.uniforms.progress = progress;\n }\n}\n","import {Screen} from \"../Screen\";\nimport {LoadAnim} from \"../../Elements/LoadAnim/LoadAnim\";\nimport * as PIXI from \"pixi.js\";\n\nexport class LoadScreen extends Screen {\n\n private loadAnim = new LoadAnim(\"rgba(255,255,255,0.7)\", \"black\");\n\n public start() {\n this.loadAnim.scale.set(0.8 * Screen.getScaleBasedOffScreenSize());\n this.loadAnim.position.set(this.getScreenWidth() - this.loadAnim.getWidth() - 15, this.getScreenHeight() - this.loadAnim.getHeight() - 15);\n this.addChild(this.loadAnim);\n }\n\n public draw(deltaTime: PIXI.Ticker) {\n this.loadAnim?.draw(deltaTime);\n }\n\n public onClose(): Promise {\n return new Promise((resolve) => {\n if (this.loadAnim != null) {\n this.loadAnim.destroy();\n }\n setTimeout(() => {\n resolve(this);\n }, 400);\n });\n }\n\n public onResize() {\n this.loadAnim.position.set(this.getScreenWidth() - this.loadAnim.getWidth() - 20, this.getScreenHeight() - this.loadAnim.getHeight() - 20);\n this.loadAnim.scale.set(0.8 * Screen.getScaleBasedOffScreenSize());\n }\n}\n","import {Screen} from \"../Screen\";\nimport * as PIXI from \"pixi.js\";\nimport {RandomBackground} from \"../../Elements/RandomBackground/RandomBackground\";\nimport {OsuLogo} from \"../../Elements/MainMenu/OsuCircle/OsuLogo\";\nimport {ButtonSystem} from \"../../Elements/MainMenu/OsuCircle/Menu/ButtonSystem\";\n\nexport class MainMenu extends Screen {\n private bg = new RandomBackground();\n private osuCircle = new OsuLogo();\n private menu: ButtonSystem = new ButtonSystem(this.osuCircle);\n\n public start() {\n this.bg.start();\n this.addChild(this.bg);\n this.osuCircle.scale = Screen.getScaleBasedOffScreenSize();\n this.addChild(this.menu);\n this.menu.onResize();\n this.addChild(this.osuCircle);\n }\n\n public draw(deltaTime: PIXI.Ticker) {\n this.bg.draw(deltaTime);\n this.osuCircle.draw(deltaTime);\n }\n\n public onClose(): Promise {\n return new Promise((resolve) => {\n this.bg.onClose().then(() => {\n resolve(this);\n });\n })\n }\n\n public onResize() {\n this.osuCircle.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.bg.onResize();\n this.menu.onResize();\n this.osuCircle.scale = !this.menu.isOpen() ? Screen.getScaleBasedOffScreenSize() :\n Screen.getScaleBasedOffScreenSize() * 0.5;\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport {Settings} from \"../Settings/Settings\";\nimport {UIScale} from \"../Settings/impl/Graphics/UIScale\";\n\nexport abstract class Screen extends PIXI.Container {\n\n public constructor() {\n super();\n }\n\n public static getScaleBasedOffScreenSize() {\n // this was made with 1080p screens in mind.\n const uiScale = Settings.getSetting(UIScale).getValue();\n return ((((window.innerWidth / 1920) + (window.innerHeight / 1080)) / 2)) * uiScale\n }\n\n /**\n * Called once before the first frame is drawn\n */\n public abstract start(): void;\n\n\n /**\n * Called every frame\n */\n public abstract draw(deltaTime: PIXI.Ticker): void;\n\n /**\n * Called when screen will be closed, but has to return a promise to clean up after, for example, the screen's close animations are done.\n * Make sure you also pass in `this` into the promise's resolve.\n */\n public abstract onClose(): Promise;\n\n public abstract onResize(): void;\n\n protected getScreenWidth(): number {\n return window.innerWidth;\n }\n\n protected getScreenHeight(): number {\n return window.innerHeight;\n }\n}\n","import {Settings} from \"./Settings\";\n\nexport abstract class Setting {\n public readonly info: Settings;\n\n public constructor(SettingData: SettingInfo) {\n this.info = SettingData;\n Settings.register({setting: this, info: SettingData});\n }\n\n public abstract getValue(): any;\n\n public abstract getDefaultValue(): any;\n\n public abstract setValue(value: any): void;\n\n protected onValueChanged(): void {}\n\n /** When implementing this method, do **NOT** save the settings. This is so that loading won't reset most settings. */\n public abstract loadFromSaveValue(value: any): void;\n}\n\nexport interface SettingInfo {\n name: string;\n category: SettingsCategory;\n}\n\nexport enum SettingsCategory {\n General = \"General\",\n Skin = \"Skin\",\n Input = \"Input\",\n UserInterface = \"User Interface\",\n Gameplay = \"Gameplay\",\n Rulesets = \"Rulesets\",\n Audio = \"Audio\",\n Graphics = \"Graphics\",\n Online = \"Online\",\n Maintenance = \"Maintenance\",\n Debug = \"Debug\"\n}\n","import {Setting} from \"../Setting\";\nimport {Settings} from \"../Settings\";\n\nexport abstract class DropdownSetting extends Setting {\n public abstract readonly list: DropDownOption[];\n public abstract readonly defaultValue: DropDownOption;\n protected value: DropDownOption | undefined;\n\n public getValue(): DropDownOption {\n if (!this.value)\n throw new Error(\"Value is undefined!\");\n return this.value;\n }\n\n public getDefaultValue(): DropDownOption {\n return this.defaultValue;\n }\n\n public setValue(value: DropDownOption) {\n if (this.list.find((option) => option.value == value.value && option.displayName == value.displayName )) {\n this.value = value;\n Settings.save();\n this.onValueChanged();\n } else {\n console.warn('The value provided to this DropDownSetting does not exist in the option list! Ignoring value provided.');\n }\n }\n\n public loadFromSaveValue(value: DropDownOption) {\n if (this.list.find((option) => option.value == value.value && option.displayName == value.displayName)) {\n this.value = value;\n this.onValueChanged();\n } else {\n console.warn('The value provided to this DropDownSetting does not exist in the option list! Ignoring value provided.');\n }\n }\n}\n\nexport interface DropDownOption {\n displayName: string;\n value: string;\n}\n","import {Setting} from \"../Setting\";\nimport {Settings} from \"../Settings\";\nimport {MathUtil} from \"../../Util/MathUtil\";\n\nexport abstract class RangeSetting extends Setting {\n public abstract readonly minValue: number;\n public abstract readonly maxValue: number;\n public abstract readonly increment: number;\n public abstract readonly defaultValue: number;\n protected value: number = 0;\n\n public getValue(): number {\n return this.value;\n }\n\n public getDefaultValue(): number {\n return this.defaultValue;\n }\n\n public setValue(value: number) {\n this.value = MathUtil.clamp(this.minValue, this.maxValue, value);\n Settings.save();\n this.onValueChanged();\n }\n\n public loadFromSaveValue(value: number) {\n this.value = MathUtil.clamp(this.minValue, this.maxValue, value);\n this.onValueChanged();\n }\n}\n","import {Setting, SettingInfo} from \"./Setting\";\nimport {UIScale} from \"./impl/Graphics/UIScale\";\nimport {Renderer} from \"./impl/Graphics/Renderer\";\nimport {MouseSensitivity} from \"./impl/Input/MouseSensitivity\";\n\nexport class Settings {\n private static settingsList: SettingData[] = [];\n\n public static registerAll() {\n new UIScale();\n new Renderer();\n new MouseSensitivity();\n }\n\n public static load() {\n let settingSaveDataString = window.localStorage.getItem(\"settings\");\n if (settingSaveDataString == null) {\n return;\n }\n let settings = this.getList();\n try {\n let settingSaveData: SettingSaveData[] = JSON.parse(settingSaveDataString) as SettingSaveData[];\n settingSaveData.forEach((setting) => {\n let corrupt = false;\n try {\n if (!setting.value) {\n console.warn(\"Setting '\" + JSON.stringify(setting) + \"' may be corrupted, skipping!\");\n corrupt = true;\n }\n if (setting.info) {\n if (!setting.info.name) {\n console.warn(\"Setting '\" + JSON.stringify(setting) + \"' may be corrupted, skipping!\");\n corrupt = true;\n }\n if (!setting.info.category) {\n console.warn(\"Setting '\" + JSON.stringify(setting) + \"' may be corrupted, skipping!\");\n corrupt = true;\n }\n }\n else {\n console.warn(\"Setting '\" + JSON.stringify(setting) + \"' may be corrupted, skipping!\");\n corrupt = true;\n }\n }\n catch (e) {\n console.warn(\"Something went wrong when validating saved settings!\", e);\n console.warn(\"The setting may be REALLY corrupted, skipping!\");\n corrupt = true;\n }\n if (!corrupt) {\n let settingObj = settings.filter((_settingObj) => (_settingObj.info.name == setting.info.name) &&\n _settingObj.info.category == setting.info.category)[0];\n if (settingObj) {\n settingObj.setting.loadFromSaveValue(setting.value);\n } else {\n console.warn(\"Could not find setting object '\" + setting.info.name + \"', maybe it has been removed in this version of kosu?, skipping setting\")\n }\n }\n });\n }\n catch (e) {\n console.warn(\"Failed to load settings! Resetting Settings due to corrupted save!\", e);\n this.reset();\n }\n }\n\n public static save() {\n let settings = this.getList();\n let settingSaveData: SettingSaveData[] = [];\n settings.forEach((setting: SettingData) => {\n // only save if setting is different from default value\n if (setting.setting.getValue() != setting.setting.getDefaultValue()) {\n settingSaveData.push({info: setting.info, value: setting.setting.getValue()});\n }\n });\n window.localStorage.setItem(\"settings\", JSON.stringify(settingSaveData));\n }\n\n public static reset() {\n console.warn(\"Resetting Settings!\");\n window.localStorage.removeItem(\"settings\");\n }\n\n public static register(setting: SettingData) {\n this.settingsList.push(setting);\n }\n\n public static getSetting(setting: new (...args: any[]) => T): T {\n return this.settingsList.filter((_setting) => {\n return _setting.setting instanceof setting\n })[0].setting as T;\n }\n\n public static getSettingData(setting: new (...args: any[]) => T): SettingData {\n return this.settingsList.filter((_setting) => {\n return _setting.setting instanceof setting\n })[0];\n }\n\n public static getList() {\n return this.settingsList;\n }\n}\n\nexport interface SettingData {\n readonly setting: Setting;\n readonly info: SettingInfo;\n}\n\nexport interface SettingSaveData {\n readonly info: SettingInfo;\n readonly value: any;\n}\n","import {SettingsCategory} from \"../../Setting\";\nimport {DropDownOption, DropdownSetting} from \"../../SettingType/DropdownSetting\";\n\nexport class Renderer extends DropdownSetting {\n public readonly list: DropDownOption[] = [];\n\n public readonly webglOption: DropDownOption = {displayName: \"WebGL\", value: \"webgl\"}\n public readonly webGpuOption: DropDownOption = {displayName: \"WebGPU\", value: \"webgpu\"}\n public readonly defaultValue = this.webglOption;\n\n public constructor() {\n super({name: \"Renderer\", category: SettingsCategory.Graphics});\n this.list.push(this.webglOption, this.webGpuOption);\n this.value = this.defaultValue;\n }\n}\n","import {RangeSetting} from \"../../SettingType/RangeSetting\";\nimport {SettingsCategory} from \"../../Setting\";\n\nexport class UIScale extends RangeSetting {\n public readonly maxValue = 1.6;\n public readonly minValue = 0.8;\n public readonly increment = 0.1;\n public readonly defaultValue = 1;\n\n public constructor() {\n super({name: \"UI scaling\", category: SettingsCategory.Graphics});\n this.value = this.defaultValue;\n }\n}\n","import {RangeSetting} from \"../../SettingType/RangeSetting\";\nimport {SettingsCategory} from \"../../Setting\";\nimport {EventSystem} from \"pixi.js\";\n\nexport class MouseSensitivity extends RangeSetting{\n public readonly defaultValue: number = 1.0;\n public readonly increment: number = 0.01;\n public readonly maxValue: number = 10.0;\n public readonly minValue: number = 0.10;\n\n public constructor() {\n super({name: \"Sensitivity\", category: SettingsCategory.Input});\n this.value = this.defaultValue;\n this.onValueChanged();\n }\n\n public onValueChanged() {\n EventSystem.cursorSensitivity = this.getValue();\n }\n}\n","import {GeneralData} from \"./Sections/General/GeneralData\";\nimport {EditorData} from \"./Sections/Editor/EditorData\";\nimport {Metadata} from \"./Sections/Metadata/Metadata\";\nimport {DifficultyData} from \"./Sections/Difficulty/DifficultyData\";\nimport {EventsData} from \"./Sections/Events/EventsData\";\nimport {TimingPoint} from \"./Sections/TimingPoints/TimingPoint\";\nimport {TimingPointsData} from \"./Sections/TimingPoints/TimingPointsData\";\nimport {ColorsData} from \"./Sections/Colors/ColorsData\";\n\n/**\n * .osu (file format)\n */\nexport class BeatmapData {\n public files: Map = new Map();\n\n public formatVersion: number = -1;\n\n /**\n * General information about the beatmap\n */\n public General: GeneralData = new GeneralData();\n /**\n * Saved settings for the beatmap editor\n */\n public Editor: EditorData = new EditorData();\n /**\n * Information used to identify the beatmap\n */\n public Metadata: Metadata = new Metadata();\n /**\n * Difficulty settings\n */\n public Difficulty: DifficultyData = new DifficultyData();\n /**\n * Beatmap and storyboard graphic events\n */\n public Events: EventsData = new EventsData();\n /**\n * Timing and control points\n */\n public TimingPoints: TimingPointsData = new TimingPointsData();\n /**\n * Combo and skin colours\n */\n public Colors: ColorsData = new ColorsData();\n\n //TODO: add hitobject data\n\n}\n","import {Color} from \"./Color\";\n\n/**\n * \tCombo and skin colours\n */\nexport class ColorsData {\n public Colors: Color[] = [];\n}\n","/**\n * Difficulty settings\n */\nexport class DifficultyData {\n /**\n * HP setting (0–10)\n */\n public HPDrainRate!: number;\n /**\n * CS setting (0–10)\n */\n public CircleSize!: number;\n /**\n * OD setting (0–10)\n */\n public OverallDifficulty!: number;\n /**\n * AR setting (0–10)\n */\n public ApproachRate!: number;\n /**\n * Base slider velocity in hundreds of osu! pixels per beat\n */\n public SliderMultiplier!: number;\n /**\n * Amount of slider ticks per beat\n */\n public SliderTickRate!: number;\n}\n","/**\n * Saved settings for the beatmap editor\n */\nexport class EditorData {\n /**\n * Time in milliseconds of bookmarks\n */\n public Bookmarks: number[] = [];\n /**\n * Distance snap multiplier\n */\n public DistanceSpacing: number | undefined;\n /**\n * Beat snap divisor\n */\n public BeatDivisor: number | undefined;\n /**\n * Grid size\n */\n public GridSize: number | undefined;\n /**\n * Scale factor for the object timeline\n */\n public TimelineZoom: number | undefined;\n}\n","import {EventTypes} from \"./EventTypes\";\n\nexport class Event {\n /**\n * Type of the event. Some events may be referred to by either a name or a number.\n */\n public eventType!: EventTypes;\n /**\n * Start time of the event, in milliseconds from the beginning of the beatmap's audio. For events that do not use a start time, the default is 0.\n */\n public startTime: number = 0;\n}\n","import {Event} from \"./Event\";\nimport {EventTypes} from \"./EventTypes\";\nimport * as PIXI from \"pixi.js\";\n\nexport class EventBackground extends Event {\n public eventType = EventTypes.BACKGROUND;\n public startTime = 0;\n /**\n * Location of the background image relative to the beatmap directory. Double quotes are\n * usually included surrounding the filename, but they are not required.\n */\n public filename!: string;\n /**\n * Offset in osu! pixels from the centre of the screen.\n * For example, an offset of 50,100 would have the background shown 50 osu! pixels to the\n * right and 100 osu! pixels down from the centre of the screen. If the offset is 0,0, writing it is optional.\n */\n public xOffset!: number;\n /**\n * Offset in osu! pixels from the centre of the screen.\n * For example, an offset of 50,100 would have the background shown 50 osu! pixels to the\n * right and 100 osu! pixels down from the centre of the screen. If the offset is 0,0, writing it is optional.\n */\n public yOffset!: number;\n\n public texture?: PIXI.Texture;\n}\n","import {Event} from \"./Event\";\nimport {EventTypes} from \"./EventTypes\";\n\nexport class EventBreak extends Event {\n public eventType = EventTypes.BREAK;\n public endTime: number = 0;\n}","export enum EventTypes {\n BACKGROUND = \"Background\",\n VIDEO = \"Video\",\n BREAK = \"Break\",\n COLOR = \"Colour\",\n SPRITE = \"Sprite\",\n SAMPLE = \"Sample\",\n ANIMATION = \"Animation\"\n}\n","import {Event} from \"./Event\";\nimport {EventTypes} from \"./EventTypes\";\nimport * as PIXI from \"pixi.js\";\n\nexport class EventVideo extends Event {\n public eventType = EventTypes.VIDEO;\n /**\n * Location of the background video relative to the beatmap directory. Double quotes are\n * usually included surrounding the filename, but they are not required.\n */\n public filename!: string;\n /**\n * Offset in osu! pixels from the centre of the screen.\n * For example, an offset of 50,100 would have the background shown 50 osu! pixels to the\n * right and 100 osu! pixels down from the centre of the screen. If the offset is 0,0, writing it is optional.\n */\n public xOffset!: number;\n /**\n * Offset in osu! pixels from the centre of the screen.\n * For example, an offset of 50,100 would have the background shown 50 osu! pixels to the\n * right and 100 osu! pixels down from the centre of the screen. If the offset is 0,0, writing it is optional.\n */\n public yOffset!: number;\n\n\n public texture?: PIXI.Texture;\n}\n","import {Event} from \"./Event\";\n\n/**\n * Beatmap and storyboard graphic events\n */\nexport class EventsData {\n public Events: Event[] = [];\n}\n","import {EventStoryboard} from \"./EventStoryboard\";\nimport {EventTypes} from \"../EventTypes\";\nimport {LoopType} from \"./LoopType\";\nimport * as PIXI from \"pixi.js\";\n\nexport class EventAnimation extends EventStoryboard {\n public eventType = EventTypes.ANIMATION;\n public filepaths: string[] = [];\n /**\n * (frameCount) indicates how many frames the animation has.\n * If we have \"sample0.png\" and \"sample1.png\", for instance, our `frameCount = 2`.\n */\n public frameCount!: number;\n /**\n * (frameDelay) indicates how many milliseconds should be in between each frame.\n * For instance, if we wanted our animation to advance at 2 frames per second, `frameDelay = 500`.\n */\n public frameDelay!: number;\n /**\n * (looptype) indicates if the animation should loop or not. Valid values are:\n * - LoopForever (default if you leave this value off;\n * the animation will return to the first frame after finishing the last frame)\n * - LoopOnce (the animation will stop on the last frame and continue to display that last frame;\n * useful for, like, an animation of someone turning around)\n */\n public loopType!: LoopType;\n\n public textures: PIXI.Texture[] = [];\n}\n","import {EventStoryboard} from \"./EventStoryboard\";\nimport {EventTypes} from \"../EventTypes\";\n\nexport class EventSample extends EventStoryboard {\n public eventType = EventTypes.SAMPLE;\n public volume: number = 1; // 0 to 1\n public audioBuffer?: AudioBuffer;\n}\n","import {EventStoryboard} from \"./EventStoryboard\";\nimport {EventTypes} from \"../EventTypes\";\nimport * as PIXI from \"pixi.js\";\n\nexport class EventSprite extends EventStoryboard {\n public eventType = EventTypes.SPRITE;\n\n public texture?: PIXI.Texture;\n}\n","import {StoryboardCommand} from \"./Commands/StoryboardCommand\";\nimport {Event} from \"../Event\";\nimport {Layer} from \"./Layer\";\nimport {Origin} from \"./Origin\";\nimport * as PIXI from \"pixi.js\";\n\nexport abstract class EventStoryboard extends Event {\n public startTime = -1;\n /**\n * Each object declaration\n * is followed by one or more commands. These tell the object to do something, called an event,\n * such as move or change colour. You can think of each command as affecting a variable\n * (or set of variables) for that object; once a command is finished, the object keeps those values until\n * another command changes it. Objects who don't have a particular type of\n * command used will use the default value for that variable.\n */\n public Commands: StoryboardCommand[] = [];\n /**\n * (layer) is the layer\n * the object appears on.\n */\n public layer!: Layer;\n /**\n * (origin) is where on the image should osu! consider that image's origin (coordinate)\n * to be. This affects the (x) and (y) values, as well as several other command-specific\n * behaviours. For example, choosing (origin) = TopLeft will let the (x),(y) values determine,\n * where the top left corner of the image itself should be on the screen. The valid values are listed below.\n */\n public origin!: Origin;\n /**\n * (filepath) is, in laymans terms, the filename of the image you want. But it's not always quite that simple:\n * - If you have a subfolder inside your Song Folder, you need to include that, as well.\n * - Example: \"backgrounds/sky.jpg\" if you have a subfolder called \"backgrounds\" with an image called \"sky.jpg\" in it.\n * Start listing directories only from the Song Folder, where the .osu or .osb file is (i.e., a relative filepath).\n * It should not have something like \"C:\" anywhere in it.\n * - Animations are referred to without their number. So if you have \"sample0.png\" and \"sample1.png\" as two frames\n * to make a single animation, you want to refer to it as \"sample.png\".\n * - The \"\"s are technically optional, but they're required if your filename or subfolder name has spaces.\n * - Example: \"SB/J_K.jpg\" rather than SB/J_K.jpg. The prior will find in SB folder for J_K.jpg while the later will\n * null the instance (it finds SB/J, an invalid variable).\n */\n public filepath!: string;\n /**\n * (x) and (y) are the x-/y-coordinates of where the object should be, by default respectively.\n * The interpretation of this depends on the value of (origin);\n * for instance, to place a 640x480 image as your background,\n * the values could be:\n * - origin = TopLeft, x = 0, y = 0\n * - origin = Centre, x = 320, y = 240\n * - origin = BottomRight, x = 640, y = 480\n * - and so on.\n */\n public x: number = 0;\n /**\n * (x) and (y) are the x-/y-coordinates of where the object should be, by default respectively.\n * The interpretation of this depends on the value of (origin);\n * for instance, to place a 640x480 image as your background,\n * the values could be:\n * - origin = TopLeft, x = 0, y = 0\n * - origin = Centre, x = 320, y = 240\n * - origin = BottomRight, x = 640, y = 480\n * - and so on.\n */\n public y: number = 0;\n}\n","export enum Layer {\n Background = \"Background\",\n Fail = \"Fail\",\n Pass = \"Pass\",\n Foreground = \"Foreground\",\n}\nexport function convertToLayer(input: string) {\n let number = parseInt(input);\n if (isNaN(number)) {\n return input as Layer;\n } else {\n switch (number) {\n case 0:\n return Layer.Background;\n case 1:\n return Layer.Fail;\n case 2:\n return Layer.Pass;\n case 3:\n return Layer.Foreground;\n default:\n return Layer.Background;\n }\n }\n}\n","export enum LoopType {\n LoopForever = \"LoopForever\",\n LoopOnce = \"LoopOnce\"\n}\n\nexport function convertToLoopType(input: string) {\n let number = parseInt(input);\n if (isNaN(number)) {\n return input as LoopType\n }\n else {\n switch (number) {\n case 0:\n return LoopType.LoopForever;\n case 1:\n return LoopType.LoopOnce;\n default:\n return LoopType.LoopForever;\n }\n }\n}","export enum Origin {\n TopLeft = \"TopLeft\",\n Center = \"Centre\",\n CenterLeft = \"CentreLeft\",\n TopRight = \"TopRight\",\n BottomCenter = \"BottomCentre\",\n TopCenter = \"TopCentre\",\n /**\n * (same effect as TopLeft, but should not be used)\n */\n Custom = \"Custom\",\n CenterRight = \"CentreRight\",\n BottomLeft = \"BottomLeft\",\n BottomRight = \"BottomRight\"\n}\n\nexport function convertToOrigin(input: string) {\n let number = parseInt(input);\n if (isNaN(number)) {\n return input as Origin;\n } else {\n switch (number) {\n case 0:\n return Origin.TopLeft;\n case 1:\n return Origin.Center;\n case 2:\n return Origin.CenterLeft;\n case 3:\n return Origin.TopRight;\n case 4:\n return Origin.BottomCenter;\n case 5:\n return Origin.TopCenter;\n case 6:\n return Origin.Custom;\n case 7:\n return Origin.CenterRight;\n case 8:\n return Origin.BottomLeft;\n case 9:\n return Origin.BottomRight\n default:\n return Origin.TopLeft;\n }\n }\n}\n","export enum Countdown {\n NoCountdown = 0,\n Normal = 1,\n Half = 2,\n Double = 3\n}","import {Countdown} from \"./Countdown\";\nimport {SampleSet} from \"./SampleSet\";\nimport {Mode} from \"./Mode\";\nimport {OverlayPosition} from \"./OverlayPosition\";\n/**\n * General information about the beatmap\n */\nexport class GeneralData {\n\n public audioFile?: Blob;\n\n /**\n * Location of the audio file relative to the current folder.\n */\n public AudioFilename: string | null = null;\n /**\n * Milliseconds of silence before the audio starts playing\n */\n public AudioLeadIn: number = 0;\n /**\n * @deprecated The `AudioHash` property is deprecated according to the osu! wiki.\n */\n public AudioHash: string | null = null;\n /**\n * Time in milliseconds when the audio preview should start\n */\n public PreviewTime: number = -1;\n /**\n * Speed of the countdown before the first hit object (0 = no countdown, 1 = normal, 2 = half, 3 = double)\n */\n public Countdown: Countdown = Countdown.Normal;\n /**\n * Sample set that will be used if timing points do not override it (Normal, Soft, Drum)\n */\n public SampleSet: SampleSet = SampleSet.Normal;\n /**\n * Multiplier for the\n * threshold in time where hit objects placed close together stack (0–1)\n */\n public StackLeniency: number = 0.7;\n /**\n * Game mode (0 = osu!, 1 = osu!taiko, 2 = osu!catch, 3 = osu!mania)\n */\n public Mode: Mode = Mode.OSU;\n /**\n * Whether or not breaks have a letterboxing effect\n */\n public LetterboxInBreaks: boolean = false;\n /**\n * @deprecated The `StoryFireInFront` property is deprecated according to the osu! wiki.\n */\n public StoryFireInFront: boolean = true;\n /**\n * Whether or not the storyboard can use the user's skin images\n */\n public UseSkinSprites: boolean = false;\n /**\n * @deprecated The `AlwaysShowPlayfield` property is deprecated according to the osu! wiki.\n */\n public AlwaysShowPlayfield: boolean = false;\n /**\n * Draw order of hit circle overlays compared to hit numbers (NoChange = use skin setting,\n * Below = draw overlays under numbers, Above = draw overlays on top of numbers)\n */\n public OverlayPosition: OverlayPosition = OverlayPosition.NoChange;\n /**\n * Preferred skin to use during gameplay\n */\n public SkinPreference: string | null = null;\n /**\n * Whether or not a warning about flashing colours should be shown at the beginning of the map\n */\n public EpilepsyWarning: boolean = false;\n /**\n * Time in beats that the countdown starts before the first hit object\n */\n public CountdownOffset: number = 0;\n /**\n * Whether or not the \"N+1\" style key layout is used for osu!mania\n */\n public SpecialStyle: boolean = false;\n /**\n * Whether or not the storyboard allows widescreen viewing\n */\n public WidescreenStoryboard: boolean = false;\n /**\n * Whether or not sound samples will change rate when playing with speed-changing mods\n */\n public SamplesMatchPlaybackRate: boolean = false;\n}\n","export enum Mode {\n OSU = 0,\n TAIKO = 1,\n CATCH = 2,\n MANIA = 3\n}","export enum OverlayPosition {\n NoChange = \"NoChange\",\n Below = \"Below\",\n Above = \"Above\"\n}\n","export enum SampleSet {\n Normal = \"Normal\",\n Soft = \"Soft\",\n Drum = \"Drum\"\n}","/**\n * Information used to identify the beatmap\n */\nexport class Metadata {\n /**\n * Romanised song title\n */\n public Title!: string;\n /**\n * Song title\n */\n public TitleUnicode!: string;\n /**\n * Romanised song artist\n */\n public Artist!: string;\n /**\n * Song artist\n */\n public ArtistUnicode!: string;\n /**\n * Beatmap creator\n */\n public Creator!: string;\n /**\n * Difficulty name\n */\n public Version!: string;\n /**\n * Original media the song was produced for\n */\n public Source: string | undefined;\n /**\n * Search terms\n */\n public Tags!: string[];\n /**\n * Difficulty ID\n */\n public BeatmapID!: number;\n /**\n * Beatmap ID\n */\n public BeatmapSetID!: number;\n}\n","export enum Effect {\n KiaiTime = 1,\n None = 0,\n FirstBarLineOmittedInOsuTaikoAndOsuMania = 3\n}\n","import {TimingPoint} from \"./TimingPoint\";\n\nexport class InheritedTimingPoint extends TimingPoint {\n /**\n * a negative inverse slider velocity multiplier, as a percentage.\n * For example, `-50` would make all sliders in this timing section twice as fast as `SliderMultiplier`.\n */\n public sliderVelocityMultiplier!: number;\n\n}","import {TimingPointSampleSet} from \"./TimingPointSampleSet\";\nimport {Effect} from \"./Effect\";\n\nexport abstract class TimingPoint {\n /**\n * Start time of the timing section, in milliseconds from the beginning of the beatmap's audio.\n * The end of the timing section is the next timing point's time (or never, if this is the last timing point).\n */\n public time!: number;\n /**\n * Default sample set for hit objects (0 = beatmap default, 1 = normal, 2 = soft, 3 = drum).\n */\n public sampleSet!: TimingPointSampleSet;\n /**\n * Custom sample index for hit objects. 0 indicates osu!'s default hitsounds.\n */\n public sampleIndex!: number;\n /**\n * Volume percentage for hit objects.\n */\n public volume!: number;\n /**\n * Bit flags that give the timing point extra effects.\n * See the effects section.\n */\n public effects!: Effect\n}","import {TimingPoint} from \"./TimingPoint\";\nimport {UnInheritedTimingPoint} from \"./UnInheritedTimingPoint\";\nimport {InheritedTimingPoint} from \"./InheritedTimingPoint\";\n\n/**\n * Timing and control points\n */\nexport class TimingPointsData {\n public TimingPoints: TimingPoint[] = [];\n\n /**\n * Returns the current timing point in an array using the time provided.\n * If the current timing point is inherited, it will also return the parent\n * timing point along with it in the array as the second index.\n */\n public GetCurrentTimingPoints(time: number) {\n let toReturn: TimingPoint[] = [];\n let filter = this.TimingPoints.filter((timingPoint) => {if (timingPoint.time <= time) {return timingPoint}});\n if (filter.length == 0) {\n filter.push(this.TimingPoints[0]);\n }\n toReturn.push(filter[filter.length-1]);\n\n if (toReturn[0] instanceof InheritedTimingPoint) {\n let filter = this.TimingPoints.filter((timingPoint) => {return timingPoint instanceof UnInheritedTimingPoint})\n .filter((timingPoint) => {if (timingPoint.time <= time) {return timingPoint}});\n if (filter.length == 0) {\n throw new Error(\"Could not find a parent timing point for the un-inherited timing point!\");\n }\n toReturn.push(filter[filter.length-1]);\n }\n if (toReturn.length == 0) {\n throw new Error(\"Could not find any timing points!\");\n }\n return toReturn;\n }\n\n public GetCurrentUninheritedTimingPoint(time: number) {\n let timingPoint = this.GetCurrentTimingPoints(time);\n let unInheritedTimingPoint: UnInheritedTimingPoint;\n if (timingPoint[0] instanceof UnInheritedTimingPoint) {\n unInheritedTimingPoint = timingPoint[0];\n }\n else if(timingPoint[1] instanceof UnInheritedTimingPoint){\n unInheritedTimingPoint = timingPoint[1];\n }\n else {\n throw new Error(\"Could not find any UnInherited Timing Points!\")\n }\n return unInheritedTimingPoint;\n }\n\n}\n","import {TimingPoint} from \"./TimingPoint\";\n\nexport class UnInheritedTimingPoint extends TimingPoint {\n /**\n * The duration of a beat, in milliseconds.\n */\n public beatLength!: number;\n /**\n * Amount of beats in a measure.\n */\n public meter!: number;\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {TimingPointsParser} from \"./TimingPointsParser\";\nimport {GeneralParser} from \"./GeneralParser\";\nimport {EditorParser} from \"./EditorParser\";\nimport {MetadataParser} from \"./MetadataParser\";\nimport {DifficultyParser} from \"./DifficultyParser\";\nimport {EventsParser} from \"./EventsParser\";\nimport {AudioEngine} from \"../../../Audio/AudioEngine\";\n\nexport class BeatmapParser {\n public static Parse(osuFileContent: string, beatMapData = new BeatmapData(), storyBoardFileContent?: string): BeatmapData {\n let osuFileContentLines = osuFileContent.split(/\\r?\\n|\\r|\\n/g);\n let osuSBFileContentLines = storyBoardFileContent?.split(/\\r?\\n|\\r|\\n/g);\n for (let i = 0; i < osuFileContentLines.length; i++) {\n if (osuFileContentLines[i].startsWith(\"osu file format\")){\n let version = osuFileContentLines[i].split(\"v\")[1];\n beatMapData.formatVersion = parseFloat(version);\n }\n }\n\n GeneralParser.ParseGeneral(beatMapData, BeatmapParser.GetSection(\"General\", osuFileContentLines));\n EditorParser.ParseEditor(beatMapData, BeatmapParser.GetSection(\"Editor\", osuFileContentLines));\n MetadataParser.ParseMetadata(beatMapData, BeatmapParser.GetSection(\"Metadata\", osuFileContentLines));\n DifficultyParser.ParseDifficulty(beatMapData, BeatmapParser.GetSection(\"Difficulty\", osuFileContentLines));\n EventsParser.ParseEvents(beatMapData, BeatmapParser.GetSection(\"Events\", osuFileContentLines, osuSBFileContentLines));\n TimingPointsParser.ParseTimingPoints(beatMapData, BeatmapParser.GetSection(\"TimingPoints\", osuFileContentLines));\n return beatMapData\n }\n\n public static async LoadFiles(beatMapData: BeatmapData, audioEngine: AudioEngine) {\n await new Promise((resolve) => {\n let toLoad = 2;\n let loaded = 0;\n let check = () => {\n if (loaded == toLoad) {\n resolve();\n }\n }\n GeneralParser.LoadFiles(beatMapData); // this is not async\n loaded++;\n check();\n EventsParser.LoadFiles(beatMapData, audioEngine).then(() => {\n loaded++;\n check();\n });\n });\n }\n\n public static GetSection(sectionName: string, osuFileContentLines: string[], osuStoryBoardFileContentLines?: string[]) {\n let section: string[] = [];\n let index = 0;\n osuFileContentLines.forEach((str, i) => {\n if (str == \"[\" + sectionName + \"]\") {\n index = i;\n }\n });\n for (let i = index + 1; i < osuFileContentLines.length; i++) {\n if (osuFileContentLines[i] == \"\") {\n continue;\n }\n if (osuFileContentLines[i].startsWith(\"//\")) {\n continue;\n }\n if (osuFileContentLines[i].startsWith(\"[\")) {\n break;\n }\n section.push(osuFileContentLines[i]);\n }\n if (osuStoryBoardFileContentLines) {\n for (let i = 0; i < osuStoryBoardFileContentLines.length; i++) {\n if (osuStoryBoardFileContentLines[i] == \"\") {\n continue;\n }\n if (osuStoryBoardFileContentLines[i].startsWith(\"//\")) {\n continue;\n }\n if (osuStoryBoardFileContentLines[i].startsWith(\"[\" + sectionName + \"]\")) {\n continue;\n }\n section.push(osuStoryBoardFileContentLines[i]);\n }\n }\n return section;\n }\n\n public static AutoParse(sectionType: new (...args: any[]) => T, propValue: string[], beatmapDataSection: T) {\n let key = propValue[0] as keyof T;\n let keyExists = false;\n for (let sectionKey in beatmapDataSection) {\n if (sectionKey == key) {\n keyExists = true;\n }\n }\n if (!keyExists) {\n console.warn(key.toString() + \" does not exist on \" + sectionType.name + \"!\");\n return;\n }\n let isNumber = /^[0-9]+$|^[0-9]+\\.+[0-9]+$|^-[0-9]+$|^-[0-9]+\\.+[0-9]+$/.test(propValue[1]);\n let isBoolean = typeof beatmapDataSection[key] == \"boolean\";\n let value;\n if (isBoolean) {\n value = propValue[1] == \"1\";\n } else if (isNumber) {\n value = parseFloat(propValue[1]);\n } else {\n value = propValue[1];\n }\n\n // @ts-ignore\n beatmapDataSection[key] = value;\n }\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {BeatmapParser} from \"./BeatmapParser\";\nimport {DifficultyData} from \"../Data/Sections/Difficulty/DifficultyData\";\n\nexport class DifficultyParser {\n public static ParseDifficulty(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let propValue = str.split(\":\");\n if (propValue[1].startsWith(\" \")){\n propValue[1] = propValue[1].substring(1, propValue[1].length);\n }\n\n BeatmapParser.AutoParse(DifficultyData, propValue, beatmapData.Difficulty);\n });\n }\n\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {BeatmapParser} from \"./BeatmapParser\";\nimport {EditorData} from \"../Data/Sections/Editor/EditorData\";\n\nexport class EditorParser {\n public static ParseEditor(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let propValue = str.split(\":\");\n if (propValue[1].startsWith(\" \")){\n propValue[1] = propValue[1].substring(1, propValue[1].length);\n }\n if (propValue[0] != \"Bookmarks\") {\n BeatmapParser.AutoParse(EditorData, propValue, beatmapData.Editor);\n }\n else {\n propValue[1].split(\",\")\n .forEach((num) => {beatmapData.Editor.Bookmarks.push(parseFloat(num));});\n }\n });\n }\n\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {EventTypes} from \"../Data/Sections/Events/EventTypes\";\nimport {EventBackground} from \"../Data/Sections/Events/EventBackground\";\nimport {EventVideo} from \"../Data/Sections/Events/EventVideo\";\nimport {EventBreak} from \"../Data/Sections/Events/EventBreak\";\nimport {FFmpeg} from '@ffmpeg/ffmpeg';\nimport * as PIXI from \"pixi.js\";\nimport {Loader} from \"../../../Loader\";\nimport {EventSprite} from \"../Data/Sections/Events/Storyboard/EventSprite\";\nimport {convertToLayer} from \"../Data/Sections/Events/Storyboard/Layer\";\nimport {EventAnimation} from \"../Data/Sections/Events/Storyboard/EventAnimation\";\nimport {convertToOrigin} from \"../Data/Sections/Events/Storyboard/Origin\";\nimport {convertToLoopType, LoopType} from \"../Data/Sections/Events/Storyboard/LoopType\";\nimport {AudioEngine} from \"../../../Audio/AudioEngine\";\nimport {EventSample} from \"../Data/Sections/Events/Storyboard/EventSample\";\nimport {MathUtil} from \"../../MathUtil\";\n\nexport class EventsParser {\n public static aviTranscodedVideoCache: { beatmapSID: number, filePath: string, blob: Blob }[] = [];\n\n public static ParseEvents(beatmapData: BeatmapData, section: string[]) {\n console.log(section);\n let object;\n section.forEach((str) => {\n let values = str.split(\",\");\n let event;\n switch (values[0]) {\n case EventTypes.BACKGROUND:\n case \"0\":\n event = new EventBackground();\n event.filename = values[2].replaceAll('\"', \"\").replaceAll(\"\\\\\", \"/\");\n event.xOffset = parseFloat(values[3]);\n event.yOffset = parseFloat(values[4]);\n if (isNaN(event.xOffset)) {\n event.xOffset = 0;\n }\n if (isNaN(event.yOffset)) {\n event.yOffset = 0;\n }\n object = event;\n break;\n case EventTypes.VIDEO:\n case \"1\":\n event = new EventVideo();\n event.startTime = parseInt(values[1]);\n event.filename = values[2].replaceAll('\"', \"\").replaceAll(\"\\\\\", \"/\");\n event.xOffset = parseFloat(values[3]);\n event.yOffset = parseFloat(values[4]);\n if (isNaN(event.xOffset)) {\n event.xOffset = 0;\n }\n if (isNaN(event.yOffset)) {\n event.yOffset = 0;\n }\n object = event;\n break;\n case EventTypes.BREAK:\n case \"2\":\n event = new EventBreak();\n event.startTime = parseInt(values[1]);\n event.endTime = parseInt(values[2]);\n object = event;\n break;\n case EventTypes.COLOR:\n case \"3\":\n object = undefined; //ignore event for now\n break;\n case EventTypes.SPRITE:\n case \"4\":\n event = new EventSprite();\n event.layer = convertToLayer(values[1]);\n event.origin = convertToOrigin(values[2]);\n event.filepath = values[3].replaceAll('\"', \"\").replaceAll(\"\\\\\", \"/\");\n event.x = parseFloat(values[4]);\n event.y = parseFloat(values[5]);\n if (isNaN(event.x)) {\n event.x = 0;\n }\n if (isNaN(event.y)) {\n event.y = 0;\n }\n object = event;\n break;\n case EventTypes.SAMPLE:\n case \"5\":\n event = new EventSample();\n event.startTime = parseFloat(values[1]);\n event.layer = convertToLayer(values[2]);\n event.filepath = values[3].replaceAll('\"', \"\").replaceAll(\"\\\\\", \"/\");\n event.volume = values.length > 4 ? MathUtil.clamp01(parseFloat(values[4])/100) : 1;\n object = event;\n break;\n case EventTypes.ANIMATION:\n case \"6\":\n event = new EventAnimation();\n event.layer = convertToLayer(values[1]);\n event.origin = convertToOrigin(values[2]);\n event.filepath = values[3].replaceAll('\"', \"\").replaceAll(\"\\\\\", \"/\");\n let filePathWithNoFileExtension = event.filepath.substring(0, event.filepath.lastIndexOf(\".\"));\n for (let filePath of beatmapData.files.keys()) {\n if (filePath.startsWith(filePathWithNoFileExtension)){\n event.filepaths.push(filePath);\n }\n }\n event.filepaths.sort((a, b) => {\n //@ts-ignore\n let noExtA = parseInt(a.substring(filePathWithNoFileExtension.length, a.lastIndexOf(\".\")));\n //@ts-ignore\n let noExtB = parseInt(b.substring(filePathWithNoFileExtension.length, b.lastIndexOf(\".\")));\n return noExtA - noExtB;\n });\n event.x = parseFloat(values[4]);\n event.y = parseFloat(values[5]);\n if (isNaN(event.x)) {\n event.x = 0;\n }\n if (isNaN(event.y)) {\n event.y = 0;\n }\n event.frameCount = parseInt(values[6]);\n event.frameDelay = parseFloat(values[7]);\n\n if (beatmapData.formatVersion < 6) {\n // i don't understand this at all, but looks like the developers behind osu! lazer don't either\n // https://github.com/ppy/osu/blob/c46d787f1ef46827693dcfc334276e8b76b00d51/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs#L145\n event.frameDelay = Math.round(0.015 * event.frameDelay) * 1.186 * (1000 / 60);\n }\n\n event.loopType = values.length > 8 ? convertToLoopType(values[8]) : LoopType.LoopForever;\n console.log(event);\n object = event;\n break;\n }\n if (event) {\n beatmapData.Events.Events.push(event);\n }\n });\n }\n\n public static async LoadFiles(beatmapData: BeatmapData, audioEngine: AudioEngine) {\n await new Promise(async (resolve) => {\n let toLoad = beatmapData.Events.Events.filter((event) => {\n if ((\"filename\" in event && event.filename) || (\"filepath\" in event && event.filepath)) {\n return event;\n }\n });\n let loaded = 0;\n let check = () => {\n if (loaded == toLoad.length) {\n resolve();\n return;\n }\n }\n check(); // check because toLoad.length could be 0\n for (const event of toLoad) {\n for (let eventKey in event) {\n if (eventKey == \"filename\" || eventKey == \"filepath\") {\n // @ts-ignore\n let file = beatmapData.files.get(event[eventKey]);\n if (event instanceof EventAnimation) {\n file = new Blob();\n }\n if (file) {\n let url = URL.createObjectURL(file);\n if (event instanceof EventBackground) {\n PIXI.Assets.load({src: url, loadParser: \"loadTextures\"}).then((texture) => {\n event.texture = texture;\n loaded++;\n check();\n }).catch((e) => {\n console.warn(e);\n loaded++;\n check();\n });\n }\n if (event instanceof EventVideo) {\n let failed = false;\n // @ts-ignore\n if (event[eventKey].endsWith(\".avi\")) {\n // @ts-ignore\n let cacheHit = this.aviTranscodedVideoCache.find(\n (cache) => {\n // @ts-ignore\n if (cache.beatmapSID == beatmapData.Metadata.BeatmapSetID && cache.filePath == event[eventKey]) {\n return cache;\n }\n }\n );\n try {\n if (!cacheHit) {\n console.warn(\"AVI video is not natively supported! Transcoding to .mp4, this may take a few minutes!\");\n let ffmpeg = new FFmpeg();\n ffmpeg.on('progress', ({progress, time}) => {\n console.log(`.avi to .mp4 transcoding: ${Math.round(progress * 1000) / 10}% (transcoded time: ${Math.round(time / 100000) / 10}s)`);\n });\n console.log(\"FFmpeg initialized\");\n const baseURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm';\n let classWorker = Loader.Get(\"workers.ffmpeg\");\n let core = Loader.Get(\"ffmpeg.core\");\n let wasm = Loader.Get(\"ffmpeg.wasm\");\n let worker = Loader.Get(\"ffmpeg.coreWorker\");\n await ffmpeg.load({\n classWorkerURL: URL.createObjectURL(classWorker),\n coreURL: URL.createObjectURL(core),\n wasmURL: URL.createObjectURL(wasm),\n workerURL: URL.createObjectURL(worker)\n });\n console.log(\"FFmpeg loaded\");\n await ffmpeg.writeFile('input.avi', new Uint8Array(await file.arrayBuffer()));\n console.log(\"Written file to FFmpeg's vfs\");\n await ffmpeg.exec([\"-i\", \"input.avi\", \"-c:v\", \"libx264\", \"-preset\",\n \"ultrafast\", \"-an\", \"-movflags\", \"faststart\", \"output.mp4\"]);\n console.log(\"Transcoding done\");\n const data = await ffmpeg.readFile(\"output.mp4\");\n ffmpeg.terminate();\n console.log(\"FFmpeg terminated\");\n let newFile = new Blob([data], {type: 'video/mp4'});\n this.aviTranscodedVideoCache.push({\n beatmapSID: beatmapData.Metadata.BeatmapSetID,\n // @ts-ignore\n filePath: event[eventKey],\n blob: newFile\n });\n // @ts-ignore\n beatmapData.files.delete(event[eventKey]);\n // @ts-ignore\n event[eventKey] = event[eventKey].substring(0, event[eventKey].length - 4) + \".mp4\";\n // @ts-ignore\n beatmapData.files.set(event[eventKey], newFile);\n URL.revokeObjectURL(url);\n url = URL.createObjectURL(newFile);\n console.log(\"Successfully transcoded from .avi to .mp4!\");\n } else {\n // @ts-ignore\n beatmapData.files.delete(event[eventKey]);\n // @ts-ignore\n event[eventKey] = event[eventKey].substring(0, event[eventKey].length - 4) + \".mp4\";\n // @ts-ignore\n beatmapData.files.set(event[eventKey], cacheHit.blob);\n URL.revokeObjectURL(url);\n url = URL.createObjectURL(cacheHit.blob);\n }\n } catch (e) {\n console.warn(e);\n failed = true;\n }\n }\n if (!failed) {\n PIXI.Assets.load({src: url, loadParser: \"loadVideo\"}).then((texture) => {\n event.texture = texture;\n if (event.texture) {\n event.texture.source.resource.volume = 0;\n event.texture.source.resource.pause();\n }\n loaded++;\n check();\n }).catch((e) => {\n console.warn(e);\n loaded++;\n check();\n });\n } else {\n loaded++;\n check();\n }\n }\n if (event instanceof EventSprite) {\n PIXI.Assets.load({src: url, loadParser: \"loadTextures\"}).then((texture) => {\n event.texture = texture;\n loaded++;\n check();\n }).catch((e) => {\n console.warn(e);\n loaded++;\n check();\n });\n }\n if (event instanceof EventSample) {\n file.arrayBuffer().then((arrayBuffer) => {\n audioEngine.audioContext.decodeAudioData(arrayBuffer).then((audioBuffer) => {\n event.audioBuffer = audioBuffer;\n loaded++;\n check();\n }).catch((e) => {\n console.warn(e);\n loaded++;\n check();\n });\n })\n }\n if (event instanceof EventAnimation) {\n URL.revokeObjectURL(url);\n let loadedTextures = 0;\n let texturesNeededToLoad = event.filepaths.length;\n let checkLoadedTextures = () => {\n if (loadedTextures == texturesNeededToLoad) {\n loaded++;\n check();\n }\n }\n event.filepaths.forEach((filePath, i) => {\n let file = beatmapData.files.get(filePath);\n if (file) {\n let url = URL.createObjectURL(file);\n PIXI.Assets.load({src: url, loadParser: \"loadTextures\"}).then((texture) => {\n event.textures[i] = texture;\n loadedTextures++\n checkLoadedTextures();\n }).catch((e) => {\n console.warn(e);\n loadedTextures++;\n checkLoadedTextures();\n });\n }\n });\n }\n } else {\n // @ts-ignore\n console.warn(\"Could not find referenced file: \" + event[eventKey]);\n }\n }\n }\n }\n });\n }\n}","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {GeneralData} from \"../Data/Sections/General/GeneralData\";\nimport {BeatmapParser} from \"./BeatmapParser\";\n\nexport class GeneralParser {\n public static ParseGeneral(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let propValue = str.split(\":\");\n if (propValue[1].startsWith(\" \")) {\n propValue[1] = propValue[1].substring(1, propValue[1].length);\n }\n if (propValue[0] != \"AudioFilename\") {\n BeatmapParser.AutoParse(GeneralData, propValue, beatmapData.General);\n } else {\n beatmapData.General.AudioFilename = propValue[1].replaceAll(\"\\\\\", \"/\");\n }\n\n });\n }\n\n public static LoadFiles(beatmapData: BeatmapData) {\n if (beatmapData.General.AudioFilename) {\n beatmapData.General.audioFile = beatmapData.files.get(beatmapData.General.AudioFilename);\n }\n }\n\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {BeatmapParser} from \"./BeatmapParser\";\nimport {Metadata} from \"../Data/Sections/Metadata/Metadata\";\n\nexport class MetadataParser {\n public static ParseMetadata(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let propValue = str.split(\":\");\n if (propValue[1].startsWith(\" \")){\n propValue[1] = propValue[1].substring(1, propValue[1].length);\n }\n\n BeatmapParser.AutoParse(Metadata, propValue, beatmapData.Metadata);\n });\n }\n\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {UnInheritedTimingPoint} from \"../Data/Sections/TimingPoints/UnInheritedTimingPoint\";\nimport {InheritedTimingPoint} from \"../Data/Sections/TimingPoints/InheritedTimingPoint\";\nimport {Effect} from \"../Data/Sections/TimingPoints/Effect\";\n\nexport class TimingPointsParser {\n public static ParseTimingPoints(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let prop = str.split(\",\");\n let timingPoint;\n if (prop[6] == \"1\") {\n timingPoint = new UnInheritedTimingPoint();\n timingPoint.beatLength = Number.parseFloat(prop[1]);\n timingPoint.meter = Number.parseInt(prop[2]);\n }\n else {\n timingPoint = new InheritedTimingPoint();\n timingPoint.sliderVelocityMultiplier = Number.parseFloat(prop[1]);\n }\n timingPoint.time = Number.parseInt(prop[0]);\n timingPoint.sampleSet = Number.parseInt(prop[3]);\n timingPoint.sampleIndex = Number.parseInt(prop[4]);\n timingPoint.volume = Number.parseInt(prop[5]);\n if (prop[7] == \"1\" || prop[7] == \"3\"){\n timingPoint.effects = Number.parseInt(prop[7]);\n } else {\n timingPoint.effects = Effect.None;\n }\n\n beatmapData.TimingPoints.TimingPoints.push(timingPoint);\n });\n }\n}\n","export class MathUtil {\n public static RadiansToDegrees(radians: number) {\n return radians * 180 / Math.PI;\n }\n\n public static DegreesToRadians(degrees: number) {\n return degrees * Math.PI / 180;\n }\n\n public static clamp(min: number, max: number, value: number) {\n return Math.min(Math.max(value, min), max);\n }\n\n public static clamp01(value: number) {\n return MathUtil.clamp(0, 1, value);\n }\n\n public static Damp(start: number, final: number, base: number, exponent: number) {\n return MathUtil.Lerp(start, final, 1 - Math.pow(base, exponent));\n }\n\n public static Lerp(start: number, final: number, ammount: number) {\n return start + (final - start) * ammount;\n }\n\n}\n","import * as TWEEN from \"@tweenjs/tween.js\";\nimport * as PIXI from \"pixi.js\";\n\nexport class Ease {\n private static previousEases: Ease[] = [];\n private easings: Easing[] = [];\n private readonly obj: PIXI.Container;\n private delay: TWEEN.Tween | null = null;\n\n private constructor(obj: PIXI.Container, dontStore: boolean) {\n this.obj = obj;\n if (!dontStore) {\n Ease.previousEases.push(this);\n }\n }\n\n public static getEase(obj: PIXI.Container, dontStore?: boolean) {\n if (dontStore == null) {\n dontStore = false;\n }\n let checkIfEaseExists = Ease.previousEases.filter((ease) => {\n return ease.obj == obj;\n });\n if (checkIfEaseExists.length > 0) {\n return checkIfEaseExists[0];\n }\n return new Ease(obj, dontStore);\n }\n\n public createTween>(value: T, newValue: T, isPrimitive: boolean, property: keyof PIXI.Container, duration: number, easingFunc: (ammount: number) => number) {\n const tweenValue = {value: 0}\n const tween = new TWEEN.Tween(isPrimitive ? tweenValue : value);\n const easing = new Easing(tween);\n tween.to(isPrimitive ? {value: 1} : newValue, duration);\n tween.easing(easingFunc);\n tween.onUpdate(() => {\n if (!this.obj.destroyed) {\n if (!isPrimitive) {\n // @ts-ignore\n this.obj[property] = value;\n } else {\n // @ts-ignore\n this.obj[property] = (tweenValue.value * (newValue.value - value.value)) + value.value;\n }\n }\n easing.onUpdate();\n });\n\n tween.onStart(() => {\n if (isPrimitive) {\n // @ts-ignore\n value.value = this.obj[property];\n }\n });\n\n\n if (this.delay == null) {\n\n tween.start();\n } else {\n this.delay.chain(tween);\n this.delay = null;\n }\n this.easings.push(easing);\n\n tween.onStop(() => {\n this.onDone(tween);\n });\n tween.onComplete(() => {\n this.onDone(tween);\n });\n return this;\n }\n\n public TransformTo(newPosition: PIXI.PointData, duration: number, easing: (ammount: number) => number) {\n this.createTween(this.obj.position, newPosition, false, \"position\", duration, easing);\n return this;\n }\n\n private onDone(tween: TWEEN.Tween) {\n this.easings = this.easings.filter((tweenInArray) => {\n return tweenInArray.tween != tween\n })\n }\n\n public ScaleTo(newScale: PIXI.PointData | number, duration: number, easing: (ammount: number) => number) {\n let _newScale: PIXI.PointData = {x: 0, y: 0};\n if (typeof newScale == \"number\") {\n _newScale.x = newScale;\n _newScale.y = newScale;\n }\n this.createTween(this.obj.scale, _newScale, false, \"scale\", duration, easing);\n return this;\n }\n\n public FadeTo(newAlpha: number, duration: number, easing: (ammount: number) => number) {\n this.createTween({value: this.obj.alpha}, {value: newAlpha}, true, \"alpha\", duration, easing);\n return this;\n }\n\n public FadeOut(duration: number, easing: (ammount: number) => number) {\n this.FadeTo(0, duration, easing);\n return this;\n }\n\n public FadeIn(duration: number, easing: (ammount: number) => number) {\n this.FadeTo(1, duration, easing);\n return this;\n }\n\n public ClearEasings() {\n this.easings.forEach((tween) => {\n tween.tween.stop();\n });\n this.easings = [];\n return this;\n }\n\n public Then(cb?: () => void) {\n let largestDuration = this.easings.sort((a, b) => {\n return a.tween.getDuration() - b.tween.getDuration()\n });\n if (largestDuration.length > 0) {\n this.delay = largestDuration[0].tween;\n if (cb != undefined) {\n largestDuration[0].tween.onComplete(() => {this.onDone(largestDuration[0].tween); cb();});\n largestDuration[0].tween.onStop(() => {this.onDone(largestDuration[0].tween); cb();});\n }\n }\n return this;\n }\n\n public OnEach(cb: () => void) {\n let largestDuration = this.easings.sort((a, b) => {\n return a.tween.getDuration() - b.tween.getDuration()\n });\n if (largestDuration.length > 0) {\n largestDuration[0].registerOnUpdate(cb);\n }\n }\n}\n\nclass Easing {\n public tween: TWEEN.Tween;\n private updateEventListeners: (() => void)[] = [];\n public constructor(tween: TWEEN.Tween) {\n this.tween = tween;\n }\n public onUpdate() {\n this.updateEventListeners.forEach((eventListener) => {\n eventListener();\n })\n }\n public registerOnUpdate(cb: () => void) {\n this.updateEventListeners.push(cb);\n }\n public unRegisterOnUpdate(cb: () => void) {\n this.updateEventListeners = this.updateEventListeners.filter((ev) => {return !(cb === ev);});\n }\n}\n","import {List} from \"@pixi/ui\";\nimport {UIUtils} from \"./UIUtils\";\n\nexport class CenteredList extends List {\n public get elementsMargin() {\n return super.elementsMargin;\n }\n public set elementsMargin(margin: number) {\n super.elementsMargin = margin;\n UIUtils.centerPivotOfList(this);\n }\n\n\n public ReCenter() {\n UIUtils.centerPivotOfList(this);\n }\n}\n","import {List} from \"@pixi/ui\";\n\nexport class UIUtils {\n public static centerPivotOfList(list: List) {\n let width = list.leftPadding;\n let height = list.topPadding;\n for (let i = 0; i < list.children.length; i++) {\n let isLast = i + 1 == list.children.length;\n switch (list.type) {\n case \"horizontal\":\n width += list.children[i].width + (!isLast? list.elementsMargin : 0);\n height += list.children[i].height;\n break;\n case \"vertical\":\n width += list.children[i].width;\n height += list.children[i].height + (!isLast? list.elementsMargin : 0);\n break;\n default:\n width += list.children[i].width + (!isLast? list.elementsMargin : 0);\n height += list.children[i].height + (!isLast? list.elementsMargin : 0);\n break;\n }\n }\n switch (list.type) {\n case \"horizontal\":\n height /= list.children.length;\n break;\n case \"vertical\":\n width /= list.children.length;\n break;\n }\n width += list.rightPadding;\n height += list.bottomPadding;\n\n list.pivot.set(width/2, height/2);\n }\n}\n","import \"./style.css\";\nimport {Application, EventSystem} from \"pixi.js\";\nimport {Main} from \"./main\";\nimport {Settings} from \"./Settings/Settings\";\nimport {Renderer} from \"./Settings/impl/Graphics/Renderer\";\nimport {MouseSensitivity} from \"./Settings/impl/Input/MouseSensitivity\";\nimport {UIScale} from \"./Settings/impl/Graphics/UIScale\";\nSettings.registerAll();\nSettings.load();\nconst gameWidth = window.innerWidth;\nconst gameHeight = window.innerHeight;\n\nconst app = new Application();\n// @ts-ignore\nglobalThis.__PIXI_APP__ = app;\nwindow.onload = async (): Promise => {\n // @ts-ignore\n const renderer = Settings.getSetting(Renderer).getValue().value as \"webgl\" | \"webgpu\";\n app.init({\n backgroundColor: \"black\",\n width: gameWidth,\n height: gameHeight,\n antialias: true,\n preference: renderer,\n resolution: window.devicePixelRatio,\n autoDensity: true\n }).then(() => {\n new Main(app);\n });\n};\n\nnavigator.mediaSession.setActionHandler('play', () => {Main.AudioEngine.GetCurrentPlayingMusicNoSilent()?.Play();});\nnavigator.mediaSession.setActionHandler('pause', () => {Main.AudioEngine.GetCurrentPlayingMusicNoSilent()?.Pause();});\nnavigator.mediaSession.setActionHandler('stop', () => {});\nnavigator.mediaSession.setActionHandler('seekbackward', () => {});\nnavigator.mediaSession.setActionHandler('seekforward', () => {});\nnavigator.mediaSession.setActionHandler('seekto', () => {});\nnavigator.mediaSession.setActionHandler('previoustrack', () => {});\nnavigator.mediaSession.setActionHandler('nexttrack', () => {});\n\nObject.defineProperty(window, \"setSensitivity\", {value: (sensitivity: number) => {\n Settings.getSetting(MouseSensitivity).setValue(sensitivity);\n}});\n\nObject.defineProperty(window, \"setRenderer\", {value: (renderer: string) => {\n let rendererSetting = Settings.getSetting(Renderer);\n rendererSetting.setValue(renderer == \"webgl\" ? rendererSetting.webglOption : rendererSetting.webGpuOption);\n window.location.reload();\n}});\n\nObject.defineProperty(window, \"setUIScale\", {value: (scale: number) => {\n Settings.getSetting(UIScale).setValue(scale);\n window.location.reload();\n}});\n","import * as PIXI from \"pixi.js\";\nimport {Application} from \"pixi.js\";\nimport {Screen} from \"./Screens/Screen\";\nimport {LoadScreen} from \"./Screens/LoadScreen/LoadScreen\";\nimport {InteractScreen} from \"./Screens/InteractScreen/InteractScreen\";\nimport {Loader} from \"./Loader\";\nimport {MenuCursor} from \"./Elements/MenuCursor/MenuCursor\";\nimport {AudioEngine} from \"./Audio/AudioEngine\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {SettingsPane} from \"./Elements/Settings/SettingsPane\";\nimport {unzip} from \"unzipit\";\nimport {BeatmapParser} from \"./Util/Beatmap/Parser/BeatmapParser\";\nimport {BeatmapData} from \"./Util/Beatmap/Data/BeatmapData\";\n\nexport class Main {\n public static app: Application;\n public static mousePos = {x: 0, y: 0};\n public static pointerLockExitTime: number;\n public static cursor: MenuCursor;\n public static AudioEngine: AudioEngine;\n private static currentScreen: Screen | null;\n private static allScreens: Screen[] = [];\n private static clickArea: PIXI.Graphics = new PIXI.Graphics();\n private static doPointerLock: boolean = false;\n private static settingsPane: SettingsPane;\n private static processingOsuFile: boolean = false;\n\n public constructor(app: Application) {\n Main.app = app;\n // for testing purposes\n Main.setDropEvents();\n\n document.body.appendChild(Main.app.canvas);\n\n Main.settingsPane = new SettingsPane();\n Main.settingsPane.zIndex = 999998;\n Main.app.stage.addChild(Main.settingsPane);\n\n document.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (e.ctrlKey && e.code == \"KeyO\") {\n Main.settingsPane.toggle();\n }\n });\n\n this.doResize();\n window.addEventListener(\"resize\", this.doResize);\n Main.app.ticker.add(() => {\n TWEEN.update();\n })\n Main.app.stage.eventMode = \"static\";\n Main.AudioEngine = new AudioEngine();\n Main.app.stage.addEventListener(\"mousemove\", (e) => {\n Main.mousePos.x = e.clientX;\n Main.mousePos.y = e.clientY;\n if (Main.cursor) {\n Main.cursor.updateMouse();\n }\n });\n document.addEventListener(\"pointerlockchange\", this.pointerLockChanged, false);\n Main.switchScreen(new LoadScreen());\n Loader.Load(Main.AudioEngine.audioContext).then(() => {\n Main.cursor = new MenuCursor(false);\n let dialogOk = Loader.GetAudio(\"sample_dialog_ok\");\n let introTrack = Loader.Get(\"introTrianglesTrack\");\n Main.switchScreen(new InteractScreen(introTrack, dialogOk));\n });\n }\n\n // for testing purposes\n private static setDropEvents() {\n Object.defineProperty(window, \"onDropEvent\", {\n value: (e: DragEvent) => {\n e.preventDefault();\n if (Main.processingOsuFile) {\n alert(\"Another BeatMap is still processing. (Most likely transcoding a .avi file, check the console for progress) \" +\n \"Please wait for it to process and start playing before processing another one!\");\n return;\n }\n Main.processingOsuFile = true;\n if (e.dataTransfer!.items) {\n let item = [...e.dataTransfer!.items][0];\n if (item.kind == \"file\") {\n\n const file = item.getAsFile()!;\n unzip(file).then(({entries}) => {\n for (const [name, entry] of Object.entries(entries)) {\n if (name.endsWith(\".osu\")) {\n entry.text().then(async (osuFile) => {\n let beatmapData = new BeatmapData();\n await new Promise((resolve) => {\n for (const [name, entry] of Object.entries(entries)) {\n entry.blob().then((blob) => {\n beatmapData.files.set(name, blob);\n if (beatmapData.files.size == Object.entries(entries).length){\n resolve();\n }\n })\n }\n });\n let SBFile: string | undefined;\n for (const [name, entry] of beatmapData.files.entries()) {\n if (name.endsWith(\".osb\")){\n SBFile = await entry.text();\n }\n }\n BeatmapParser.Parse(osuFile, beatmapData, SBFile);\n await BeatmapParser.LoadFiles(beatmapData, Main.AudioEngine);\n let audioFile = beatmapData.General.audioFile;\n if (audioFile) {\n let url = URL.createObjectURL(audioFile);\n Main.AudioEngine.PlayMusicImmediately(url, beatmapData, () => {\n console.log(\"Now playing \" + beatmapData.Metadata.TitleUnicode + \" - \" + beatmapData.Metadata.ArtistUnicode +\n \" (\" + beatmapData.Metadata.Title + \" - \" + beatmapData.Metadata.Artist + \")\");\n });\n }\n Main.processingOsuFile = false;\n console.log(beatmapData);\n });\n break;\n }\n }\n });\n\n }\n }\n }\n });\n\n Object.defineProperty(window, \"onDragEvent\", {\n value: (e: DragEvent) => {\n e.preventDefault();\n }\n });\n Main.app.canvas.setAttribute(\"ondrop\", \"window.onDropEvent(event);\");\n Main.app.canvas.setAttribute(\"ondragover\", \"window.onDragEvent(event);\");\n }\n\n public static lockKeyboard() {\n // @ts-ignore\n if (navigator.keyboard) {\n // @ts-ignore\n navigator.keyboard.lock([]).then(() => {\n console.log(\"Locked keyboard!\");\n if (!document.fullscreenElement) {\n console.warn(\"Keyboard lock won't work unless the user is in fullscreen (as requested by the game, not if the user just presses F11)!\");\n }\n });\n }\n }\n\n public static pointerLock() {\n try {\n this.doPointerLock = true;\n // @ts-ignore\n Main.app.canvas.requestPointerLock({\n unadjustedMovement: true,\n });\n } catch (e) {\n console.warn(\"Failed to lock cursor, error:\", e);\n this.doPointerLock = false;\n }\n\n }\n\n public static exitPointerLock() {\n this.doPointerLock = false;\n // @ts-ignore\n Main.app.canvas.exitPointerLock();\n }\n\n public static switchScreen(screen: Screen) {\n if (this.currentScreen != null) {\n this.currentScreen.zIndex = 1;\n this.currentScreen.onClose().then((lastScreen) => {\n for (let i = 0; i < this.allScreens.length; i++) {\n if (this.allScreens[i] == lastScreen) {\n this.allScreens.splice(i, 1);\n }\n }\n Main.app.ticker.remove(lastScreen.draw);\n Main.app.stage.removeChild(lastScreen);\n lastScreen.destroy();\n });\n }\n Main.app.stage.addChild(screen);\n this.allScreens.push(screen);\n this.currentScreen = screen;\n screen.start();\n screen.onResize();\n Main.app.ticker.add(screen.draw, screen);\n }\n\n public doResize(): void {\n Main.app.renderer.resize(window.innerWidth, window.innerHeight);\n Main.app.stage.scale.x = 1;\n Main.app.stage.scale.y = 1;\n if (!Main.clickArea.destroyed) {\n Main.clickArea.width = window.innerWidth;\n Main.clickArea.height = window.innerHeight;\n Main.clickArea.position.set(0, 0);\n }\n Main.allScreens.forEach((screen) => {\n screen.onResize();\n })\n Main.settingsPane.resize();\n }\n\n private pointerLockChanged(): void {\n if (!document.pointerLockElement && Main.doPointerLock) {\n PIXI.EventSystem.isPointerLocked = false;\n Main.pointerLockExitTime = Date.now();\n Main.clickArea = new PIXI.Graphics();\n Main.clickArea.rect(0, 0, 1, 1);\n Main.clickArea.fill(\"rgba(0,0,0,0.1)\");\n Main.clickArea.width = window.innerWidth;\n Main.clickArea.height = window.innerHeight;\n Main.clickArea.position.set(0, 0);\n Main.app.stage.addChild(Main.clickArea);\n Main.clickArea.eventMode = \"static\";\n Main.clickArea.cursor = \"pointer\";\n Main.cursor.PopOut();\n Main.clickArea.zIndex = 9999999;\n Main.clickArea.onclick = () => {\n if (Date.now() - Main.pointerLockExitTime < 1500) {\n return;\n }\n Main.clickArea.removeFromParent();\n Main.clickArea.destroy();\n Main.pointerLock();\n Main.cursor.PopIn();\n }\n } else {\n PIXI.EventSystem.isPointerLocked = true;\n }\n }\n\n}\n","export default \"in vec2 vUV;\\nin vec2 vPositionOffset;\\nin vec2 vPosition;\\nin vec4 vColorTint;\\nuniform sampler2D uTexture;\\nuniform float time;\\n\\nvoid main() {\\n float a = ((vPositionOffset.y + vPosition.y)/1200.0) - 0.1;\\n vec4 color = texture(uTexture, vUV);\\n if (a > 1.0) {\\n a = 1.0;\\n }\\n gl_FragColor = (color*vColorTint)*a;\\n}\";","export default \"in vec2 aPosition;\\nin vec2 aUV;\\nin vec2 aPositionOffset;\\nin vec4 aColorTint;\\n\\nout vec2 vUV;\\nout vec2 vPositionOffset;\\nout vec2 vPosition;\\nout vec4 vColorTint;\\n\\nuniform mat3 uProjectionMatrix;\\nuniform mat3 uWorldTransformMatrix;\\nuniform mat3 uTransformMatrix;\\n\\n\\nvoid main() {\\n\\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\\n gl_Position = vec4((mvp * vec3(aPosition + aPositionOffset, 1.0)).xy, 0.0, 1.0);\\n vPositionOffset = aPositionOffset;\\n vUV = aUV;\\n vPosition = aPosition;\\n vColorTint = aColorTint;\\n}\";","export default \"struct GlobalUniforms {\\n uProjectionMatrix:mat3x3,\\n uWorldTransformMatrix:mat3x3,\\n uWorldColorAlpha: vec4,\\n uResolution: vec2,\\n}\\n\\nstruct LocalUniforms {\\n uTransformMatrix:mat3x3,\\n uColor:vec4,\\n uRound:f32,\\n}\\n\\n\\n@group(0) @binding(0) var globalUniforms : GlobalUniforms;\\n@group(1) @binding(0) var localUniforms : LocalUniforms;\\n\\nstruct VertexOutput {\\n @builtin(position) position: vec4,\\n @location(0) vUV: vec2,\\n @location(1) vPositionOffset: vec2,\\n @location(2) vPosition: vec2,\\n @location(3) vColorTint: vec4\\n};\\n\\n\\n@vertex\\nfn mainVert(\\n @location(0) aPosition : vec2,\\n @location(1) aUV : vec2,\\n @location(2) aColorTint : vec4,\\n @location(3) aPositionOffset : vec2,\\n) -> VertexOutput {\\n var mvp = globalUniforms.uProjectionMatrix\\n * globalUniforms.uWorldTransformMatrix\\n * localUniforms.uTransformMatrix;\\n\\n var output: VertexOutput;\\n\\n output.position = vec4(mvp * vec3(aPosition+aPositionOffset, 1.0), 1.0);\\n output.vUV = aUV;\\n output.vPosition = aPosition;\\n output.vPositionOffset = aPositionOffset;\\n output.vColorTint = aColorTint;\\n\\n return output;\\n};\\n\\nstruct WaveUniforms {\\n time:f32,\\n}\\n\\n@group(2) @binding(1) var uTexture : texture_2d;\\n@group(2) @binding(2) var uSampler : sampler;\\n@group(2) @binding(3) var waveUniforms : WaveUniforms;\\n\\n@fragment\\nfn mainFrag(\\n @location(0) vUV: vec2,\\n @location(1) vPositionOffset: vec2,\\n @location(2) vPosition: vec2,\\n @location(3) vColorTint: vec4\\n) -> @location(0) vec4 {\\n var a: f32 = ((vPositionOffset.y + vPosition.y)/1200.0) - 0.1;\\n let color: vec4 = textureSample(uTexture, uSampler, vUV);\\n if (a > 1.0){\\n a = 1.0;\\n }\\n return (color*vColorTint)*a;\\n};\";","export default \"in vec4 vColor;\\nin vec2 vUV;\\n\\nuniform sampler2D uTexture;\\nuniform float progress;\\n\\nvoid main() {\\n vec4 color = texture2D(uTexture, vUV);\\n float a = vColor.a * color.a;\\n vec4 _vColor = vec4(smoothstep(0.88, 1.0, color.a))*vColor;\\n vec4 outColor = (color.r < progress) ? vec4(_vColor.rgb * a, a) : vec4(0.0);\\n gl_FragColor = outColor;\\n}\\n\";","export default \"in vec2 aPosition;\\nin vec4 aColor;\\nin vec2 aUV;\\n\\nout vec4 vColor;\\nout vec2 vUV;\\n\\nuniform mat3 uProjectionMatrix;\\nuniform mat3 uWorldTransformMatrix;\\n\\nuniform mat3 uTransformMatrix;\\n\\n\\nvoid main() {\\n\\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\\n gl_Position = vec4((mvp * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\\n\\n vColor = aColor;\\n vUV = aUV;\\n}\\n\";","export default \"struct GlobalUniforms {\\n uProjectionMatrix:mat3x3,\\n uWorldTransformMatrix:mat3x3,\\n uWorldColorAlpha: vec4,\\n uResolution: vec2,\\n}\\n\\nstruct LocalUniforms {\\n uTransformMatrix:mat3x3,\\n uColor:vec4,\\n uRound:f32,\\n}\\n\\n\\n@group(0) @binding(0) var globalUniforms : GlobalUniforms;\\n@group(1) @binding(0) var localUniforms : LocalUniforms;\\n\\nstruct VertexOutput {\\n @builtin(position) position: vec4,\\n @location(0) vUV: vec2,\\n @location(1) vColor: vec4,\\n};\\n\\n\\n@vertex\\nfn mainVert(@location(0) aPosition : vec2, @location(1) aUV : vec2, @location(2) aColor: vec4\\n) -> VertexOutput {\\n var mvp = globalUniforms.uProjectionMatrix\\n * globalUniforms.uWorldTransformMatrix\\n * localUniforms.uTransformMatrix;\\n\\n var output: VertexOutput;\\n\\n output.position = vec4(mvp * vec3(aPosition, 1.0), 1.0);\\n output.vUV = aUV;\\n output.vColor = aColor;\\n\\n return output;\\n};\\n\\nstruct ProgressUniform {\\n progress:f32\\n}\\n\\n@group(2) @binding(1) var uTexture : texture_2d;\\n@group(2) @binding(2) var uSampler : sampler;\\n@group(2) @binding(3) var uProgress : ProgressUniform;\\n\\n@fragment\\nfn mainFrag(@location(0) vUV: vec2, @location(1) vColor: vec4) -> @location(0) vec4 {\\n let color: vec4 = textureSample(uTexture, uSampler, vUV);\\n let a: f32 = color.a;\\n let _vColor: vec4 = smoothstep(0.88, 1.0, color.a) * vColor;\\n var outColor: vec4 = vec4(0.0);\\n if (color.r < uProgress.progress) {\\n outColor = vec4(_vColor.rgb * a, a);\\n }\\n return outColor;\\n};\\n\";","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.hmd = function(module) {\n\tmodule = Object.create(module);\n\tif (!module.children) module.children = [];\n\tObject.defineProperty(module, 'exports', {\n\t\tenumerable: true,\n\t\tset: function() {\n\t\t\tthrow new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);\n\t\t}\n\t});\n\treturn module;\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t179: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkkosu\"] = self[\"webpackChunkkosu\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [151], function() { return __webpack_require__(29820); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","main_1","require","EventTypes_1","Audio","audio","source","mediaSource","mediaAudioElement","id","isPaused","this","_useMediaSource","paused","isPlaying","nodes","tempArrayMain","Float32Array","tempArrayL","tempArrayR","LeftChannel","RightChannel","FrequencyAmplitudes","_connectedToContext","_onEndCallback","timeStarted","beatmap","GetMaximumAudioLevel","Math","max","GetAverageAudioLevel","Create","audioContext","useMediaSource","Error","createMediaElementSource","onpause","ended","Play","createBufferSource","buffer","AddAudioNode","node","push","GetNode","type","filter","length","ConnectToContext","howToConnectFunction","forEach","index","connect","AnalyserNode","destination","play","backgroundVideo","Events","find","e","eventType","EventTypes","VIDEO","texture","resource","startPromise","then","start","Pause","pause","Stop","stop","SetTime","timeMS","currentTime","video","time","startTime","Promise","resolve","setTimeout","abs","GetDuration","duration","GetCurrentTime","Date","now","RegisterEndCallBack","callback","onended","exports","fadingOut","fadeOutTimeout","playingCallback","FadeOut","clearTimeout","gainNodes","GainNode","gain","linearRampToValueAtTime","Main","AudioEngine","PlayingAudios_1","Audio_1","BeatmapData_1","UnInheritedTimingPoint_1","Effect_1","_playingAudios","_musicQueue","_audioIdTicker","_changeCallbacks","silentMusic","createSilentMusic","useSilentMusic","constructor","AudioContext","PlayingAudios","app","ticker","add","update","UpdateMusicQueue","_play","cb","mapAudio","MapAudio","BeatmapData","timingPoint","UnInheritedTimingPoint","beatLength","effects","Effect","None","TimingPoints","addMusicChangeEventListener","removeMusicChangeEventListener","GetCurrentPlayingMusic","GetCurrentPlayingMusicNoSilent","PlayEffect","pitch","audioObj","AddToMusicQueue","beatMapData","musicPlayingCallback","mapAudioObj","document","createElement","src","PlayMusicImmediately","currentPlaying","currentPlayingNoSilent","analyzerMain","analyzerL","analyzerR","getFloatFrequencyData","i","Infinity","getFloatTimeDomainData","avgL","avgR","value","createGain","analyzer","createAnalyser","fftSize","smoothingTimeConstant","splitter","createChannelSplitter","audios","playbackRate","splice","audioInArr","PIXI","__importStar","MathUtil_1","LogoVisualizer","Container","static","frequencyAmplitudes","temporalAmplitudes","graphics","Graphics","index_change","bar_length","bars_per_visualiser","visualiser_rounds","decay_per_millisecond","time_between_updates","amplitude_dead_zone","indexOffset","firstDraw","alpha","number","super","blendMode","addChild","eventMode","setInterval","updateAmplitudes","draw","clear","decayFactor","deltaMS","j","rotation","MathUtil","DegreesToRadians","rotationCos","cos","rotationSin","sin","barPosition","x","size","y","barSize","sqrt","amplitudeOffset","moveTo","lineTo","stroke","color","width","audioTime","GetCurrentTimingPoints","targetAmplitude","KiaiTime","LogoVisualizer_1","MenuLogoVisualizer","TWEEN","Ease_1","LoadAnim","bg","arc","arcContainer","animInterval","container","bgContainer","bgRotation","bgColor","arcColor","pivot","set","PI","roundRect","fill","cap","scale","Ease","getEase","ScaleTo","Easing","Quadratic","InOut","FadeIn","doAnims","createTween","angle","getWidth","getHeight","deltaTime","destroy","_options","clearInterval","Screen_1","LogoTrackingContainer_1","ButtonSystem","menuBG","isOpened","logo","state","ButtonSystemState","Initial","logoTrackingContainer","LogoTrackingContainer","menuHeight","State","lastState","updateLogoState","console","log","name","arguments","undefined","Exit","Close","TopLevel","Open","ClearEasings","Screen","getScaleBasedOffScreenSize","Linear","In","Quintic","Out","drawMenuBG","Action","onOsuLogo","rect","Edit","Sinusoidal","isOpen","onResize","position","window","innerHeight","innerWidth","Logo","easing","startPosition","visual_box_size","StartTracking","IsTracking","StopTracking","ComputeLogoTrackingPosition","pos","Update","Triangles_1","Loader_1","MenuLogoVisualizer_1","OsuLogo","outline","visualizer","triangles","Triangles","flash","logoContainer","logoBounceContainer","logoBeatContainer","logoAmplitudeContainer","logoHoverContainer","rippleContainer","ripple","defaultVisualizerAlpha","early_activation","timeElapsedSinceLastBeat","timeUntilNextBeat","lastTimeElapasedSinceLastBeat","selectSample","Loader","GetAudio","backToLogoSample","isMouseDown","mouseDownPosition","SizeForFlow","Sprite","from","anchor","mask","circle","height","hitArea","Circle","onmouseenter","_onmouseenter","onmouseleave","_onmouseleave","onmousedown","_onmousedown","onclick","_onclick","stage","addEventListener","_onmouseup","Elastic","mousePos","Exponential","TransformTo","GetCurrentUninheritedTimingPoint","Velocity","Damp","maxAmplitude","onNewBeat","change","pow","amplitudeAdjust","min","Then","FadeTo","osuCircleTriangles_vert_1","__importDefault","osuCircleTriangles_frag_1","osuCircleTriangles_wgsl_1","bgGradient","timeSinceLastSpawn","instancePositionBuffer","totalTriangles","colorStops","FillGradient","ratio","addColorStop","random","velocity","randVelocity","Buffer","data","usage","BufferUsage","VERTEX","COPY_DST","Color","geometry","Geometry","attributes","aPosition","aUV","aColorTint","red","green","blue","aPositionOffset","instance","indexBuffer","instanceCount","gl","vertex","default","fragment","gpu","entryPoint","triangleGraphic","triangleTexture","renderer","generateTexture","shader","Shader","resources","uTexture","uSampler","style","waveUniforms","triangleMesh","Mesh","options","count","triangle","u1","u2","randStdNormal","MenuCursor","mouseCursor","mouseCursorAdditive","mouseContainer","animContainer","animRotationContainer","dragRotationState","DragRotationState","NotDragging","lastDragRotationState","mouseHideContainer","elastic_const2","elastic_const","elastic_offset_quarter","posMouseDown","mouseIsDown","cursorTapSample","mouseButtonClicked","visible","updateMouse","tint","zIndex","addEventListeners","button","DragStarted","Rotating","PopIn","PopOut","distance","offsetX","offsetY","degrees","RadiansToDegrees","atan2","diff","Background","destroying","show","fadeOutDuration","BackgroundContainer","children","child","destroyed","Background_1","RandomBackground","parallaxMultiplier","getScreenWidth","getScreenHeight","newRandomBG","background","BACKGROUND","setBGContainer","setBG","bgSprite","useSeasonalBackgrounds","seasonalBackgroundsNum","randomNum","defaultBackgroundsNum","round","Texture","onClose","sprite","resizeSprite","scaleFactor","texWidth","texHeight","SettingsPane","resize","open","Cubic","toggle","close","addToLoadList","loadList","url","isAudio","pixiBundleName","Get","result","loadedList","loadedObj","GetString","dataString","dataAudio","addBackgrounds","fetch","encodeURIComponent","res","json","backgrounds","loadParser","catch","error","warn","Load","nonPixi","pixi","pixiwithBundles","loadedAssets","erroredAssets","loadObj","added","loadObjs","incrementLoadAssetNumber","errored","response","blob","isText","text","arrayBuffer","arrBuff","decodeAudioData","audioBuff","bundle","assets","alias","Assets","addBundle","loadBundle","IntroScreen_1","InteractScreen","text2","textContainer","textContainerContainer","introTrack","clickSound","clickArea","Text","fontFamily","fontSize","align","cursor","clicked","switchScreen","IntroScreen","body","pointerLock","lockKeyboard","ontap","GlitchingTriangles","bounds","randX","x1","x2","randY","y1","y2","unzipit_1","GlitchingTriangles_1","MainMenu_1","LazerLogo_1","BeatmapParser_1","UIUtils_1","CenteredList_1","introTrackUrl","doTextSpacingAnim","ruleSetContainer","ruleSetList","CenteredList","logoContainerContainer","lazerLogo","LazerLogo","flashed","standard","taiko","ctb","mania","completionPromise","welcomeText","letterSpacing","URL","createObjectURL","entries","unzip","entry","Object","endsWith","async","SBFile","beatmapData","files","BeatmapParser","Parse","osuFile","LoadFiles","audioFile","General","afterAudioPlay","glitchingInterval","padding","elementsMargin","UIUtils","centerPivotOfList","MainMenu","ReCenter","LogoAnimation_1","highlight","textureHighlight","textureBackground","LogoAnimation","dummy","OnEach","setProgress","logoAnimation_vert_1","logoAnimation_frag_1","logoAnimation_wgsl_1","uProgress","progress","quadGeometry","aColor","quad","uniforms","LoadAnim_1","LoadScreen","loadAnim","RandomBackground_1","OsuLogo_1","ButtonSystem_1","osuCircle","menu","Settings_1","UIScale_1","uiScale","Settings","getSetting","UIScale","getValue","SettingsCategory","info","SettingData","register","setting","onValueChanged","Setting_1","DropdownSetting","Setting","getDefaultValue","defaultValue","setValue","list","option","displayName","save","loadFromSaveValue","RangeSetting","clamp","minValue","maxValue","Renderer_1","MouseSensitivity_1","registerAll","Renderer","MouseSensitivity","load","settingSaveDataString","localStorage","getItem","settings","getList","JSON","parse","corrupt","stringify","category","settingObj","_settingObj","reset","settingSaveData","setItem","removeItem","settingsList","_setting","getSettingData","DropdownSetting_1","webglOption","webGpuOption","RangeSetting_1","increment","pixi_js_1","Input","EventSystem","cursorSensitivity","GeneralData_1","EditorData_1","Metadata_1","DifficultyData_1","EventsData_1","TimingPointsData_1","ColorsData_1","Map","formatVersion","GeneralData","Editor","EditorData","Metadata","Difficulty","DifficultyData","EventsData","TimingPointsData","Colors","ColorsData","HPDrainRate","CircleSize","OverallDifficulty","ApproachRate","SliderMultiplier","SliderTickRate","Bookmarks","DistanceSpacing","BeatDivisor","GridSize","TimelineZoom","Event_1","EventBackground","Event","filename","xOffset","yOffset","EventBreak","BREAK","endTime","EventVideo","EventStoryboard_1","EventAnimation","EventStoryboard","ANIMATION","filepaths","frameCount","frameDelay","loopType","textures","EventSample","SAMPLE","volume","audioBuffer","EventSprite","SPRITE","Commands","layer","origin","filepath","Layer","input","parseInt","isNaN","Fail","Pass","Foreground","LoopType","LoopForever","LoopOnce","Origin","TopLeft","Center","CenterLeft","TopRight","BottomCenter","TopCenter","Custom","CenterRight","BottomLeft","BottomRight","Countdown","Countdown_1","SampleSet_1","Mode_1","OverlayPosition_1","AudioFilename","AudioLeadIn","AudioHash","PreviewTime","Normal","SampleSet","StackLeniency","Mode","OSU","LetterboxInBreaks","StoryFireInFront","UseSkinSprites","AlwaysShowPlayfield","OverlayPosition","NoChange","SkinPreference","EpilepsyWarning","CountdownOffset","SpecialStyle","WidescreenStoryboard","SamplesMatchPlaybackRate","Title","TitleUnicode","Artist","ArtistUnicode","Creator","Version","Source","Tags","BeatmapID","BeatmapSetID","TimingPoint_1","InheritedTimingPoint","TimingPoint","sliderVelocityMultiplier","sampleSet","sampleIndex","InheritedTimingPoint_1","toReturn","unInheritedTimingPoint","meter","TimingPointsParser_1","GeneralParser_1","EditorParser_1","MetadataParser_1","DifficultyParser_1","EventsParser_1","osuFileContent","storyBoardFileContent","osuFileContentLines","split","osuSBFileContentLines","startsWith","version","parseFloat","GeneralParser","ParseGeneral","GetSection","EditorParser","ParseEditor","MetadataParser","ParseMetadata","DifficultyParser","ParseDifficulty","EventsParser","ParseEvents","TimingPointsParser","ParseTimingPoints","audioEngine","loaded","check","sectionName","osuStoryBoardFileContentLines","section","str","AutoParse","sectionType","propValue","beatmapDataSection","key","keyExists","sectionKey","toString","isNumber","test","substring","num","EventBackground_1","EventVideo_1","EventBreak_1","ffmpeg_1","EventSprite_1","Layer_1","EventAnimation_1","Origin_1","LoopType_1","EventSample_1","object","event","values","replaceAll","COLOR","convertToLayer","convertToOrigin","clamp01","filePathWithNoFileExtension","lastIndexOf","filePath","keys","sort","a","b","convertToLoopType","toLoad","eventKey","file","get","Blob","failed","cacheHit","aviTranscodedVideoCache","cache","beatmapSID","delete","revokeObjectURL","ffmpeg","FFmpeg","on","_ref","classWorker","core","wasm","worker","classWorkerURL","coreURL","wasmURL","workerURL","writeFile","Uint8Array","exec","readFile","terminate","newFile","loadedTextures","texturesNeededToLoad","checkLoadedTextures","prop","Number","radians","final","base","exponent","Lerp","ammount","easings","obj","delay","dontStore","previousEases","checkIfEaseExists","ease","newValue","isPrimitive","property","easingFunc","tweenValue","tween","Tween","to","onUpdate","onStart","chain","onStop","onDone","onComplete","newPosition","tweenInArray","newScale","_newScale","newAlpha","largestDuration","getDuration","registerOnUpdate","updateEventListeners","eventListener","unRegisterOnUpdate","ev","ui_1","List","margin","leftPadding","topPadding","isLast","rightPadding","bottomPadding","gameWidth","gameHeight","Application","globalThis","__PIXI_APP__","onload","init","backgroundColor","antialias","preference","resolution","devicePixelRatio","autoDensity","navigator","mediaSession","setActionHandler","defineProperty","sensitivity","rendererSetting","location","reload","LoadScreen_1","InteractScreen_1","MenuCursor_1","AudioEngine_1","SettingsPane_1","setDropEvents","appendChild","canvas","settingsPane","ctrlKey","code","doResize","clientX","clientY","pointerLockChanged","dialogOk","preventDefault","processingOsuFile","alert","dataTransfer","items","item","kind","getAsFile","setAttribute","keyboard","lock","fullscreenElement","doPointerLock","requestPointerLock","unadjustedMovement","exitPointerLock","screen","currentScreen","lastScreen","allScreens","remove","removeChild","pointerLockElement","isPointerLocked","pointerLockExitTime","removeFromParent","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","module","__webpack_modules__","call","m","O","chunkIds","fn","priority","notFulfilled","fulfilled","every","r","d","definition","o","enumerable","hmd","create","prototype","hasOwnProperty","Symbol","toStringTag","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","self","bind","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file diff --git a/game.c52c91455b8f4b9329e2.js b/game.c52c91455b8f4b9329e2.js deleted file mode 100644 index 906f0e6..0000000 --- a/game.c52c91455b8f4b9329e2.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(){"use strict";var e,t={65918:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MapAudio=t.Audio=void 0;const n=i(20825),s=i(15041);class o{audio;source;mediaSource;mediaAudioElement;id;get isPaused(){return!!this._useMediaSource&&this.mediaAudioElement.paused}get isPlaying(){return!this._useMediaSource||!this.mediaAudioElement.paused}nodes=[];tempArrayMain=new Float32Array(256);tempArrayL=new Float32Array(64);tempArrayR=new Float32Array(64);LeftChannel=0;RightChannel=0;FrequencyAmplitudes=new Float32Array(256);_connectedToContext=!1;_useMediaSource=!1;_onEndCallback;timeStarted=0;paused=!1;beatmap;GetMaximumAudioLevel(){return Math.max(this.LeftChannel,this.RightChannel)}GetAverageAudioLevel(){return(this.LeftChannel+this.RightChannel)/2}Create(e,t){if(this._useMediaSource=t||!1,t){if(!this.mediaAudioElement)throw new Error("HTML Audio Element was not initialized!");this.mediaSource=e.createMediaElementSource(this.mediaAudioElement),this.mediaAudioElement.onpause=()=>{this.paused||this.mediaAudioElement.ended||this.Play()}}else this.source=e.createBufferSource(),this.source.buffer=this.audio}AddAudioNode(e){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");this.nodes.push(e)}GetNode(e){let t=this.nodes.filter((t=>t instanceof e));return t.length>0?t:null}ConnectToContext(e,t){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");this._connectedToContext||(this._connectedToContext=!0,this.nodes.length>0?t?t(this.nodes,this._useMediaSource?this.mediaSource:this.source):this.nodes.forEach(((t,i)=>{this.source.connect(t),t instanceof AnalyserNode||t.connect(e.destination)})):this._useMediaSource?this.mediaSource.connect(e.destination):this.source.connect(e.destination))}Play(){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(this.paused=!1,this._useMediaSource){this.mediaAudioElement.play();let e=this.beatmap.Events.Events.find((e=>{if(e.eventType==s.EventTypes.VIDEO)return e}));e&&e.texture&&e.texture.source.resource.startPromise&&e.texture.source.resource.startPromise.then((()=>{e.texture.source.resource.play()}))}else this.source.start()}Pause(){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(!this._useMediaSource)throw new Error("Pause is not supported on AudioSourceBuffer!");this.paused=!0,this.mediaAudioElement.pause();let e=this.beatmap.Events.Events.find((e=>{if(e.eventType==s.EventTypes.VIDEO)return e}));e&&e.texture&&e.texture.source.resource.startPromise&&e.texture.source.resource.startPromise.then((()=>{e.texture.source.resource.pause()}))}Stop(){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(this.paused=!0,this._useMediaSource){this.mediaAudioElement.pause(),this._onEndCallback&&this._onEndCallback();let e=this.beatmap.Events.Events.find((e=>{if(e.eventType==s.EventTypes.VIDEO)return e}));e&&e.texture&&e.texture.source.resource.startPromise&&e.texture.source.resource.startPromise.then((()=>{e.texture.source.resource.pause()}))}else this.source.stop()}SetTime(e){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(!this._useMediaSource)throw new Error("SetTime is not supported on AudioSourceBuffer!");this.mediaAudioElement.currentTime=e/1e3;let t=this.beatmap.Events.Events.find((e=>{if(e.eventType==s.EventTypes.VIDEO)return e}));t&&t.texture&&t.texture.source.resource.startPromise&&t.texture.source.resource.startPromise.then((()=>{let i=t.texture.source.resource,n=e/1e3;n+=t.startTime,n<0?(i.currentTime=0,i.pause(),t.texture.source.resource.startPromise=new Promise((e=>{setTimeout((()=>{i.play()}),Math.abs(n))}))):i.currentTime=n}))}GetDuration(){return this._useMediaSource?1e3*this.mediaAudioElement.duration:this.audio.duration}GetCurrentTime(){return this._useMediaSource?1e3*this.mediaAudioElement.currentTime:0!=this.timeStarted?Date.now()-this.timeStarted:0}RegisterEndCallBack(e){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");this._onEndCallback=e,this._useMediaSource?this.mediaAudioElement.onended=()=>{this.paused=!0,e()}:this.source.onended=()=>{this.isPaused||(this.paused=!0,e())}}}t.Audio=o;t.MapAudio=class extends o{fadingOut=!1;fadeOutTimeout;playingCallback;FadeOut(){if(!(this._useMediaSource?this.mediaSource:this.source))throw new Error("Source not created yet!");if(!this._connectedToContext)throw new Error("Not connected to audio context yet!");if(!this._useMediaSource)throw new Error("FadeOut is not supported on AudioSourceBuffer!");if(this.fadingOut)return;this.fadingOut=!0,clearTimeout(this.fadeOutTimeout);let e=this.GetNode(GainNode);if(null==e)throw new Error("Gain Node doesn't exist on Audio Object!");e[0].gain.linearRampToValueAtTime(0,n.Main.AudioEngine.audioContext.currentTime+1),setTimeout((()=>{this.Stop()}),1e3)}}},85437:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.AudioEngine=void 0;const n=i(14981),s=i(65918),o=i(17898),a=i(20825),r=i(87816),l=i(22331);t.AudioEngine=class{audioContext;_playingAudios;_musicQueue=[];_audioIdTicker=0;_changeCallbacks=[];silentMusic=this.createSilentMusic();useSilentMusic=!0;constructor(){this.audioContext=new AudioContext,this._playingAudios=new n.PlayingAudios,a.Main.app.ticker.add((()=>{this.update()}))}UpdateMusicQueue(){this._musicQueue[0]&&(this._musicQueue[0].fadingOut||0!=this._musicQueue[0].GetCurrentTime()||(this._play(this._musicQueue[0]),this._changeCallbacks.forEach((e=>e(this._musicQueue[0])))),this._musicQueue[0].fadingOut&&this._musicQueue[1]&&this._musicQueue[1]&&(this._play(this._musicQueue[1]),this._changeCallbacks.forEach((e=>e(this._musicQueue[1]))))),this._musicQueue.length>=1?this.useSilentMusic=!1:(this.silentMusic=this.createSilentMusic(),this.useSilentMusic=!0)}createSilentMusic(){let e=new s.MapAudio;e.timeStarted=Date.now(),e.beatmap=new o.BeatmapData;let t=new r.UnInheritedTimingPoint;return t.time=0,t.beatLength=1e3,t.effects=l.Effect.None,e.beatmap.TimingPoints.TimingPoints.push(t),e}addMusicChangeEventListener(e){this._changeCallbacks.push(e)}removeMusicChangeEventListener(e){this._changeCallbacks=this._changeCallbacks.filter((t=>t!=e))}GetCurrentPlayingMusic(){return this.useSilentMusic?this.silentMusic:this._musicQueue[0]}GetCurrentPlayingMusicNoSilent(){return this._musicQueue[0]}PlayEffect(e,t){let i=new s.Audio;i.audio=e,i.id=this._audioIdTicker,this._play(i,t),this._audioIdTicker++}AddToMusicQueue(e,t,i){let n=new s.MapAudio;return n.mediaAudioElement=document.createElement("audio"),n.mediaAudioElement.src=e,n.beatmap=t,n.id=this._audioIdTicker,i&&(n.playingCallback=i),this._musicQueue.push(n),this._audioIdTicker++,this.UpdateMusicQueue(),n.id}PlayMusicImmediately(e,t,i){let n=this.GetCurrentPlayingMusicNoSilent();this._musicQueue=[],n&&n.FadeOut(),this.AddToMusicQueue(e,t,i)}update(){let e=this.GetCurrentPlayingMusic(),t=this.GetCurrentPlayingMusicNoSilent();if(t)if(t.isPaused)this.useSilentMusic=!0;else if(this.useSilentMusic&&(this.useSilentMusic=!1,e=this.GetCurrentPlayingMusic()),!this.useSilentMusic){e.fadingOut||e.GetDuration()-e.GetCurrentTime()<=1e3&&e.FadeOut();let t=e.GetNode(AnalyserNode)[0],i=e.GetNode(AnalyserNode)[1],n=e.GetNode(AnalyserNode)[2];t.getFloatFrequencyData(e.tempArrayMain);for(let t=0;t{s+=(e+1)/2})),e.tempArrayR.forEach((e=>{o+=(e+1)/2})),s/=e.tempArrayL.length,o/=e.tempArrayR.length,e.LeftChannel=s,e.RightChannel=o}}_play(e,t){if(e instanceof s.MapAudio){e.Create(this.audioContext,!0);let t=this.audioContext.createGain();t.gain.value=0;let i=this.audioContext.createAnalyser();i.fftSize=512,i.smoothingTimeConstant=0;let n=this.audioContext.createChannelSplitter(2),s=this.audioContext.createAnalyser();s.smoothingTimeConstant=0,s.fftSize=128;let o=this.audioContext.createAnalyser();o.smoothingTimeConstant=0,o.fftSize=128,e.AddAudioNode(t),e.AddAudioNode(i),e.AddAudioNode(s),e.AddAudioNode(o),e.ConnectToContext(this.audioContext,((e,a)=>{a.connect(t),t.connect(this.audioContext.destination),a.connect(i),a.connect(n),n.connect(s,0),n.connect(o,1)})),e.Play(),this._playingAudios.audios.push(e),e.playingCallback&&e.playingCallback(),t.gain.linearRampToValueAtTime(1,this.audioContext.currentTime+.5)}else e.Create(this.audioContext,!1),e.ConnectToContext(this.audioContext),t&&e.source&&(e.source.playbackRate.value=t),e.Play(),this._playingAudios.audios.push(e);e.RegisterEndCallBack((()=>{e instanceof s.MapAudio&&(this._musicQueue[0]==e&&this._musicQueue.splice(0,1),this.UpdateMusicQueue()),this._playingAudios.audios.forEach(((t,i)=>{t!==e||this._playingAudios.audios.splice(i,1)}))}))}}},14981:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.PlayingAudios=void 0;t.PlayingAudios=class{audios=[]}},9611:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.LogoVisualizer=void 0;const a=i(20825),r=o(i(58687)),l=i(5825),u=i(22331);class c extends r.Container{static size=900;frequencyAmplitudes=new Float32Array(256);audio;temporalAmplitudes=new Float32Array(256);graphics=new r.Graphics;index_change=5;bar_length=600;bars_per_visualiser=200;visualiser_rounds=5;decay_per_millisecond=.0024;time_between_updates=50;amplitude_dead_zone=1/this.bar_length;indexOffset=0;firstDraw=!0;set alpha(e){super.alpha=.2*e}get alpha(){return 5*super.alpha}constructor(){super(),this.alpha=1}start(){this.graphics.blendMode="add",this.addChild(this.graphics),this.graphics.eventMode="none",this.eventMode="none",setInterval((()=>{this.updateAmplitudes()}),this.time_between_updates)}draw(e){if(this.firstDraw)for(let e=0;ethis.frequencyAmplitudes[e]&&(this.frequencyAmplitudes[e]=i)}this.indexOffset=(this.indexOffset+this.index_change)%this.bars_per_visualiser}}t.LogoVisualizer=c},8211:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MenuLogoVisualizer=void 0;const n=i(9611);class s extends n.LogoVisualizer{draw(e){super.draw(e)}}t.MenuLogoVisualizer=s},49323:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.LoadAnim=void 0;const a=o(i(58687)),r=o(i(29172)),l=i(92915);class u extends a.Container{bg;arc;arcContainer;animInterval;container;bgContainer;bgRotation=0;constructor(e,t){super(),this.pivot.set(.5,.5),this.container=new a.Container,this.container.alpha=0,this.rotation=2.5*Math.PI,this.bgContainer=new a.Container,this.bg=new a.Graphics,this.bg.roundRect(-50,-50,100,100,25),this.bg.fill(e),this.arcContainer=new a.Container,this.arc=new a.Graphics,this.arc.arc(0,0,27,Math.PI+.26,2.92*Math.PI),this.arc.stroke({width:8,color:t,cap:"round"}),this.arc.scale.set(-1,1),this.container.scale.set(.5,.5),this.bgContainer.addChild(this.bg),this.arcContainer.addChild(this.arc),this.bgContainer.addChild(this.arcContainer),this.container.addChild(this.bgContainer),this.addChild(this.container),l.Ease.getEase(this.container).ScaleTo(1,400,r.Easing.Quadratic.InOut).FadeIn(400,r.Easing.Quadratic.InOut),this.doAnims(),this.animInterval=setInterval((()=>{this.doAnims()}),800)}doAnims(){this.bgRotation+=90,l.Ease.getEase(this.bgContainer).createTween({value:this.bgContainer.angle},{value:this.bgRotation},!0,"angle",600,r.Easing.Quadratic.InOut)}getWidth(){return 100*this.scale.x}getHeight(){return 100*this.scale.y}draw(e){this.arcContainer.angle+=3*e.deltaTime}destroy(e){l.Ease.getEase(this.container).FadeOut(400,r.Easing.Quadratic.InOut).ScaleTo(.5,400,r.Easing.Quadratic.InOut),setTimeout((()=>{clearInterval(this.animInterval),super.destroy(e)}),400)}}t.LoadAnim=u},70723:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.ButtonSystem=void 0;const a=o(i(58687)),r=o(i(29172)),l=i(92915),u=i(84283),c=i(57853);class d extends a.Container{menuBG=new a.Graphics;isOpened=!1;logo;state=h.Initial;logoTrackingContainer=new c.LogoTrackingContainer;menuHeight=150;get State(){return this.state}set State(e){if(this.state==e)return;const t=this.state;this.state=e,this.updateLogoState(t),console.log(`${this.constructor.name}'s state changed from ${t} to ${e}`)}updateLogoState(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:h.Initial;switch(this.state){case h.Exit:case h.Initial:this.Close();break;case h.TopLevel:case h.Play:switch(e){case h.TopLevel:break;case h.Initial:this.Open(),l.Ease.getEase(this.logo).ClearEasings().ScaleTo(.5*u.Screen.getScaleBasedOffScreenSize(),200,r.Easing.Linear.In);break;default:this.Open(),l.Ease.getEase(this.logo).ClearEasings().ScaleTo(.5*u.Screen.getScaleBasedOffScreenSize(),200,r.Easing.Quintic.Out)}}}constructor(e){super(),this.logo=e,this.drawMenuBG(),this.scale.y=0,this.alpha=0,this.addChild(this.menuBG),this.addChild(this.logoTrackingContainer),this.logo.Action=()=>this.onOsuLogo()}drawMenuBG(){this.menuBG.rect(0,u.Screen.getScaleBasedOffScreenSize()*(-this.menuHeight/2),1,u.Screen.getScaleBasedOffScreenSize()*this.menuHeight),this.menuBG.fill({color:"rgb(50,50,50)"})}onOsuLogo(){switch(this.state){default:return!1;case h.Initial:return this.State=h.TopLevel,!0;case h.TopLevel:case h.Play:case h.Edit:return!1}}Open(){setTimeout((()=>{this.isOpened=!0,l.Ease.getEase(this).ScaleTo(1,400,r.Easing.Quintic.Out).FadeIn(400,r.Easing.Quintic.Out)}),150)}Close(){this.isOpened=!1,l.Ease.getEase(this).ClearEasings().ScaleTo({x:1,y:0},300,r.Easing.Sinusoidal.In).FadeOut(300,r.Easing.Sinusoidal.In)}isOpen(){return this.isOpened}onResize(){this.menuBG.clear(),this.drawMenuBG(),this.position.set(0,window.innerHeight/2),this.menuBG.width=window.innerWidth}}var h;t.ButtonSystem=d,function(e){e.Exit="Exit",e.Initial="Initial",e.TopLevel="TopLevel",e.Play="Play",e.Edit="Edit",e.EnteringMode="EnteringMode"}(h||(h={}))},57853:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.LogoTrackingContainer=void 0;const a=o(i(58687)),r=o(i(29172));class l extends a.Container{Logo=null;easing;startPosition=null;startTime=null;duration;visual_box_size=72;StartTracking(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:r.Easing.Linear.None;if(e.IsTracking&&null==this.Logo)throw new Error("Cannot track an instance of OsuLogo to multiple LogoTrackingContainers");this.Logo!=e&&null!=this.Logo&&(this.Logo.IsTracking=!1),this.Logo=e,this.Logo.IsTracking=!0,this.duration=t,this.easing=i,this.startTime=null,this.startPosition=null}StopTracking(){null!=this.Logo&&(this.Logo.IsTracking=!1,this.Logo=null)}ComputeLogoTrackingPosition(){let e=this.Logo.position;return e.x=window.innerWidth/3,e}Update(){this.Logo}}t.LogoTrackingContainer=l},73703:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.OsuLogo=void 0;const a=o(i(58687)),r=i(44961),l=o(i(29172)),u=i(92915),c=i(20825),d=i(12235),h=i(8211),g=i(9611),f=i(22331),p=i(5825);class m extends a.Container{outline;visualizer=new h.MenuLogoVisualizer;triangles=new r.Triangles;flash;logoContainer=new a.Container;logoBounceContainer=new a.Container;logoBeatContainer=new a.Container;logoAmplitudeContainer=new a.Container;logoHoverContainer=new a.Container;rippleContainer=new a.Container;ripple;defaultVisualizerAlpha=.5;early_activation=60;timeElapsedSinceLastBeat=0;timeUntilNextBeat=0;lastTimeElapasedSinceLastBeat=0;selectSample=d.Loader.GetAudio("mainMenu.osuLogo.select");backToLogoSample=d.Loader.GetAudio("mainMenu.osuLogo.backToLogo");isMouseDown=!1;mouseDownPosition={x:0,y:0};Action=null;IsTracking=!1;get SizeForFlow(){return this.outline.width*this.logoBounceContainer.scale.x*this.logoHoverContainer.scale.x}constructor(){super(),this.visualizer.start(),this.outline=a.Sprite.from("mainMenu.logoOutline"),this.outline.anchor.set(.5,.5);let e=.7;this.visualizer.scale.set(e),this.visualizer.pivot.set(g.LogoVisualizer.size/2,g.LogoVisualizer.size/2),this.visualizer.alpha=this.defaultVisualizerAlpha;let t=new a.Graphics;t.circle(0,0,450),t.fill({color:"white"}),t.scale=e,this.flash=a.Sprite.from("mainMenu.logoMask"),this.flash.anchor.set(.5,.5),this.flash.scale=e,this.flash.blendMode="add",this.flash.alpha=0,this.triangles.flash.anchor.set(.5,.5),this.triangles.flash.scale=e,this.outline.scale.set(e),this.triangles.scale.set(e),this.triangles.position.set(-this.outline.width/2,-this.outline.height/2),this.triangles.mask=t,this.ripple=a.Sprite.from("mainMenu.logoMask"),this.ripple.anchor.set(.5,.5),this.ripple.scale=e,this.ripple.alpha=0,this.ripple.blendMode="add",this.rippleContainer.addChild(this.ripple),this.logoContainer.addChild(this.visualizer),this.logoContainer.addChild(this.triangles),this.logoContainer.addChild(this.triangles.flash),this.logoContainer.addChild(t),this.logoContainer.addChild(this.flash),this.logoContainer.addChild(this.outline),this.logoContainer.hitArea=new a.Circle(0,0,336),this.logoContainer.eventMode="static",this.logoContainer.onmouseenter=this._onmouseenter,this.logoContainer.onmouseleave=this._onmouseleave,this.logoContainer.onmousedown=this._onmousedown,this.logoContainer.onclick=this._onclick,this.logoBeatContainer.addChild(this.logoContainer),this.logoAmplitudeContainer.addChild(this.logoBeatContainer),this.logoBounceContainer.addChild(this.rippleContainer),this.logoBounceContainer.addChild(this.logoAmplitudeContainer),this.logoHoverContainer.addChild(this.logoBounceContainer),this.addChild(this.logoHoverContainer),c.Main.app.stage.addEventListener("mouseup",(e=>{this._onmouseup(e)}))}_onmouseenter=e=>{u.Ease.getEase(this.logoHoverContainer).ScaleTo(1.1,500,l.Easing.Elastic.Out)};_onmouseleave=e=>{u.Ease.getEase(this.logoHoverContainer).ScaleTo(1,500,l.Easing.Elastic.Out)};_onmousedown=e=>{this.isMouseDown=!0,u.Ease.getEase(this.logoBounceContainer).ClearEasings().ScaleTo(.9,1e3,l.Easing.Sinusoidal.Out),this.mouseDownPosition={x:c.Main.mousePos.x,y:c.Main.mousePos.y}};_onclick=e=>{this.flash.alpha=.4,u.Ease.getEase(this.flash).ClearEasings().FadeOut(1500,l.Easing.Exponential.Out),this.Action&&this.Action()&&c.Main.AudioEngine.PlayEffect(d.Loader.GetAudio("mainMenu.osuLogo.select"))};_onmouseup=e=>{this.isMouseDown=!1,u.Ease.getEase(this.logoBounceContainer).ClearEasings().ScaleTo(1,500,l.Easing.Elastic.Out).TransformTo({x:0,y:0},800,l.Easing.Elastic.Out)};draw(e){this.visualizer.draw(e),this.triangles.draw(e);let t=c.Main.AudioEngine.GetCurrentPlayingMusic(),i=t.GetCurrentTime(),n=t.beatmap.TimingPoints.GetCurrentUninheritedTimingPoint(i);if(this.timeUntilNextBeat=(n.time-i)%n.beatLength,this.timeUntilNextBeat<=0&&(this.timeUntilNextBeat+=n.beatLength),this.timeElapsedSinceLastBeat=n.beatLength-this.timeUntilNextBeat,c.Main.AudioEngine.useSilentMusic)this.logoAmplitudeContainer.scale=1,this.triangles.Velocity=p.MathUtil.Damp(this.triangles.Velocity,.5,.9,e.deltaMS);else{let i=t.GetMaximumAudioLevel();this.logoAmplitudeContainer.scale.set(p.MathUtil.Damp(this.logoAmplitudeContainer.scale.x,1-.04*Math.max(0,i-.4),.9,e.deltaMS)),this.triangles.Velocity=p.MathUtil.Damp(this.triangles.Velocity,.5*(n.effects==f.Effect.KiaiTime?4:2),.995,e.deltaMS)}if(this.lastTimeElapasedSinceLastBeat>this.timeElapsedSinceLastBeat&&this.onNewBeat(),this.lastTimeElapasedSinceLastBeat=this.timeElapsedSinceLastBeat,this.isMouseDown){let e={x:c.Main.mousePos.x-this.mouseDownPosition.x,y:c.Main.mousePos.y-this.mouseDownPosition.y},t=Math.sqrt(e.x*e.x+e.y*e.y);e.x*=t<=0?0:Math.pow(t,.6)/t,e.y*=t<=0?0:Math.pow(t,.6)/t,this.logoBounceContainer.x=e.x,this.logoBounceContainer.y=e.y}}onNewBeat(){let e=c.Main.AudioEngine.GetCurrentPlayingMusic(),t=e.GetCurrentTime(),i=e.beatmap.TimingPoints.GetCurrentUninheritedTimingPoint(t).beatLength,n=e.beatmap.TimingPoints.GetCurrentTimingPoints(t)[0],s=c.Main.AudioEngine.useSilentMusic?0:e.GetMaximumAudioLevel(),o=Math.min(1,.2+s);u.Ease.getEase(this.logoBeatContainer).ScaleTo(1-.02*o,this.early_activation,l.Easing.Linear.None).Then().ScaleTo(1,2*i,l.Easing.Quintic.Out),this.rippleContainer.scale=1.02,u.Ease.getEase(this.rippleContainer).ClearEasings().ScaleTo(1.02*(1+.04*o),i,l.Easing.Quintic.Out),this.ripple.alpha=.15*o,u.Ease.getEase(this.ripple).ClearEasings().FadeOut(i,l.Easing.Quintic.Out),n.effects==f.Effect.KiaiTime&&(u.Ease.getEase(this.triangles.flash).ClearEasings().FadeTo(.2*o,this.early_activation,l.Easing.Linear.None).Then().FadeTo(0,i,l.Easing.Linear.None),u.Ease.getEase(this.visualizer).ClearEasings().FadeTo(1.8*this.defaultVisualizerAlpha*o,this.early_activation,l.Easing.Linear.None).Then().FadeTo(this.defaultVisualizerAlpha,i,l.Easing.Linear.None)),setTimeout((()=>{this.triangles.Velocity+=o*(n.effects==f.Effect.KiaiTime?6:3)}),60)}}t.OsuLogo=m},44961:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.Triangles=void 0;const r=o(i(58687)),l=i(20825),u=a(i(46404)),c=a(i(58689)),d=a(i(61630));class h extends r.Container{flash;Velocity=1;bgGradient;triangles=[];graphics=new r.Graphics;timeSinceLastSpawn=0;instancePositionBuffer;totalTriangles=15;constructor(){super();let e=[16737963,13390473];this.bgGradient=new r.FillGradient(0,0,0,1024),e.forEach(((t,i)=>{const n=i/e.length;this.bgGradient.addColorStop(n,t)}));for(let e=0;e{this.mouseButtonClicked=e.button,this.visible&&(this.posMouseDown={x:r.Main.mousePos.x,y:r.Main.mousePos.y},this.mouseIsDown=!0,this.dragRotationState=f.DragStarted,d.Ease.getEase(this.animContainer).ClearEasings().ScaleTo(.9,800,h.Easing.Quintic.Out),d.Ease.getEase(this.mouseCursorAdditive).ClearEasings().FadeIn(800,h.Easing.Quintic.Out),r.Main.AudioEngine.PlayEffect(this.cursorTapSample))})),r.Main.app.stage.addEventListener("mouseup",(e=>{this.visible&&e.button==this.mouseButtonClicked&&(this.mouseIsDown=!1,d.Ease.getEase(this.animContainer).ClearEasings().ScaleTo(1,500,h.Easing.Elastic.Out),d.Ease.getEase(this.mouseCursorAdditive).ClearEasings().FadeOut(500,h.Easing.Quintic.Out),this.dragRotationState!=f.NotDragging&&(this.dragRotationState==f.Rotating&&d.Ease.getEase(this.animRotationContainer).ClearEasings().createTween({value:this.animRotationContainer.angle},{value:0},!0,"angle",800*(.5+Math.abs(this.animRotationContainer.angle/960)),(e=>Math.pow(2,-10*e)*Math.sin((.25*e-this.elastic_const2)*this.elastic_const)+1-this.elastic_offset_quarter*e)),this.dragRotationState=f.NotDragging),r.Main.AudioEngine.PlayEffect(this.cursorTapSample,.8))}))}PopIn(){d.Ease.getEase(this.animRotationContainer).ClearEasings(),this.visible=!0,d.Ease.getEase(this.mouseHideContainer).ClearEasings().FadeIn(250,h.Easing.Quintic.Out).ScaleTo(1,400,h.Easing.Quintic.Out),this.dragRotationState=f.NotDragging}PopOut(){d.Ease.getEase(this.mouseHideContainer).ClearEasings().FadeOut(250,h.Easing.Quintic.Out).ScaleTo(.6,250,h.Easing.Quintic.Out),d.Ease.getEase(this.animRotationContainer).ClearEasings().createTween({value:this.animRotationContainer.angle},{value:0},!0,"angle",400,h.Easing.Quintic.Out),this.dragRotationState=f.NotDragging}updateMouse(){if(this.mouseContainer.scale.set(.07*c.Screen.getScaleBasedOffScreenSize()),this.position.set(r.Main.mousePos.x,r.Main.mousePos.y),this.dragRotationState!=f.NotDragging&&this.visible){let e=Math.sqrt((2^Math.abs(this.posMouseDown.x-r.Main.mousePos.x))+(2^Math.abs(this.posMouseDown.y-r.Main.mousePos.y)));if(this.dragRotationState==f.DragStarted&&e>15&&(this.dragRotationState=f.Rotating,this.lastDragRotationState!=this.dragRotationState&&(this.posMouseDown={x:r.Main.mousePos.x,y:r.Main.mousePos.y})),this.dragRotationState==f.Rotating&&e>0){let e=r.Main.mousePos.x-this.posMouseDown.x,t=r.Main.mousePos.y-this.posMouseDown.y,i=u.MathUtil.RadiansToDegrees(Math.atan2(-e,t))+24.3,n=(i-this.animRotationContainer.angle)%360;n<-180&&(n+=360),n>180&&(n-=360),i=this.animRotationContainer.angle+n,this.animRotationContainer.angle=i,d.Ease.getEase(this.animRotationContainer).createTween({value:this.animRotationContainer.angle},{value:i},!0,"angle",120,h.Easing.Quintic.Out)}}this.lastDragRotationState=this.dragRotationState}}var f;t.MenuCursor=g,function(e){e[e.NotDragging=0]="NotDragging",e[e.DragStarted=1]="DragStarted",e[e.Rotating=2]="Rotating"}(f||(f={}))},67991:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.BackgroundContainer=t.Background=void 0;const a=o(i(58687)),r=i(92915),l=o(i(29172));class u extends a.Sprite{static fadeOutDuration=800;destroying=!1;constructor(e){super(),this.texture=e,this.visible=!1,this.anchor.set(.5,.5)}show(){this.visible=!0}destroy(e){this.destroying=!0,r.Ease.getEase(this).FadeOut(u.fadeOutDuration,l.Easing.Linear.None).Then((()=>{this.visible=!1,super.destroy(e),this.destroying=!1})),this.zIndex=1}}t.Background=u;class c extends a.Container{constructor(){super(),this.visible=!1}show(){this.visible=!0;for(let e=0;e{super.destroy(e)}),u.fadeOutDuration),this.zIndex=1}}t.BackgroundContainer=c},36721:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.RandomBackground=void 0;const a=o(i(58687)),r=i(12235),l=i(84283),u=i(20825),c=i(67991),d=i(15041);class h extends l.Screen{bgContainer=new a.Container;parallaxMultiplier=60;start(){this.bgContainer.pivot.set(.5,.5),this.bgContainer.position.set((u.Main.mousePos.x-this.getScreenWidth()/2)/this.parallaxMultiplier,(u.Main.mousePos.y-this.getScreenHeight()/2)/this.parallaxMultiplier),this.addChild(this.bgContainer),this.newRandomBG(),u.Main.AudioEngine.addMusicChangeEventListener((e=>{let t=e.beatmap.Events.Events.find((e=>{if(e.eventType==d.EventTypes.BACKGROUND)return e})),i=e.beatmap.Events.Events.find((e=>{if(e.eventType==d.EventTypes.VIDEO)return e})),n=new c.BackgroundContainer;if(t&&t.texture&&n.addChild(new c.Background(t.texture)),i&&i.texture){let e=i.texture.source.resource,t=new c.Background(i.texture);n.addChild(t),i.texture.source.resource.startPromise=new Promise((t=>{i.startTime>0?setTimeout((()=>{e.play(),t()}),i.startTime):(e.currentTime=Math.abs(i.startTime)/1e3,e.play(),t())})),e.onended=()=>{t.destroy()}}(t||i)&&this.setBGContainer(n),t||i||this.newRandomBG()})),this.zIndex=-100}setBG(e){let t=new c.Background(e);if(this.bgContainer.addChild(t),t.show(),0==this.bgContainer.children?.length);else{this.bgContainer.children[0].destroy()}this.onResize()}setBGContainer(e){if(this.bgContainer.addChild(e),e.show(),0==this.bgContainer.children?.length);else{this.bgContainer.children[0].destroy()}this.onResize()}newRandomBG(){let e=r.Loader.seasonalBackgroundsNum>0,t=(i=1,n=e?r.Loader.seasonalBackgroundsNum:r.Loader.defaultBackgroundsNum,Math.round(Math.random()*(n-i)+i));var i,n;this.setBG(a.Texture.from((e?"seasonal_bg":"default_bg")+t))}draw(e){this.bgContainer.position.set((u.Main.mousePos.x-this.getScreenWidth()/2)/this.parallaxMultiplier,(u.Main.mousePos.y-this.getScreenHeight()/2)/this.parallaxMultiplier)}onClose(){return Promise.resolve(this)}onResize(){this.bgContainer.children.forEach((e=>{e instanceof c.BackgroundContainer&&e.children?.forEach((e=>{e instanceof c.Background&&this.resizeSprite(e)})),e instanceof c.Background&&this.resizeSprite(e)}))}resizeSprite(e){let t,i=e.texture.width,n=e.texture.height;t=window.innerWidth>window.innerHeight?window.innerWidth/i:window.innerHeight/n,n*t{i.id==e&&(t=i.data)})),!t)throw new Error("Asset not found!");return t}static GetString(e){let t;if(this.loadedList.forEach((i=>{i.id==e&&(t=i.dataString)})),!t)throw new Error("Asset not found or is not a string!");return t}static GetAudio(e){let t;if(this.loadedList.forEach((i=>{i.id==e&&(t=i.dataAudio)})),!t)throw new Error("Asset not found or was not marked as audio during loading!");return t}static addBackgrounds(){return new Promise((e=>{for(let e=1;ee.json())).then((t=>{t.backgrounds.forEach(((e,t)=>{this.loadList.push({id:"seasonal_bg"+(t+1),url:"https://corsproxy.io/?"+encodeURIComponent(e.url),pixiBundleName:"textures",loadParser:"loadTextures"}),this.seasonalBackgroundsNum=t+1})),e()})).catch((t=>{console.warn("Could not fetch seasonal backgrounds.",t),e()}))}))}static Load(e){return this.addToLoadList(),new Promise((t=>{this.addBackgrounds().then((()=>{let i=[],n=[],s=[],o=0,r=0;this.loadList.forEach((e=>{e.pixiBundleName?n.push(e):i.push(e)})),n.forEach((e=>{let t=!1;s.forEach((i=>{i.length>0&&i[0].pixiBundleName==e.pixiBundleName&&(i.push(e),t=!0)})),t||s.push([e])}));const l=e=>{e?r++:o++,r+o>=this.loadList.length&&t()};i.forEach((t=>{fetch(t.url).then((e=>e.blob())).then((i=>{t.isText||t.isAudio?t.isText?i.text().then((e=>{l(),this.loadedList.push({id:t.id,data:i,dataString:e})})):t.isAudio&&i.arrayBuffer().then((t=>e.decodeAudioData(t))).then((e=>{l(),this.loadedList.push({id:t.id,data:i,dataAudio:e})})):(l(),this.loadedList.push({id:t.id,data:i}))})).catch((e=>{l(!0),console.warn("Asset '"+t.id+"' failed to load: "+e)}))})),s.forEach((e=>{if(e.length>0){if(!e[0].pixiBundleName)throw new Error("wtf????");let t=[];e.forEach((e=>{e.loadParser?t.push({alias:e.id,src:e.url,loadParser:e.loadParser}):t.push({alias:e.id,src:e.url})})),a.Assets.addBundle(e[0].pixiBundleName,t),a.Assets.loadBundle(e[0].pixiBundleName).then((()=>{e.forEach((()=>{l()}))}))}}))}))}))}}},25373:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.InteractScreen=void 0;const a=i(84283),r=o(i(58687)),l=i(20825),u=i(94433),c=o(i(29172)),d=i(92915);class h extends a.Screen{text;text2;textContainer=new r.Container;textContainerContainer=new r.Container;introTrack;clickSound;clickArea=new r.Graphics;constructor(e,t){super(),this.introTrack=e,this.clickSound=t,this.text=new r.Text({text:"Click anywhere to play!",style:{fontFamily:"TorusRegular",fontSize:36,fill:"white"}}),this.text2=new r.Text({text:"(this is for enabling audio because it's required by web-browsers\n to have interaction on this webpage before playing audio.)",style:{fontFamily:"TorusRegular",fontSize:26,fill:"gray",align:"center"}})}start(){this.text.anchor.set(.5,.5),this.text2.anchor.set(.5,.5),this.text2.position.set(0,this.text.height+15),this.textContainer.addChild(this.text),this.textContainer.addChild(this.text2),this.textContainer.scale.set(.5),this.textContainer.alpha=0,this.textContainerContainer.addChild(this.textContainer),this.textContainerContainer.scale=a.Screen.getScaleBasedOffScreenSize(),this.textContainerContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.addChild(this.textContainerContainer),this.clickArea.rect(0,0,1,1),this.clickArea.fill("rgba(0,0,0,0)"),this.clickArea.width=this.getScreenWidth(),this.clickArea.height=this.getScreenHeight(),this.clickArea.position.set(0,0),this.addChild(this.clickArea),this.clickArea.eventMode="static",this.clickArea.cursor="pointer";const e=()=>{this.clickArea.eventMode="none",l.Main.AudioEngine.PlayEffect(this.clickSound),l.Main.switchScreen(new u.IntroScreen(this.introTrack)),document.body.style.cursor="none",l.Main.pointerLock(),l.Main.lockKeyboard()};this.clickArea.onclick=()=>{e()},this.clickArea.ontap=()=>{e()},d.Ease.getEase(this.textContainer).FadeIn(400,c.Easing.Quadratic.Out).ScaleTo(1,400,c.Easing.Quadratic.Out)}onClose(){return new Promise((e=>{d.Ease.getEase(this.textContainer).FadeOut(200,c.Easing.Quadratic.Out).ScaleTo(.5,200,c.Easing.Quadratic.InOut),setTimeout((()=>{e(this)}),200)}))}draw(e){}onResize(){this.textContainerContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.clickArea.width=this.getScreenWidth(),this.clickArea.height=this.getScreenHeight(),this.clickArea.position.set(0,0),this.textContainerContainer.scale=a.Screen.getScaleBasedOffScreenSize()}}t.InteractScreen=h},88662:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.GlitchingTriangles=void 0;const a=o(i(58687)),r=i(92915),l=o(i(29172));class u extends a.Container{constructor(e){super();let t=new a.Graphics,i=n(.2,1.2);function n(e,t){return Math.random()*(t-e)+e}t.moveTo(0,0),t.lineTo(-50*i,100*i),t.lineTo(50*i,100*i),t.lineTo(0,0),Math.random()<.5?t.fill("white"):t.stroke({color:"white",width:1});let s=n(e.x1,e.x2),o=n(e.y1,e.y2);t.position.set(s,o),r.Ease.getEase(t,!0).FadeOut(200,l.Easing.Linear.None),setTimeout((()=>{this.destroy()}),200),this.addChild(t)}}t.GlitchingTriangles=u},94433:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.IntroScreen=void 0;const a=i(84283),r=o(i(58687)),l=i(53931),u=i(20825),c=i(88662),d=i(58940),h=i(55402),g=i(9752),f=o(i(29172)),p=i(92915),m=i(5168),v=i(94461);class b extends a.Screen{introTrackUrl;doTextSpacingAnim=!1;triangles=new r.Container;ruleSetContainer=new r.Container;ruleSetList=new v.CenteredList({});flash=new r.Graphics;logoContainerContainer=new r.Container;logoContainer=new r.Container;lazerLogo=new h.LazerLogo;flashed=!1;standard=r.Sprite.from("icon_ruleset_std");taiko=r.Sprite.from("icon_ruleset_taiko");ctb=r.Sprite.from("icon_ruleset_ctb");mania=r.Sprite.from("icon_ruleset_mania");bg=new r.Graphics;completionPromise;welcomeText=new r.Text({text:"",style:{fontFamily:"TorusThin",fontSize:42,fill:"white",letterSpacing:5}});constructor(e){super(),this.introTrackUrl=URL.createObjectURL(e),this.bg.rect(0,0,1,1),this.bg.fill("black")}start(){this.bg.width=window.innerWidth,this.bg.height=window.innerHeight,this.bg.x=0,this.bg.y=0,this.addChild(this.bg),this.lazerLogo.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.logoContainer.addChild(this.lazerLogo),this.logoContainer.scale.set(1.2),this.logoContainerContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.logoContainerContainer.pivot.set(.5,.5),this.logoContainerContainer.addChild(this.logoContainer),this.logoContainerContainer.alpha=0,this.addChild(this.logoContainerContainer),this.flash.rect(0,0,1,1),this.flash.fill("white"),this.flash.position.set(0,0),this.flash.width=this.getScreenWidth(),this.flash.height=this.getScreenHeight(),this.flash.blendMode="add",this.welcomeText.anchor.set(.5,.5),this.welcomeText.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),(async()=>{const{entries:e}=await(0,l.unzip)(this.introTrackUrl);for(const[t,i]of Object.entries(e))if(t.endsWith(".osu")){i.text().then((async t=>{let i=g.BeatmapParser.Parse(t);for(const[t,n]of Object.entries(e)){let e=await n.blob();i.files.set(t,e)}await g.BeatmapParser.LoadFiles(i);let n=i.General.audioFile;if(n){let e=URL.createObjectURL(n);setTimeout((()=>{u.Main.AudioEngine.PlayMusicImmediately(e,i,(()=>{this.afterAudioPlay()}))}),200)}console.log(i)}));break}})()}afterAudioPlay(){this.completionPromise=new Promise((e=>{let t;this.welcomeText.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.addChild(this.welcomeText),setTimeout((()=>{this.welcomeText.text="wel",this.onResize()}),200),setTimeout((()=>{this.welcomeText.text="welcome",this.onResize()}),400),setTimeout((()=>{this.welcomeText.text="welcome to",this.onResize()}),700),this.triangles.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.triangles.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.addChild(this.triangles),setTimeout((()=>{this.welcomeText.text="welcome to kosu!",this.doTextSpacingAnim=!0,t=setInterval((()=>{let e=new c.GlitchingTriangles({x1:-this.welcomeText.width/2-100,x2:this.welcomeText.width/2+100,y1:-this.welcomeText.height/2-150,y2:this.welcomeText.height/2+100});this.triangles.addChild(e)}),30),this.onResize()}),900),this.standard.scale=.5*a.Screen.getScaleBasedOffScreenSize(),this.ctb.scale=.5*a.Screen.getScaleBasedOffScreenSize(),this.mania.scale=.5*a.Screen.getScaleBasedOffScreenSize(),this.taiko.scale=.5*a.Screen.getScaleBasedOffScreenSize(),this.ruleSetList.addChild(this.standard),this.ruleSetList.addChild(this.taiko),this.ruleSetList.addChild(this.ctb),this.ruleSetList.addChild(this.mania),this.ruleSetList.padding=0,this.ruleSetList.elementsMargin=200*a.Screen.getScaleBasedOffScreenSize(),this.ruleSetList.type="horizontal",this.ruleSetList.scale=1,this.ruleSetContainer.addChild(this.ruleSetList),setTimeout((()=>{this.doTextSpacingAnim=!1,this.onResize(),clearInterval(t),this.welcomeText.destroy(),this.triangles.destroy(),this.ruleSetContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.addChild(this.ruleSetContainer),this.ruleSetList.elementsMargin=200*a.Screen.getScaleBasedOffScreenSize(),p.Ease.getEase(this.ruleSetContainer).ScaleTo(.8,1e3,f.Easing.Linear.None)}),1450),setTimeout((()=>{this.ruleSetList.elementsMargin=30*a.Screen.getScaleBasedOffScreenSize(),this.ruleSetList.scale=2,m.UIUtils.centerPivotOfList(this.ruleSetList)}),1650),setTimeout((()=>{this.ruleSetList.elementsMargin=10*a.Screen.getScaleBasedOffScreenSize(),this.ruleSetList.scale=4,p.Ease.getEase(this.ruleSetContainer).ScaleTo(1.3,1e3,f.Easing.Linear.None)}),1850),setTimeout((()=>{this.ruleSetContainer.destroy(),this.lazerLogo.start(),this.logoContainerContainer.alpha=1,this.logoContainerContainer.scale.set(1.2),p.Ease.getEase(this.logoContainerContainer).ScaleTo(1,920,f.Easing.Quadratic.In),setTimeout((()=>{p.Ease.getEase(this.logoContainer).ScaleTo(1.2-.8,276,f.Easing.Quintic.In)}),644)}),2080),setTimeout((()=>{this.addChild(this.flash),this.bg.destroy(),this.flash.eventMode="none",this.flashed=!0,this.logoContainerContainer.visible=!1,p.Ease.getEase(this.flash).FadeOut(1e3,f.Easing.Quadratic.Out).Then((()=>{e()})),u.Main.cursor.PopIn()}),3e3)})),u.Main.switchScreen(new d.MainMenu)}draw(e){this.doTextSpacingAnim&&(this.welcomeText.style.letterSpacing+=.15*e.deltaTime,this.onResize())}onClose(){return new Promise((e=>{this.completionPromise.then((()=>{e(this)}))}))}onResize(){this.bg.destroyed||(this.bg.width=window.innerWidth,this.bg.height=window.innerHeight,this.bg.x=0,this.bg.y=0),this.welcomeText.destroyed||this.welcomeText.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.triangles.destroyed||(this.triangles.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.triangles.scale.set(a.Screen.getScaleBasedOffScreenSize())),this.ruleSetContainer.destroyed||this.ruleSetContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.flash.destroyed||(this.flash.position.set(0,0),this.flash.width=this.getScreenWidth(),this.flash.height=this.getScreenHeight()),this.logoContainerContainer.destroyed||this.logoContainerContainer.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.lazerLogo.destroyed||this.lazerLogo.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.welcomeText.destroyed||this.welcomeText.scale.set(a.Screen.getScaleBasedOffScreenSize()),this.standard.destroyed||this.standard.scale.set(.5*a.Screen.getScaleBasedOffScreenSize()),this.mania.destroyed||this.mania.scale.set(.5*a.Screen.getScaleBasedOffScreenSize()),this.ctb.destroyed||this.ctb.scale.set(.5*a.Screen.getScaleBasedOffScreenSize()),this.taiko.destroyed||this.taiko.scale.set(.5*a.Screen.getScaleBasedOffScreenSize()),this.ruleSetList.destroyed||this.ruleSetList.ReCenter()}}t.IntroScreen=b},55402:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.LazerLogo=void 0;const a=o(i(58687)),r=i(87525),l=o(i(29172)),u=i(92915);class c extends a.Container{highlight;background;textureHighlight=a.Texture.from("intro_triangles_osuLogo_anim_highlight");textureBackground=a.Texture.from("intro_triangles_osuLogo_anim_background");constructor(){super(),this.highlight=new r.LogoAnimation(this.textureHighlight,new a.Color("white")),this.background=new r.LogoAnimation(this.textureBackground,new a.Color("rgb(128, 128, 128)")),this.addChild(this.highlight),this.addChild(this.background)}start(){let e=new a.Container;e.scale.set(0,0),u.Ease.getEase(e).ScaleTo(1,920,l.Easing.Linear.None).OnEach((()=>{this.highlight.setProgress(e.scale.x),this.background.setProgress(e.scale.x)}))}}t.LazerLogo=c},87525:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.LogoAnimation=void 0;const r=o(i(58687)),l=a(i(26045)),u=a(i(44160)),c=a(i(46110));class d extends r.Container{shader;texture;constructor(e,t){super(),this.texture=e,this.shader=r.Shader.from({gl:{vertex:l.default,fragment:u.default},gpu:{vertex:{entryPoint:"mainVert",source:c.default},fragment:{entryPoint:"mainFrag",source:c.default}},resources:{uTexture:this.texture.source,uSampler:this.texture.source.style,uProgress:{progress:{value:0,type:"f32"}}}});const i=new r.Geometry({attributes:{aPosition:[-this.texture.width/2,-this.texture.height/2,this.texture.width/2,-this.texture.height/2,this.texture.width/2,this.texture.width/2,-this.texture.width/2,this.texture.width/2],aUV:[0,0,1,0,1,1,0,1],aColor:[t.red,t.green,t.blue,t.alpha,t.red,t.green,t.blue,t.alpha,t.red,t.green,t.blue,t.alpha,t.red,t.green,t.blue,t.alpha]},indexBuffer:[0,1,2,0,2,3]}),n=new r.Mesh({geometry:i,shader:this.shader});this.addChild(n)}setProgress(e){this.shader.resources.uProgress.uniforms.progress=e}}t.LogoAnimation=d},76969:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.LoadScreen=void 0;const n=i(84283),s=i(49323);class o extends n.Screen{loadAnim=new s.LoadAnim("rgba(255,255,255,0.7)","black");start(){this.loadAnim.scale.set(.8*n.Screen.getScaleBasedOffScreenSize()),this.loadAnim.position.set(this.getScreenWidth()-this.loadAnim.getWidth()-15,this.getScreenHeight()-this.loadAnim.getHeight()-15),this.addChild(this.loadAnim)}draw(e){this.loadAnim?.draw(e)}onClose(){return new Promise((e=>{null!=this.loadAnim&&this.loadAnim.destroy(),setTimeout((()=>{e(this)}),400)}))}onResize(){this.loadAnim.position.set(this.getScreenWidth()-this.loadAnim.getWidth()-20,this.getScreenHeight()-this.loadAnim.getHeight()-20),this.loadAnim.scale.set(.8*n.Screen.getScaleBasedOffScreenSize())}}t.LoadScreen=o},58940:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MainMenu=void 0;const n=i(84283),s=i(36721),o=i(73703),a=i(70723);class r extends n.Screen{bg=new s.RandomBackground;osuCircle=new o.OsuLogo;menu=new a.ButtonSystem(this.osuCircle);start(){this.bg.start(),this.addChild(this.bg),this.osuCircle.scale=n.Screen.getScaleBasedOffScreenSize(),this.addChild(this.menu),this.menu.onResize(),this.addChild(this.osuCircle)}draw(e){this.bg.draw(e),this.osuCircle.draw(e)}onClose(){return new Promise((e=>{this.bg.onClose().then((()=>{e(this)}))}))}onResize(){this.osuCircle.position.set(this.getScreenWidth()/2,this.getScreenHeight()/2),this.bg.onResize(),this.menu.onResize(),this.osuCircle.scale=this.menu.isOpen()?.5*n.Screen.getScaleBasedOffScreenSize():n.Screen.getScaleBasedOffScreenSize()}}t.MainMenu=r},84283:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Screen=void 0;const a=o(i(58687)),r=i(58293),l=i(64681);class u extends a.Container{constructor(){super()}static getScaleBasedOffScreenSize(){const e=r.Settings.getSetting(l.UIScale).getValue();return(window.innerWidth/1920+window.innerHeight/1080)/2*e}getScreenWidth(){return window.innerWidth}getScreenHeight(){return window.innerHeight}}t.Screen=u},75341:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.SettingsCategory=t.Setting=void 0;const n=i(58293);var s;t.Setting=class{info;constructor(e){this.info=e,n.Settings.register({setting:this,info:e})}onValueChanged(){}},function(e){e.General="General",e.Skin="Skin",e.Input="Input",e.UserInterface="User Interface",e.Gameplay="Gameplay",e.Rulesets="Rulesets",e.Audio="Audio",e.Graphics="Graphics",e.Online="Online",e.Maintenance="Maintenance",e.Debug="Debug"}(s||(t.SettingsCategory=s={}))},74975:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.DropdownSetting=void 0;const n=i(75341),s=i(58293);class o extends n.Setting{value;getValue(){if(!this.value)throw new Error("Value is undefined!");return this.value}getDefaultValue(){return this.defaultValue}setValue(e){this.list.find((t=>t.value==e.value&&t.displayName==e.displayName))?(this.value=e,s.Settings.save(),this.onValueChanged()):console.warn("The value provided to this DropDownSetting does not exist in the option list! Ignoring value provided.")}loadFromSaveValue(e){this.list.find((t=>t.value==e.value&&t.displayName==e.displayName))?(this.value=e,this.onValueChanged()):console.warn("The value provided to this DropDownSetting does not exist in the option list! Ignoring value provided.")}}t.DropdownSetting=o},78642:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.RangeSetting=void 0;const n=i(75341),s=i(58293),o=i(5825);class a extends n.Setting{value=0;getValue(){return this.value}getDefaultValue(){return this.defaultValue}setValue(e){this.value=o.MathUtil.clamp(this.minValue,this.maxValue,e),s.Settings.save(),this.onValueChanged()}loadFromSaveValue(e){this.value=o.MathUtil.clamp(this.minValue,this.maxValue,e),this.onValueChanged()}}t.RangeSetting=a},58293:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.Settings=void 0;const n=i(64681),s=i(44256),o=i(59029);t.Settings=class{static settingsList=[];static registerAll(){new n.UIScale,new s.Renderer,new o.MouseSensitivity}static load(){let e=window.localStorage.getItem("settings");if(null==e)return;let t=this.getList();try{JSON.parse(e).forEach((e=>{let i=!1;try{e.value||(console.warn("Setting '"+JSON.stringify(e)+"' may be corrupted, skipping!"),i=!0),e.info?(e.info.name||(console.warn("Setting '"+JSON.stringify(e)+"' may be corrupted, skipping!"),i=!0),e.info.category||(console.warn("Setting '"+JSON.stringify(e)+"' may be corrupted, skipping!"),i=!0)):(console.warn("Setting '"+JSON.stringify(e)+"' may be corrupted, skipping!"),i=!0)}catch(e){console.warn("Something went wrong when validating saved settings!",e),console.warn("The setting may be REALLY corrupted, skipping!"),i=!0}if(!i){let i=t.filter((t=>t.info.name==e.info.name&&t.info.category==e.info.category))[0];i?i.setting.loadFromSaveValue(e.value):console.warn("Could not find setting object '"+e.info.name+"', maybe it has been removed in this version of kosu?, skipping setting")}}))}catch(e){console.warn("Failed to load settings! Resetting Settings due to corrupted save!",e),this.reset()}}static save(){let e=this.getList(),t=[];e.forEach((e=>{e.setting.getValue()!=e.setting.getDefaultValue()&&t.push({info:e.info,value:e.setting.getValue()})})),window.localStorage.setItem("settings",JSON.stringify(t))}static reset(){console.warn("Resetting Settings!"),window.localStorage.removeItem("settings")}static register(e){this.settingsList.push(e)}static getSetting(e){return this.settingsList.filter((t=>t.setting instanceof e))[0].setting}static getSettingData(e){return this.settingsList.filter((t=>t.setting instanceof e))[0]}static getList(){return this.settingsList}}},44256:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.Renderer=void 0;const n=i(75341),s=i(74975);class o extends s.DropdownSetting{list=[];webglOption={displayName:"WebGL",value:"webgl"};webGpuOption={displayName:"WebGPU",value:"webgpu"};defaultValue=this.webglOption;constructor(){super({name:"Renderer",category:n.SettingsCategory.Graphics}),this.list.push(this.webglOption,this.webGpuOption),this.value=this.defaultValue}}t.Renderer=o},64681:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.UIScale=void 0;const n=i(78642),s=i(75341);class o extends n.RangeSetting{maxValue=1.6;minValue=.8;increment=.1;defaultValue=1;constructor(){super({name:"UI scaling",category:s.SettingsCategory.Graphics}),this.value=this.defaultValue}}t.UIScale=o},59029:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MouseSensitivity=void 0;const n=i(78642),s=i(75341),o=i(58687);class a extends n.RangeSetting{defaultValue=1;increment=.01;maxValue=10;minValue=.1;constructor(){super({name:"Sensitivity",category:s.SettingsCategory.Input}),this.value=this.defaultValue,this.onValueChanged()}onValueChanged(){o.EventSystem.cursorSensitivity=this.getValue()}}t.MouseSensitivity=a},17898:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.BeatmapData=void 0;const n=i(85932),s=i(20352),o=i(32007),a=i(78878),r=i(54611),l=i(6386),u=i(43354);t.BeatmapData=class{files=new Map;General=new n.GeneralData;Editor=new s.EditorData;Metadata=new o.Metadata;Difficulty=new a.DifficultyData;Events=new r.EventsData;TimingPoints=new l.TimingPointsData;Colors=new u.ColorsData}},43354:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.ColorsData=void 0;t.ColorsData=class{Colors=[]}},78878:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.DifficultyData=void 0;t.DifficultyData=class{HPDrainRate;CircleSize;OverallDifficulty;ApproachRate;SliderMultiplier;SliderTickRate}},20352:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.EditorData=void 0;t.EditorData=class{Bookmarks=[];DistanceSpacing;BeatDivisor;GridSize;TimelineZoom}},90361:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.Event=void 0;t.Event=class{eventType;startTime=0}},64432:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventBackground=void 0;const n=i(90361),s=i(15041);class o extends n.Event{eventType=s.EventTypes.BACKGROUND;startTime=0;filename;xOffset;yOffset;texture}t.EventBackground=o},21191:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventBreak=void 0;const n=i(90361),s=i(15041);class o extends n.Event{eventType=s.EventTypes.BREAK;endTime=0}t.EventBreak=o},15041:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.EventTypes=void 0,function(e){e.BACKGROUND="0",e.VIDEO="Video",e.BREAK="Break",e.SPRITE="Sprite",e.ANIMATION="Animation"}(i||(t.EventTypes=i={}))},19437:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EventVideo=void 0;const n=i(90361),s=i(15041);class o extends n.Event{eventType=s.EventTypes.VIDEO;filename;xOffset;yOffset;texture}t.EventVideo=o},54611:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.EventsData=void 0;t.EventsData=class{Events=[]}},37940:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.Countdown=void 0,function(e){e[e.NoCountdown=0]="NoCountdown",e[e.Normal=1]="Normal",e[e.Half=2]="Half",e[e.Double=3]="Double"}(i||(t.Countdown=i={}))},85932:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.GeneralData=void 0;const n=i(37940),s=i(41080),o=i(90857),a=i(45274);t.GeneralData=class{audioFile;AudioFilename=null;AudioLeadIn=0;AudioHash=null;PreviewTime=-1;Countdown=n.Countdown.Normal;SampleSet=s.SampleSet.Normal;StackLeniency=.7;Mode=o.Mode.OSU;LetterboxInBreaks=!1;StoryFireInFront=!0;UseSkinSprites=!1;AlwaysShowPlayfield=!1;OverlayPosition=a.OverlayPosition.NoChange;SkinPreference=null;EpilepsyWarning=!1;CountdownOffset=0;SpecialStyle=!1;WidescreenStoryboard=!1;SamplesMatchPlaybackRate=!1}},90857:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.Mode=void 0,function(e){e[e.OSU=0]="OSU",e[e.TAIKO=1]="TAIKO",e[e.CATCH=2]="CATCH",e[e.MANIA=3]="MANIA"}(i||(t.Mode=i={}))},45274:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.OverlayPosition=void 0,function(e){e.NoChange="NoChange",e.Below="Below",e.Above="Above"}(i||(t.OverlayPosition=i={}))},41080:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.SampleSet=void 0,function(e){e.Normal="Normal",e.Soft="Soft",e.Drum="Drum"}(i||(t.SampleSet=i={}))},32007:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.Metadata=void 0;t.Metadata=class{Title;TitleUnicode;Artist;ArtistUnicode;Creator;Version;Source;Tags;BeatmapID;BeatmapSetID}},22331:function(e,t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.Effect=void 0,function(e){e[e.KiaiTime=1]="KiaiTime",e[e.None=0]="None",e[e.FirstBarLineOmittedInOsuTaikoAndOsuMania=3]="FirstBarLineOmittedInOsuTaikoAndOsuMania"}(i||(t.Effect=i={}))},3143:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.InheritedTimingPoint=void 0;const n=i(52032);class s extends n.TimingPoint{sliderVelocityMultiplier}t.InheritedTimingPoint=s},52032:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.TimingPoint=void 0;t.TimingPoint=class{time;sampleSet;sampleIndex;volume;effects}},6386:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.TimingPointsData=void 0;const n=i(87816),s=i(3143);t.TimingPointsData=class{TimingPoints=[];GetCurrentTimingPoints(e){let t=[],i=this.TimingPoints.filter((t=>{if(t.time<=e)return t}));if(0==i.length&&i.push(this.TimingPoints[0]),t.push(i[i.length-1]),t[0]instanceof s.InheritedTimingPoint){let i=this.TimingPoints.filter((e=>e instanceof n.UnInheritedTimingPoint)).filter((t=>{if(t.time<=e)return t}));if(0==i.length)throw new Error("Could not find a parent timing point for the un-inherited timing point!");t.push(i[i.length-1])}if(0==t.length)throw new Error("Could not find any timing points!");return t}GetCurrentUninheritedTimingPoint(e){let t,i=this.GetCurrentTimingPoints(e);if(i[0]instanceof n.UnInheritedTimingPoint)t=i[0];else{if(!(i[1]instanceof n.UnInheritedTimingPoint))throw new Error("Could not find any UnInherited Timing Points!");t=i[1]}return t}}},87816:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.UnInheritedTimingPoint=void 0;const n=i(52032);class s extends n.TimingPoint{beatLength;meter}t.UnInheritedTimingPoint=s},9752:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.BeatmapParser=void 0;const n=i(17898),s=i(30444),o=i(81347),a=i(23114),r=i(98803),l=i(92880),u=i(25820);class c{static Parse(e,t){const i=new n.BeatmapData;let d=e.split(/\r?\n|\r|\n/g);return o.GeneralParser.ParseGeneral(i,c.GetSection("General",d)),a.EditorParser.ParseEditor(i,c.GetSection("Editor",d)),r.MetadataParser.ParseMetadata(i,c.GetSection("Metadata",d)),l.DifficultyParser.ParseDifficulty(i,c.GetSection("Difficulty",d)),u.EventsParser.ParseEvents(i,c.GetSection("Events",d)),s.TimingPointsParser.ParseTimingPoints(i,c.GetSection("TimingPoints",d)),i}static async LoadFiles(e){await o.GeneralParser.LoadFiles(e),await u.EventsParser.LoadFiles(e)}static GetSection(e,t){let i=[];return t.forEach(((n,s)=>{if(n=="["+e+"]")for(let e=s+1;e{let i=t.split(":");i[1].startsWith(" ")&&(i[1]=i[1].substring(1,i[1].length)),n.BeatmapParser.AutoParse(s.DifficultyData,i,e.Difficulty)}))}}},23114:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.EditorParser=void 0;const n=i(9752),s=i(20352);t.EditorParser=class{static ParseEditor(e,t){t.forEach((t=>{let i=t.split(":");i[1].startsWith(" ")&&(i[1]=i[1].substring(1,i[1].length)),"Bookmarks"!=i[0]?n.BeatmapParser.AutoParse(s.EditorData,i,e.Editor):i[1].split(",").forEach((t=>{e.Editor.Bookmarks.push(parseFloat(t))}))}))}}},25820:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.EventsParser=void 0;const a=i(15041),r=i(64432),l=i(19437),u=i(21191),c=i(81354),d=o(i(58687)),h=i(12235);t.EventsParser=class{static aviTranscodedVideoCache=[];static ParseEvents(e,t){t.forEach((t=>{let i,n=t.split(",");switch(n[0]){case a.EventTypes.BACKGROUND:i=new r.EventBackground,i.filename=n[2].replaceAll('"',""),i.xOffset=parseInt(n[3]),i.yOffset=parseInt(n[4]),isNaN(i.xOffset)&&(i.xOffset=0),isNaN(i.yOffset)&&(i.yOffset=0);break;case a.EventTypes.VIDEO:case"1":i=new l.EventVideo,i.startTime=parseInt(n[1]),i.filename=n[2].replaceAll('"',""),i.xOffset=parseInt(n[3]),i.yOffset=parseInt(n[4]),isNaN(i.xOffset)&&(i.xOffset=0),isNaN(i.yOffset)&&(i.yOffset=0);break;case a.EventTypes.BREAK:case"2":i=new u.EventBreak,i.startTime=parseInt(n[1]),i.endTime=parseInt(n[2])}i&&e.Events.Events.push(i)}))}static async LoadFiles(e){for(const t of e.Events.Events)for(let i in t)if("filename"==i||"filepath"==i){let n=e.files.get(t[i]);if(n){let s=URL.createObjectURL(n);if(t instanceof r.EventBackground)try{t.texture=await d.Assets.load({src:s,loadParser:"loadTextures"})}catch(e){console.warn(e)}if(t instanceof l.EventVideo){let o=!1;if(t[i].endsWith(".avi")){let a=this.aviTranscodedVideoCache.find((n=>{if(n.beatmapSID==e.Metadata.BeatmapSetID&&n.filePath==t[i])return n}));try{if(a)e.files.delete(t[i]),t[i]=t[i].substring(0,t[i].length-4)+".mp4",e.files.set(t[i],a.blob),URL.revokeObjectURL(s),s=URL.createObjectURL(a.blob);else{console.warn("AVI video is not natively supported! Transcoding to .mp4, this may take a few minutes!");let o=new c.FFmpeg;o.on("progress",(e=>{let{progress:t,time:i}=e;console.log(`.avi to .mp4 transcoding: ${Math.round(1e3*t)/10}% (transcoded time: ${Math.round(i/1e5)/10}s)`)})),console.log("FFmpeg initialized");let a=h.Loader.Get("workers.ffmpeg"),r=h.Loader.Get("ffmpeg.core"),l=h.Loader.Get("ffmpeg.wasm"),u=h.Loader.Get("ffmpeg.coreWorker");await o.load({classWorkerURL:URL.createObjectURL(a),coreURL:URL.createObjectURL(r),wasmURL:URL.createObjectURL(l),workerURL:URL.createObjectURL(u)}),console.log("FFmpeg loaded"),await o.writeFile("input.avi",new Uint8Array(await n.arrayBuffer())),console.log("Written file to FFmpeg's vfs"),await o.exec(["-i","input.avi","-c:v","libx264","-preset","ultrafast","-an","-movflags","faststart","output.mp4"]),console.log("Transcoding done");const d=await o.readFile("output.mp4");o.terminate(),console.log("FFmpeg terminated");let g=new Blob([d],{type:"video/mp4"});this.aviTranscodedVideoCache.push({beatmapSID:e.Metadata.BeatmapSetID,filePath:t[i],blob:g}),e.files.delete(t[i]),t[i]=t[i].substring(0,t[i].length-4)+".mp4",e.files.set(t[i],g),URL.revokeObjectURL(s),s=URL.createObjectURL(g),console.log("Successfully transcoded from .avi to .mp4!")}}catch(e){console.warn(e),o=!0}}if(!o)try{t.texture=await d.Assets.load({src:s,loadParser:"loadVideo"}),t.texture&&(t.texture.source.resource.volume=0,t.texture.source.resource.pause())}catch(e){console.warn(e)}}}else console.warn("Could not find referenced file: "+t[i])}}}},81347:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.GeneralParser=void 0;const n=i(85932),s=i(9752);t.GeneralParser=class{static ParseGeneral(e,t){t.forEach((t=>{let i=t.split(":");i[1].startsWith(" ")&&(i[1]=i[1].substring(1,i[1].length)),s.BeatmapParser.AutoParse(n.GeneralData,i,e.General)}))}static async LoadFiles(e){e.General.AudioFilename&&(e.General.audioFile=e.files.get(e.General.AudioFilename))}}},98803:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MetadataParser=void 0;const n=i(9752),s=i(32007);t.MetadataParser=class{static ParseMetadata(e,t){t.forEach((t=>{let i=t.split(":");i[1].startsWith(" ")&&(i[1]=i[1].substring(1,i[1].length)),n.BeatmapParser.AutoParse(s.Metadata,i,e.Metadata)}))}}},30444:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.TimingPointsParser=void 0;const n=i(87816),s=i(3143),o=i(22331);t.TimingPointsParser=class{static ParseTimingPoints(e,t){t.forEach((t=>{let i,a=t.split(",");"1"==a[6]?(i=new n.UnInheritedTimingPoint,i.beatLength=Number.parseFloat(a[1]),i.meter=Number.parseInt(a[2])):(i=new s.InheritedTimingPoint,i.sliderVelocityMultiplier=Number.parseFloat(a[1])),i.time=Number.parseInt(a[0]),i.sampleSet=Number.parseInt(a[3]),i.sampleIndex=Number.parseInt(a[4]),i.volume=Number.parseInt(a[5]),"1"==a[7]||"3"==a[7]?i.effects=Number.parseInt(a[7]):i.effects=o.Effect.None,e.TimingPoints.TimingPoints.push(i)}))}}},5825:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.MathUtil=void 0;class i{static RadiansToDegrees(e){return 180*e/Math.PI}static DegreesToRadians(e){return e*Math.PI/180}static clamp(e,t,i){return Math.min(Math.max(i,e),t)}static clamp01(e){return i.clamp(0,1,e)}static Damp(e,t,n,s){return i.Lerp(e,t,1-Math.pow(n,s))}static Lerp(e,t,i){return e+(t-e)*i}}t.MathUtil=i},92915:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Ease=void 0;const a=o(i(29172));class r{static previousEases=[];easings=[];obj;delay=null;constructor(e,t){this.obj=e,t||r.previousEases.push(this)}static getEase(e,t){null==t&&(t=!1);let i=r.previousEases.filter((t=>t.obj==e));return i.length>0?i[0]:new r(e,t)}createTween(e,t,i,n,s,o){const r={value:0},u=new a.Tween(i?r:e),c=new l(u);return u.to(i?{value:1}:t,s),u.easing(o),u.onUpdate((()=>{this.obj.destroyed||(this.obj[n]=i?r.value*(t.value-e.value)+e.value:e),c.onUpdate()})),u.onStart((()=>{i&&(e.value=this.obj[n])})),null==this.delay?u.start():(this.delay.chain(u),this.delay=null),this.easings.push(c),u.onStop((()=>{this.onDone(u)})),u.onComplete((()=>{this.onDone(u)})),this}TransformTo(e,t,i){return this.createTween(this.obj.position,e,!1,"position",t,i),this}onDone(e){this.easings=this.easings.filter((t=>t.tween!=e))}ScaleTo(e,t,i){let n={x:0,y:0};return"number"==typeof e&&(n.x=e,n.y=e),this.createTween(this.obj.scale,n,!1,"scale",t,i),this}FadeTo(e,t,i){return this.createTween({value:this.obj.alpha},{value:e},!0,"alpha",t,i),this}FadeOut(e,t){return this.FadeTo(0,e,t),this}FadeIn(e,t){return this.FadeTo(1,e,t),this}ClearEasings(){return this.easings.forEach((e=>{e.tween.stop()})),this.easings=[],this}Then(e){let t=this.easings.sort(((e,t)=>e.tween.getDuration()-t.tween.getDuration()));return t.length>0&&(this.delay=t[0].tween,null!=e&&(t[0].tween.onComplete((()=>{this.onDone(t[0].tween),e()})),t[0].tween.onStop((()=>{this.onDone(t[0].tween),e()})))),this}OnEach(e){let t=this.easings.sort(((e,t)=>e.tween.getDuration()-t.tween.getDuration()));t.length>0&&t[0].registerOnUpdate(e)}}t.Ease=r;class l{tween;updateEventListeners=[];constructor(e){this.tween=e}onUpdate(){this.updateEventListeners.forEach((e=>{e()}))}registerOnUpdate(e){this.updateEventListeners.push(e)}unRegisterOnUpdate(e){this.updateEventListeners=this.updateEventListeners.filter((t=>!(e===t)))}}},94461:function(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.CenteredList=void 0;const n=i(70828),s=i(5168);class o extends n.List{get elementsMargin(){return super.elementsMargin}set elementsMargin(e){super.elementsMargin=e,s.UIUtils.centerPivotOfList(this)}ReCenter(){s.UIUtils.centerPivotOfList(this)}}t.CenteredList=o},5168:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.UIUtils=void 0;t.UIUtils=class{static centerPivotOfList(e){let t=e.leftPadding,i=e.topPadding;for(let n=0;n{const e=o.Settings.getSetting(a.Renderer).getValue().value;d.init({backgroundColor:"black",width:u,height:c,antialias:!0,preference:e,resolution:window.devicePixelRatio,autoDensity:!0}).then((()=>{new s.Main(d)}))},navigator.mediaSession.setActionHandler("play",(()=>{s.Main.AudioEngine.GetCurrentPlayingMusicNoSilent()?.Play()})),navigator.mediaSession.setActionHandler("pause",(()=>{s.Main.AudioEngine.GetCurrentPlayingMusicNoSilent()?.Pause()})),navigator.mediaSession.setActionHandler("stop",(()=>{})),navigator.mediaSession.setActionHandler("seekbackward",(()=>{})),navigator.mediaSession.setActionHandler("seekforward",(()=>{})),navigator.mediaSession.setActionHandler("seekto",(()=>{})),navigator.mediaSession.setActionHandler("previoustrack",(()=>{})),navigator.mediaSession.setActionHandler("nexttrack",(()=>{})),Object.defineProperty(window,"setSensitivity",{value:e=>{o.Settings.getSetting(r.MouseSensitivity).setValue(e)}}),Object.defineProperty(window,"setRenderer",{value:e=>{let t=o.Settings.getSetting(a.Renderer);t.setValue("webgl"==e?t.webglOption:t.webGpuOption),window.location.reload()}}),Object.defineProperty(window,"setUIScale",{value:e=>{o.Settings.getSetting(l.UIScale).setValue(e),window.location.reload()}})},20825:function(e,t,i){var n=this&&this.__createBinding||(Object.create?function(e,t,i,n){void 0===n&&(n=i);var s=Object.getOwnPropertyDescriptor(t,i);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,n,s)}:function(e,t,i,n){void 0===n&&(n=i),e[n]=t[i]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&n(t,e,i);return s(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Main=void 0;const a=o(i(58687)),r=i(76969),l=i(25373),u=i(12235),c=i(55686),d=i(85437),h=o(i(29172)),g=i(29847),f=i(53931),p=i(9752);class m{static app;static mousePos={x:0,y:0};static pointerLockExitTime;static cursor;static AudioEngine;static currentScreen;static allScreens=[];static clickArea=new a.Graphics;static doPointerLock=!1;static settingsPane;static processingOsuFile=!1;constructor(e){m.app=e,m.setDropEvents(),document.body.appendChild(m.app.canvas),m.settingsPane=new g.SettingsPane,m.settingsPane.zIndex=999998,m.app.stage.addChild(m.settingsPane),document.addEventListener("keydown",(e=>{e.ctrlKey&&"KeyO"==e.code&&m.settingsPane.toggle()})),this.doResize(),window.addEventListener("resize",this.doResize),m.app.ticker.add((()=>{h.update()})),m.app.stage.eventMode="static",m.AudioEngine=new d.AudioEngine,m.app.stage.addEventListener("mousemove",(e=>{m.mousePos.x=e.clientX,m.mousePos.y=e.clientY,m.cursor&&m.cursor.updateMouse()})),document.addEventListener("pointerlockchange",this.pointerLockChanged,!1),m.switchScreen(new r.LoadScreen),u.Loader.Load(m.AudioEngine.audioContext).then((()=>{m.cursor=new c.MenuCursor(!1);let e=u.Loader.GetAudio("sample_dialog_ok"),t=u.Loader.Get("introTrianglesTrack");m.switchScreen(new l.InteractScreen(t,e))}))}static setDropEvents(){Object.defineProperty(window,"onDropEvent",{value:e=>{if(e.preventDefault(),m.processingOsuFile)alert("Another BeatMap is still processing. (Most likely transcoding a .avi file, check the console for progress) Please wait for it to process and start playing before processing another one!");else if(m.processingOsuFile=!0,e.dataTransfer.items){let t=[...e.dataTransfer.items][0];if("file"==t.kind){const e=t.getAsFile();(0,f.unzip)(e).then((e=>{let{entries:t}=e;for(const[e,i]of Object.entries(t))if(e.endsWith(".osu")){i.text().then((async e=>{let i=p.BeatmapParser.Parse(e);for(const[e,n]of Object.entries(t)){let t=await n.blob();i.files.set(e,t)}await p.BeatmapParser.LoadFiles(i);let n=i.General.audioFile;if(n){let e=URL.createObjectURL(n);m.AudioEngine.PlayMusicImmediately(e,i,(()=>{console.log("Now playing "+i.Metadata.TitleUnicode+" - "+i.Metadata.ArtistUnicode+" ("+i.Metadata.Title+" - "+i.Metadata.Artist+")")}))}m.processingOsuFile=!1,console.log(i)}));break}}))}}}}),Object.defineProperty(window,"onDragEvent",{value:e=>{e.preventDefault()}}),m.app.canvas.setAttribute("ondrop","window.onDropEvent(event);"),m.app.canvas.setAttribute("ondragover","window.onDragEvent(event);")}static lockKeyboard(){navigator.keyboard&&navigator.keyboard.lock([]).then((()=>{console.log("Locked keyboard!"),document.fullscreenElement||console.warn("Keyboard lock won't work unless the user is in fullscreen (as requested by the game, not if the user just presses F11)!")}))}static pointerLock(){try{this.doPointerLock=!0,m.app.canvas.requestPointerLock({unadjustedMovement:!0})}catch(e){console.warn("Failed to lock cursor, error:",e),this.doPointerLock=!1}}static exitPointerLock(){this.doPointerLock=!1,m.app.canvas.exitPointerLock()}static switchScreen(e){null!=this.currentScreen&&(this.currentScreen.zIndex=1,this.currentScreen.onClose().then((e=>{for(let t=0;t{e.onResize()})),m.settingsPane.resize()}pointerLockChanged(){!document.pointerLockElement&&m.doPointerLock?(a.EventSystem.isPointerLocked=!1,m.pointerLockExitTime=Date.now(),m.clickArea=new a.Graphics,m.clickArea.rect(0,0,1,1),m.clickArea.fill("rgba(0,0,0,0.1)"),m.clickArea.width=window.innerWidth,m.clickArea.height=window.innerHeight,m.clickArea.position.set(0,0),m.app.stage.addChild(m.clickArea),m.clickArea.eventMode="static",m.clickArea.cursor="pointer",m.cursor.PopOut(),m.clickArea.zIndex=9999999,m.clickArea.onclick=()=>{Date.now()-m.pointerLockExitTime<1500||(m.clickArea.removeFromParent(),m.clickArea.destroy(),m.pointerLock(),m.cursor.PopIn())}):a.EventSystem.isPointerLocked=!0}}t.Main=m},11307:function(e,t,i){i.r(t)},58689:function(e,t,i){i.r(t),t.default="in vec2 vUV;\nin vec2 vPositionOffset;\nin vec2 vPosition;\nin vec4 vColorTint;\nuniform sampler2D uTexture;\nuniform float time;\n\nvoid main() {\n float a = ((vPositionOffset.y + vPosition.y)/1200.0) - 0.1;\n vec4 color = texture(uTexture, vUV);\n if (a > 1.0) {\n a = 1.0;\n }\n gl_FragColor = (color*vColorTint)*a;\n}"},46404:function(e,t,i){i.r(t),t.default="in vec2 aPosition;\nin vec2 aUV;\nin vec2 aPositionOffset;\nin vec4 aColorTint;\n\nout vec2 vUV;\nout vec2 vPositionOffset;\nout vec2 vPosition;\nout vec4 vColorTint;\n\nuniform mat3 uProjectionMatrix;\nuniform mat3 uWorldTransformMatrix;\nuniform mat3 uTransformMatrix;\n\n\nvoid main() {\n\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n gl_Position = vec4((mvp * vec3(aPosition + aPositionOffset, 1.0)).xy, 0.0, 1.0);\n vPositionOffset = aPositionOffset;\n vUV = aUV;\n vPosition = aPosition;\n vColorTint = aColorTint;\n}"},61630:function(e,t,i){i.r(t),t.default="struct GlobalUniforms {\n uProjectionMatrix:mat3x3,\n uWorldTransformMatrix:mat3x3,\n uWorldColorAlpha: vec4,\n uResolution: vec2,\n}\n\nstruct LocalUniforms {\n uTransformMatrix:mat3x3,\n uColor:vec4,\n uRound:f32,\n}\n\n\n@group(0) @binding(0) var globalUniforms : GlobalUniforms;\n@group(1) @binding(0) var localUniforms : LocalUniforms;\n\nstruct VertexOutput {\n @builtin(position) position: vec4,\n @location(0) vUV: vec2,\n @location(1) vPositionOffset: vec2,\n @location(2) vPosition: vec2,\n @location(3) vColorTint: vec4\n};\n\n\n@vertex\nfn mainVert(\n @location(0) aPosition : vec2,\n @location(1) aUV : vec2,\n @location(2) aColorTint : vec4,\n @location(3) aPositionOffset : vec2,\n) -> VertexOutput {\n var mvp = globalUniforms.uProjectionMatrix\n * globalUniforms.uWorldTransformMatrix\n * localUniforms.uTransformMatrix;\n\n var output: VertexOutput;\n\n output.position = vec4(mvp * vec3(aPosition+aPositionOffset, 1.0), 1.0);\n output.vUV = aUV;\n output.vPosition = aPosition;\n output.vPositionOffset = aPositionOffset;\n output.vColorTint = aColorTint;\n\n return output;\n};\n\nstruct WaveUniforms {\n time:f32,\n}\n\n@group(2) @binding(1) var uTexture : texture_2d;\n@group(2) @binding(2) var uSampler : sampler;\n@group(2) @binding(3) var waveUniforms : WaveUniforms;\n\n@fragment\nfn mainFrag(\n @location(0) vUV: vec2,\n @location(1) vPositionOffset: vec2,\n @location(2) vPosition: vec2,\n @location(3) vColorTint: vec4\n) -> @location(0) vec4 {\n var a: f32 = ((vPositionOffset.y + vPosition.y)/1200.0) - 0.1;\n let color: vec4 = textureSample(uTexture, uSampler, vUV);\n if (a > 1.0){\n a = 1.0;\n }\n return (color*vColorTint)*a;\n};"},44160:function(e,t,i){i.r(t),t.default="in vec4 vColor;\nin vec2 vUV;\n\nuniform sampler2D uTexture;\nuniform float progress;\n\nvoid main() {\n vec4 color = texture2D(uTexture, vUV);\n float a = vColor.a * color.a;\n vec4 _vColor = vec4(smoothstep(0.88, 1.0, color.a))*vColor;\n vec4 outColor = (color.r < progress) ? vec4(_vColor.rgb * a, a) : vec4(0.0);\n gl_FragColor = outColor;\n}\n"},26045:function(e,t,i){i.r(t),t.default="in vec2 aPosition;\nin vec4 aColor;\nin vec2 aUV;\n\nout vec4 vColor;\nout vec2 vUV;\n\nuniform mat3 uProjectionMatrix;\nuniform mat3 uWorldTransformMatrix;\n\nuniform mat3 uTransformMatrix;\n\n\nvoid main() {\n\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n gl_Position = vec4((mvp * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\n\n vColor = aColor;\n vUV = aUV;\n}\n"},46110:function(e,t,i){i.r(t),t.default="struct GlobalUniforms {\n uProjectionMatrix:mat3x3,\n uWorldTransformMatrix:mat3x3,\n uWorldColorAlpha: vec4,\n uResolution: vec2,\n}\n\nstruct LocalUniforms {\n uTransformMatrix:mat3x3,\n uColor:vec4,\n uRound:f32,\n}\n\n\n@group(0) @binding(0) var globalUniforms : GlobalUniforms;\n@group(1) @binding(0) var localUniforms : LocalUniforms;\n\nstruct VertexOutput {\n @builtin(position) position: vec4,\n @location(0) vUV: vec2,\n @location(1) vColor: vec4,\n};\n\n\n@vertex\nfn mainVert(@location(0) aPosition : vec2, @location(1) aUV : vec2, @location(2) aColor: vec4\n) -> VertexOutput {\n var mvp = globalUniforms.uProjectionMatrix\n * globalUniforms.uWorldTransformMatrix\n * localUniforms.uTransformMatrix;\n\n var output: VertexOutput;\n\n output.position = vec4(mvp * vec3(aPosition, 1.0), 1.0);\n output.vUV = aUV;\n output.vColor = aColor;\n\n return output;\n};\n\nstruct ProgressUniform {\n progress:f32\n}\n\n@group(2) @binding(1) var uTexture : texture_2d;\n@group(2) @binding(2) var uSampler : sampler;\n@group(2) @binding(3) var uProgress : ProgressUniform;\n\n@fragment\nfn mainFrag(@location(0) vUV: vec2, @location(1) vColor: vec4) -> @location(0) vec4 {\n let color: vec4 = textureSample(uTexture, uSampler, vUV);\n let a: f32 = color.a;\n let _vColor: vec4 = smoothstep(0.88, 1.0, color.a) * vColor;\n var outColor: vec4 = vec4(0.0);\n if (color.r < uProgress.progress) {\n outColor = vec4(_vColor.rgb * a, a);\n }\n return outColor;\n};\n"}},i={};function n(e){var s=i[e];if(void 0!==s)return s.exports;var o=i[e]={id:e,loaded:!1,exports:{}};return t[e].call(o.exports,o,o.exports,n),o.loaded=!0,o.exports}n.m=t,e=[],n.O=function(t,i,s,o){if(!i){var a=1/0;for(c=0;c=o)&&Object.keys(n.O).every((function(e){return n.O[e](i[l])}))?i.splice(l--,1):(r=!1,o0&&e[c-1][2]>o;c--)e[c]=e[c-1];e[c]=[i,s,o]},n.d=function(e,t){for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.hmd=function(e){return(e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},function(){var e={179:0};n.O.j=function(t){return 0===e[t]};var t=function(t,i){var s,o,a=i[0],r=i[1],l=i[2],u=0;if(a.some((function(t){return 0!==e[t]}))){for(s in r)n.o(r,s)&&(n.m[s]=r[s]);if(l)var c=l(n)}for(t&&t(i);u 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","import {BeatmapData} from \"../Util/Beatmap/Data/BeatmapData\";\nimport {Main} from \"../main\";\nimport {EventTypes} from \"../Util/Beatmap/Data/Sections/Events/EventTypes\";\nimport {EventVideo} from \"../Util/Beatmap/Data/Sections/Events/EventVideo\";\n\nexport class Audio {\n public audio!: AudioBuffer;\n public source?: AudioBufferSourceNode;\n public mediaSource?: MediaElementAudioSourceNode;\n public mediaAudioElement!: HTMLAudioElement;\n public id!: number;\n public get isPaused() {\n return this._useMediaSource ? this.mediaAudioElement.paused : false;\n }\n public get isPlaying() {\n return this._useMediaSource ? !this.mediaAudioElement.paused : true;\n }\n public nodes: AudioNode[] = [];\n public tempArrayMain = new Float32Array(256);\n public tempArrayL = new Float32Array(64);\n public tempArrayR = new Float32Array(64);\n public LeftChannel: number = 0;\n public RightChannel: number = 0;\n public FrequencyAmplitudes = new Float32Array(256);\n protected _connectedToContext = false;\n protected _useMediaSource = false;\n protected _onEndCallback?: () => void;\n public timeStarted = 0; // only for silent audio when real music is paused\n protected paused = false; // used to check if music was paused outside of Audio class (i.e. pressing stop media button on the keyboard)\n public beatmap!: BeatmapData;\n\n public GetMaximumAudioLevel() {\n return Math.max(this.LeftChannel, this.RightChannel);\n }\n\n public GetAverageAudioLevel() {\n return (this.LeftChannel + this.RightChannel) / 2;\n }\n\n public Create(audioContext: AudioContext, useMediaSource?: boolean) {\n this._useMediaSource = useMediaSource ? useMediaSource : false;\n if (!useMediaSource) {\n this.source = audioContext.createBufferSource();\n this.source.buffer = this.audio;\n }\n else {\n if (!this.mediaAudioElement) {\n throw new Error(\"HTML Audio Element was not initialized!\")\n }\n this.mediaSource = audioContext.createMediaElementSource(this.mediaAudioElement);\n this.mediaAudioElement.onpause = () => {\n if (!this.paused && !this.mediaAudioElement.ended) { // check if music was paused outside of Audio class\n this.Play();\n }\n }\n }\n }\n\n public AddAudioNode(node: AudioNode) {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n this.nodes.push(node);\n }\n\n public GetNode(type: new (...args: any[]) => T): T[] | null {\n let nodes = this.nodes.filter(node => node instanceof type) as T[];\n if (nodes.length > 0) {\n return nodes;\n } else {\n return null;\n }\n }\n\n public ConnectToContext(audioContext: AudioContext, howToConnectFunction?: (nodes: AudioNode[], source: AudioBufferSourceNode | MediaElementAudioSourceNode) => void) {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (this._connectedToContext) {\n return;\n }\n this._connectedToContext = true;\n if (this.nodes.length > 0) {\n if (howToConnectFunction) {\n howToConnectFunction(this.nodes, (!this._useMediaSource ? this.source : this.mediaSource)!);\n } else {\n this.nodes.forEach((node, index) => {\n this.source!.connect(node);\n if (!(node instanceof AnalyserNode)) {\n node.connect(audioContext.destination);\n }\n });\n }\n } else {\n if (!this._useMediaSource) {\n this.source!.connect(audioContext.destination);\n }\n else {\n this.mediaSource!.connect(audioContext.destination);\n }\n }\n }\n\n public Play() {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n this.paused = false;\n if (!this._useMediaSource) {\n this.source!.start();\n }\n else {\n this.mediaAudioElement!.play();\n let backgroundVideo = this.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n if (backgroundVideo.texture.source.resource.startPromise) {\n backgroundVideo.texture.source.resource.startPromise.then(() => {\n let video = backgroundVideo.texture!.source.resource as HTMLVideoElement;\n video.play();\n });\n }\n }\n }\n }\n }\n\n public Pause() {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n if (!this._useMediaSource) {\n throw new Error(\"Pause is not supported on AudioSourceBuffer!\");\n }\n this.paused = true;\n this.mediaAudioElement!.pause();\n let backgroundVideo = this.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n if (backgroundVideo.texture.source.resource.startPromise) {\n backgroundVideo.texture.source.resource.startPromise.then(() => {\n let video = backgroundVideo.texture!.source.resource as HTMLVideoElement;\n video.pause();\n });\n }\n }\n }\n }\n\n public Stop() {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n this.paused = true;\n if (!this._useMediaSource) {\n this.source!.stop();\n }\n else {\n this.mediaAudioElement!.pause();\n if (this._onEndCallback) {\n this._onEndCallback();\n }\n let backgroundVideo = this.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n if (backgroundVideo.texture.source.resource.startPromise) {\n backgroundVideo.texture.source.resource.startPromise.then(() => {\n let video = backgroundVideo.texture!.source.resource as HTMLVideoElement;\n video.pause();\n });\n }\n }\n }\n }\n }\n\n public SetTime(timeMS: number) {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n if (!this._useMediaSource) {\n throw new Error(\"SetTime is not supported on AudioSourceBuffer!\");\n }\n this.mediaAudioElement.currentTime = timeMS/1000;\n let backgroundVideo = this.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n if (backgroundVideo.texture.source.resource.startPromise) {\n backgroundVideo.texture.source.resource.startPromise.then(() => {\n let video = backgroundVideo.texture!.source.resource as HTMLVideoElement;\n let time = timeMS/1000;\n time += backgroundVideo.startTime;\n if (time < 0) {\n video.currentTime = 0;\n video.pause();\n backgroundVideo.texture!.source.resource.startPromise = new Promise((resolve) => {\n setTimeout(() => {\n video.play();\n }, Math.abs(time));\n });\n } else {\n video.currentTime = time;\n }\n\n });\n }\n }\n }\n }\n\n public GetDuration() {\n return (!this._useMediaSource ? this.audio.duration : this.mediaAudioElement.duration * 1000)\n }\n\n public GetCurrentTime() {\n return this._useMediaSource ? this.mediaAudioElement.currentTime * 1000 : (this.timeStarted != 0 ? Date.now() - this.timeStarted : 0);\n }\n\n public RegisterEndCallBack(callback: () => void) {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n this._onEndCallback = callback;\n if (!this._useMediaSource) {\n this.source!.onended = () => {\n if (!this.isPaused) {\n this.paused = true;\n callback();\n }\n }\n }\n else {\n this.mediaAudioElement.onended = () => {\n this.paused = true;\n callback();\n }\n }\n }\n\n}\n\nexport class MapAudio extends Audio {\n public fadingOut: boolean = false;\n // @ts-ignore\n public fadeOutTimeout!: Timeout\n public playingCallback?: () => void;\n\n public FadeOut() {\n if (!(!this._useMediaSource ? this.source : this.mediaSource)) {\n throw new Error(\"Source not created yet!\");\n }\n if (!this._connectedToContext) {\n throw new Error(\"Not connected to audio context yet!\");\n }\n if (!this._useMediaSource) {\n throw new Error(\"FadeOut is not supported on AudioSourceBuffer!\");\n }\n if (this.fadingOut) {\n return;\n }\n this.fadingOut = true;\n clearTimeout(this.fadeOutTimeout);\n let gainNodes = this.GetNode(GainNode);\n if (gainNodes == null) {\n throw new Error(\"Gain Node doesn't exist on Audio Object!\");\n }\n let gain = gainNodes[0];\n gain.gain.linearRampToValueAtTime(0, Main.AudioEngine.audioContext.currentTime + 1)\n setTimeout(() => {\n this.Stop();\n }, 1000);\n }\n}\n","import {PlayingAudios} from \"./PlayingAudios\";\nimport {Audio, MapAudio} from \"./Audio\";\nimport {BeatmapData} from \"../Util/Beatmap/Data/BeatmapData\";\nimport {Main} from \"../main\";\nimport {UnInheritedTimingPoint} from \"../Util/Beatmap/Data/Sections/TimingPoints/UnInheritedTimingPoint\";\nimport {Effect} from \"../Util/Beatmap/Data/Sections/TimingPoints/Effect\";\n\nexport class AudioEngine {\n public readonly audioContext: AudioContext;\n private readonly _playingAudios: PlayingAudios;\n private _musicQueue: MapAudio[] = [];\n private _audioIdTicker: number = 0;\n private _changeCallbacks: ((mapAudio: MapAudio) => void)[] = [];\n private silentMusic = this.createSilentMusic();\n public useSilentMusic = true;\n\n public constructor() {\n this.audioContext = new AudioContext();\n this._playingAudios = new PlayingAudios();\n Main.app.ticker.add(() => {\n this.update();\n });\n }\n\n public UpdateMusicQueue() {\n if (this._musicQueue[0]) {\n if (!this._musicQueue[0].fadingOut && this._musicQueue[0].GetCurrentTime() == 0) {\n this._play(this._musicQueue[0]);\n this._changeCallbacks.forEach((cb) => cb(this._musicQueue[0]));\n }\n if (this._musicQueue[0].fadingOut && this._musicQueue[1]) {\n if (this._musicQueue[1]) {\n this._play(this._musicQueue[1]);\n this._changeCallbacks.forEach((cb) => cb(this._musicQueue[1]));\n }\n }\n }\n if (!(this._musicQueue.length >= 1)) {\n this.silentMusic = this.createSilentMusic();\n this.useSilentMusic = true;\n }\n else {\n this.useSilentMusic = false;\n }\n }\n\n public createSilentMusic() {\n let mapAudio = new MapAudio();\n mapAudio.timeStarted = Date.now();\n mapAudio.beatmap = new BeatmapData();\n let timingPoint = new UnInheritedTimingPoint();\n timingPoint.time = 0;\n timingPoint.beatLength = 1000;\n timingPoint.effects = Effect.None;\n mapAudio.beatmap.TimingPoints.TimingPoints.push(timingPoint);\n return mapAudio;\n }\n\n public addMusicChangeEventListener(cb: (() => void) | ((mapAudio: MapAudio) => void)) {\n this._changeCallbacks.push(cb);\n }\n\n public removeMusicChangeEventListener(cb: (() => void) | ((mapAudio: MapAudio) => void)) {\n this._changeCallbacks = this._changeCallbacks.filter(callback => callback != cb);\n }\n\n public GetCurrentPlayingMusic(): MapAudio {\n return this.useSilentMusic ? this.silentMusic : this._musicQueue[0];\n }\n\n public GetCurrentPlayingMusicNoSilent(): MapAudio {\n return this._musicQueue[0];\n }\n\n public PlayEffect(audio: AudioBuffer, pitch?: number) {\n let audioObj = new Audio();\n audioObj.audio = audio;\n audioObj.id = this._audioIdTicker;\n this._play(audioObj, pitch);\n this._audioIdTicker++;\n }\n\n public AddToMusicQueue(mapAudio: string, beatMapData: BeatmapData, musicPlayingCallback?: () => void) {\n let mapAudioObj = new MapAudio();\n mapAudioObj.mediaAudioElement = document.createElement(\"audio\");\n mapAudioObj.mediaAudioElement.src = mapAudio;\n mapAudioObj.beatmap = beatMapData;\n mapAudioObj.id = this._audioIdTicker;\n if (musicPlayingCallback) {\n mapAudioObj.playingCallback = musicPlayingCallback;\n }\n this._musicQueue.push(mapAudioObj);\n this._audioIdTicker++;\n this.UpdateMusicQueue();\n return mapAudioObj.id;\n }\n\n public PlayMusicImmediately(mapAudio: string, beatMapData: BeatmapData, musicPlayingCallback?: () => void) {\n let currentPlaying = this.GetCurrentPlayingMusicNoSilent();\n this._musicQueue = [];\n if (currentPlaying) {\n currentPlaying.FadeOut();\n }\n this.AddToMusicQueue(mapAudio, beatMapData, musicPlayingCallback);\n }\n\n public update() {\n let currentPlaying = this.GetCurrentPlayingMusic();\n let currentPlayingNoSilent = this.GetCurrentPlayingMusicNoSilent();\n if (!currentPlayingNoSilent)\n return;\n if (currentPlayingNoSilent.isPaused) {\n this.useSilentMusic = true;\n return;\n }\n else if (this.useSilentMusic) {\n this.useSilentMusic = false;\n currentPlaying = this.GetCurrentPlayingMusic();\n }\n if (!this.useSilentMusic) {\n if (!currentPlaying.fadingOut) {\n if (currentPlaying.GetDuration() - currentPlaying.GetCurrentTime() <= 1000){\n currentPlaying.FadeOut();\n }\n }\n let analyzerMain = currentPlaying.GetNode(AnalyserNode)![0];\n let analyzerL = currentPlaying.GetNode(AnalyserNode)![1];\n let analyzerR = currentPlaying.GetNode(AnalyserNode)![2];\n\n analyzerMain.getFloatFrequencyData(currentPlaying.tempArrayMain);\n for (let i = 0; i < currentPlaying.FrequencyAmplitudes.length; i++) {\n currentPlaying.tempArrayMain[i] += 140;\n currentPlaying.tempArrayMain[i] /= 340;\n if (i < 3) {\n currentPlaying.tempArrayMain[i] *= (12 * currentPlaying.tempArrayMain[i]);\n } else if (i < 6) {\n currentPlaying.tempArrayMain[i] *= (9 * currentPlaying.tempArrayMain[i]);\n } else if (i < 100) {\n currentPlaying.tempArrayMain[i] *= (6 * currentPlaying.tempArrayMain[i]);\n }\n currentPlaying.tempArrayMain[i] /= 2;\n if (currentPlaying.tempArrayMain[i] == Infinity || currentPlaying.tempArrayMain[i] == -Infinity) {\n currentPlaying.FrequencyAmplitudes[i] = 0;\n }\n else {\n currentPlaying.FrequencyAmplitudes[i] = currentPlaying.tempArrayMain[i];\n }\n }\n\n analyzerL.getFloatTimeDomainData(currentPlaying.tempArrayL);\n analyzerR.getFloatTimeDomainData(currentPlaying.tempArrayR);\n let avgL = 0;\n let avgR = 0;\n currentPlaying.tempArrayL.forEach((value) => {\n avgL += (value + 1)/2;\n });\n currentPlaying.tempArrayR.forEach((value) => {\n avgR += (value + 1)/2;\n });\n avgL /= currentPlaying.tempArrayL.length;\n avgR /= currentPlaying.tempArrayR.length;\n currentPlaying.LeftChannel = avgL;\n currentPlaying.RightChannel = avgR;\n }\n }\n\n private _play(audio: Audio | MapAudio, pitch?: number) {\n // check if audio is type of MapAudio\n if (audio instanceof MapAudio) {\n audio.Create(this.audioContext, true);\n let gain = this.audioContext.createGain();\n gain.gain.value = 0;\n let analyzer = this.audioContext.createAnalyser();\n analyzer.fftSize = 512;\n analyzer.smoothingTimeConstant = 0;\n let splitter = this.audioContext.createChannelSplitter(2);\n let analyzerL = this.audioContext.createAnalyser();\n analyzerL.smoothingTimeConstant = 0;\n analyzerL.fftSize = 128;\n let analyzerR = this.audioContext.createAnalyser();\n analyzerR.smoothingTimeConstant = 0;\n analyzerR.fftSize = 128;\n audio.AddAudioNode(gain);\n audio.AddAudioNode(analyzer);\n audio.AddAudioNode(analyzerL);\n audio.AddAudioNode(analyzerR);\n audio.ConnectToContext(this.audioContext, (nodes, source) => {\n source.connect(gain);\n gain.connect(this.audioContext.destination);\n source.connect(analyzer);\n source.connect(splitter);\n splitter.connect(analyzerL, 0);\n splitter.connect(analyzerR, 1);\n });\n audio.Play();\n this._playingAudios.audios.push(audio);\n if (audio.playingCallback) {\n audio.playingCallback();\n }\n gain.gain.linearRampToValueAtTime(1, this.audioContext.currentTime + 0.5);\n\n } else {\n audio.Create(this.audioContext, false);\n audio.ConnectToContext(this.audioContext);\n if (pitch) {\n if (audio.source) {\n audio.source.playbackRate.value = pitch;\n }\n }\n audio.Play();\n this._playingAudios.audios.push(audio);\n }\n\n\n audio.RegisterEndCallBack(() => {\n if (audio instanceof MapAudio) {\n if (this._musicQueue[0] == audio) {\n this._musicQueue.splice(0, 1);\n }\n this.UpdateMusicQueue();\n }\n this._playingAudios.audios.forEach((audioInArr, index) => {\n if (audioInArr === audio) {\n this._playingAudios.audios.splice(index, 1);\n return;\n }\n });\n });\n }\n\n}\n","import {Audio, MapAudio} from \"./Audio\";\n\nexport class PlayingAudios {\n public audios: (Audio | MapAudio)[] = [];\n}\n","import {Main} from \"../../main\";\nimport {MapAudio} from \"../../Audio/Audio\";\nimport * as PIXI from \"pixi.js\";\nimport {MathUtil} from \"../../Util/MathUtil\";\nimport {Effect} from \"../../Util/Beatmap/Data/Sections/TimingPoints/Effect\";\nimport {UnInheritedTimingPoint} from \"../../Util/Beatmap/Data/Sections/TimingPoints/UnInheritedTimingPoint\";\n\nexport class LogoVisualizer extends PIXI.Container {\n\n public static readonly size = 900;\n public frequencyAmplitudes: Float32Array = new Float32Array(256);\n protected audio!: MapAudio;\n protected temporalAmplitudes: Float32Array = new Float32Array(256);\n protected graphics: PIXI.Graphics = new PIXI.Graphics();\n // The number of bars to jump each update iteration.\n private readonly index_change = 5;\n // The maximum length of each bar in the visualiser. Will be reduced when kiai is not activated.\n private readonly bar_length = 600;\n // The number of bars in one rotation of the visualiser.\n private bars_per_visualiser = 200;\n // How many times we should stretch around the circumference (overlapping overselves).\n private readonly visualiser_rounds = 5;\n // How much should each bar go down each millisecond (based on a full bar).\n private readonly decay_per_millisecond = 0.0024;\n // Number of milliseconds between each amplitude update.\n private readonly time_between_updates = 50;\n // The minimum amplitude to show a bar.\n private readonly amplitude_dead_zone = 1 / this.bar_length;\n private indexOffset = 0;\n private firstDraw = true;\n\n public set alpha(number: number) {\n super.alpha = number * 0.2;\n }\n public get alpha() {\n return super.alpha * 5;\n }\n\n public constructor() {\n super();\n this.alpha = 1;\n }\n\n public start() {\n this.graphics.blendMode = \"add\";\n this.addChild(this.graphics);\n this.graphics.eventMode = \"none\";\n this.eventMode = \"none\";\n setInterval(() => {\n this.updateAmplitudes()\n }, this.time_between_updates);\n\n }\n\n public draw(ticker: PIXI.Ticker) {\n if (this.firstDraw) {\n for (let i = 0; i < this.frequencyAmplitudes.length; i++) {\n this.frequencyAmplitudes[i] = 0;\n }\n }\n this.graphics.clear();\n let decayFactor = ticker.deltaMS * this.decay_per_millisecond;\n for (let i = 0; i < this.bars_per_visualiser; i++) {\n //3% of extra bar length to make it a little faster when bar is almost at it's minimum\n this.frequencyAmplitudes[i] -= decayFactor * (this.frequencyAmplitudes[i] + 0.03);\n if (this.frequencyAmplitudes[i] < 0) {\n this.frequencyAmplitudes[i] = 0;\n }\n }\n\n for (let j = 0; j < this.visualiser_rounds; j++) {\n for (let i = 0; i < this.bars_per_visualiser; i++) {\n if (this.frequencyAmplitudes[i] < this.amplitude_dead_zone) {\n continue;\n }\n\n let rotation = MathUtil.DegreesToRadians(i / this.bars_per_visualiser * 360 + j * 360 / this.visualiser_rounds);\n let rotationCos = Math.cos(rotation);\n let rotationSin = Math.sin(rotation);\n // taking the cos and sin to the 0..1 range\n let barPosition = {\n x: (rotationCos / 2 + 0.5) * LogoVisualizer.size,\n y: (rotationSin / 2 + 0.5) * LogoVisualizer.size\n };\n\n let barSize = {\n x: LogoVisualizer.size * Math.sqrt(2 * (1 - Math.cos(MathUtil.DegreesToRadians(360 / this.bars_per_visualiser)))) / 2,\n y: this.bar_length * this.frequencyAmplitudes[i]\n };\n // The distance between the bottom side of the bar and the top side.\n let amplitudeOffset = {x: rotationCos * barSize.y, y: rotationSin * barSize.y};\n\n this.graphics.moveTo(barPosition.x, barPosition.y);\n this.graphics.lineTo(barPosition.x + amplitudeOffset.x, barPosition.y + amplitudeOffset.y);\n this.graphics.stroke({color: \"rgb(255, 255, 255)\", width: 14});\n }\n }\n this.firstDraw = false;\n }\n\n private updateAmplitudes() {\n this.audio = Main.AudioEngine.GetCurrentPlayingMusic();\n for (let i = 0; i < this.audio.FrequencyAmplitudes.length; i++) {\n this.temporalAmplitudes[i] = this.audio.FrequencyAmplitudes[i];\n }\n let audioTime = this.audio.GetCurrentTime();\n let timingPoint = this.audio.beatmap.TimingPoints.GetCurrentTimingPoints(audioTime)[0];\n for (let i = 0; i < this.bars_per_visualiser; i++) {\n let targetAmplitude = (this.temporalAmplitudes[(i + this.indexOffset) % this.bars_per_visualiser]) *\n (timingPoint.effects == Effect.KiaiTime ? 1 : 0.5);\n if (targetAmplitude > this.frequencyAmplitudes[i]) {\n this.frequencyAmplitudes[i] = targetAmplitude;\n }\n }\n this.indexOffset = (this.indexOffset + this.index_change) % this.bars_per_visualiser;\n }\n}\n","import {LogoVisualizer} from \"../LogoVisualizer\";\nimport * as PIXI from \"pixi.js\";\n\nexport class MenuLogoVisualizer extends LogoVisualizer {\n\n\n public draw(ticker: PIXI.Ticker) {\n super.draw(ticker);\n\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\n\nexport class LoadAnim extends PIXI.Container {\n private readonly bg: PIXI.Graphics;\n private readonly arc: PIXI.Graphics;\n private readonly arcContainer: PIXI.Container;\n private readonly animInterval: NodeJS.Timeout;\n private readonly container: PIXI.Container;\n private readonly bgContainer: PIXI.Container;\n private bgRotation: number = 0;\n\n public constructor(bgColor: string, arcColor: string) {\n super();\n this.pivot.set(0.5, 0.5);\n this.container = new PIXI.Container();\n this.container.alpha = 0;\n this.rotation = Math.PI * 2.5;\n this.bgContainer = new PIXI.Container();\n this.bg = new PIXI.Graphics();\n this.bg.roundRect(-50, -50, 100, 100, 25);\n this.bg.fill(bgColor);\n this.arcContainer = new PIXI.Container();\n this.arc = new PIXI.Graphics();\n this.arc.arc(0, 0, 27, Math.PI + .26, 2.92 * Math.PI);\n this.arc.stroke({\n width: 8,\n color: arcColor,\n cap: \"round\"\n });\n this.arc.scale.set(-1, 1);\n this.container.scale.set(0.5, 0.5);\n this.bgContainer.addChild(this.bg);\n this.arcContainer.addChild(this.arc);\n this.bgContainer.addChild(this.arcContainer);\n this.container.addChild(this.bgContainer);\n this.addChild(this.container);\n Ease.getEase(this.container).ScaleTo(1, 400, TWEEN.Easing.Quadratic.InOut)\n .FadeIn(400, TWEEN.Easing.Quadratic.InOut)\n this.doAnims();\n\n this.animInterval = setInterval(() => {\n this.doAnims();\n }, 800);\n }\n\n public doAnims() {\n this.bgRotation += 90;\n Ease.getEase(this.bgContainer).createTween({value: this.bgContainer.angle},\n {value: this.bgRotation}, true, \"angle\", 600, TWEEN.Easing.Quadratic.InOut);\n }\n\n public getWidth() {\n return 100 * this.scale.x;\n }\n\n public getHeight() {\n return 100 * this.scale.y;\n }\n\n public draw(deltaTime: PIXI.Ticker) {\n this.arcContainer.angle += (3 * deltaTime.deltaTime);\n }\n\n public destroy(_options?: PIXI.DestroyOptions | boolean) {\n Ease.getEase(this.container).FadeOut(400, TWEEN.Easing.Quadratic.InOut)\n .ScaleTo(0.5, 400, TWEEN.Easing.Quadratic.InOut);\n setTimeout(() => {\n clearInterval(this.animInterval);\n super.destroy(_options);\n }, 400);\n }\n\n}\n","import * as PIXI from \"pixi.js\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../../../Util/TweenWrapper/Ease\";\nimport {OsuLogo} from \"../OsuLogo\";\nimport {Screen} from \"../../../../Screens/Screen\";\nimport {LogoTrackingContainer} from \"./LogoTrackingContainer\";\n\nexport class ButtonSystem extends PIXI.Container {\n\n private menuBG = new PIXI.Graphics();\n private isOpened = false;\n private logo: OsuLogo;\n private state = ButtonSystemState.Initial;\n private logoTrackingContainer = new LogoTrackingContainer();\n private readonly menuHeight = 150;\n\n private get State() {\n return this.state;\n }\n\n private set State(state: ButtonSystemState) {\n if (this.state == state) return;\n\n const lastState = this.state;\n this.state = state;\n\n this.updateLogoState(lastState);\n\n console.log(`${this.constructor.name}'s state changed from ${lastState} to ${state}`)\n }\n\n private updateLogoState(lastState = ButtonSystemState.Initial) {\n switch (this.state) {\n case ButtonSystemState.Exit:\n case ButtonSystemState.Initial:\n this.Close();\n break;\n case ButtonSystemState.TopLevel:\n case ButtonSystemState.Play:\n switch (lastState) {\n case ButtonSystemState.TopLevel: // coming from toplevel to play\n break;\n\n case ButtonSystemState.Initial:\n this.Open();\n Ease.getEase(this.logo).ClearEasings().ScaleTo(Screen.getScaleBasedOffScreenSize() * 0.5, 200, TWEEN.Easing.Linear.In);\n break;\n\n default:\n this.Open();\n Ease.getEase(this.logo).ClearEasings().ScaleTo(Screen.getScaleBasedOffScreenSize() * 0.5, 200, TWEEN.Easing.Quintic.Out);\n break;\n }\n break;\n }\n }\n\n public constructor(logo: OsuLogo) {\n super();\n this.logo = logo;\n this.drawMenuBG();\n this.scale.y = 0;\n this.alpha = 0;\n this.addChild(this.menuBG);\n this.addChild(this.logoTrackingContainer);\n this.logo.Action = () => {return this.onOsuLogo();};\n }\n\n private drawMenuBG() {\n this.menuBG.rect(0, Screen.getScaleBasedOffScreenSize() * -(this.menuHeight/2), 1, Screen.getScaleBasedOffScreenSize() * this.menuHeight);\n this.menuBG.fill({color: \"rgb(50,50,50)\"});\n }\n\n private onOsuLogo(): boolean {\n switch (this.state) {\n default:\n return false;\n\n case ButtonSystemState.Initial:\n this.State = ButtonSystemState.TopLevel;\n return true;\n\n case ButtonSystemState.TopLevel:\n\n return false;\n\n case ButtonSystemState.Play:\n\n return false;\n\n case ButtonSystemState.Edit:\n\n return false;\n }\n }\n\n private Open() {\n setTimeout(() => {\n this.isOpened = true;\n Ease.getEase(this).ScaleTo(1, 400, TWEEN.Easing.Quintic.Out)\n .FadeIn(400, TWEEN.Easing.Quintic.Out);\n }, 150);\n }\n\n private Close() {\n this.isOpened = false;\n Ease.getEase(this).ClearEasings().ScaleTo({x: 1, y: 0}, 300, TWEEN.Easing.Sinusoidal.In)\n .FadeOut(300, TWEEN.Easing.Sinusoidal.In);\n }\n\n public isOpen() {\n return this.isOpened;\n }\n\n public onResize() {\n this.menuBG.clear();\n this.drawMenuBG();\n this.position.set(0, window.innerHeight/2);\n this.menuBG.width = window.innerWidth;\n }\n}\n\nenum ButtonSystemState {\n Exit = \"Exit\",\n Initial = \"Initial\",\n TopLevel = \"TopLevel\",\n Play = \"Play\",\n Edit = \"Edit\",\n EnteringMode = \"EnteringMode\",\n}\n","import * as PIXI from \"pixi.js\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {OsuLogo} from \"../OsuLogo\";\n\nexport class LogoTrackingContainer extends PIXI.Container {\n protected Logo: OsuLogo | null = null;\n\n private easing!: (amount: number) => number;\n private startPosition: {x: number, y: number} | null = null;\n private startTime: number | null = null;\n private duration!: number;\n\n private readonly visual_box_size = 72;\n\n public StartTracking(logo: OsuLogo, duration: number = 0, easing: (amount: number) => number = TWEEN.Easing.Linear.None) {\n if (logo.IsTracking && this.Logo == null)\n throw new Error(\"Cannot track an instance of OsuLogo to multiple LogoTrackingContainers\");\n\n if (this.Logo != logo && this.Logo != null)\n {\n // If we're replacing the logo to be tracked, the old one no longer has a tracking container\n this.Logo.IsTracking = false;\n }\n\n this.Logo = logo;\n this.Logo.IsTracking = true;\n\n this.duration = duration;\n this.easing = easing;\n\n this.startTime = null;\n this.startPosition = null;\n }\n\n public StopTracking() {\n if (this.Logo != null)\n {\n this.Logo.IsTracking = false;\n this.Logo = null;\n }\n }\n\n protected ComputeLogoTrackingPosition() {\n let pos = this.Logo!.position;\n pos.x = window.innerWidth/3;\n return pos;\n }\n\n public Update() {\n if (this.Logo == null)\n return;\n }\n\n}\n","import * as PIXI from \"pixi.js\";\nimport {Triangles} from \"./Triangles\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../../Util/TweenWrapper/Ease\";\nimport {Main} from \"../../../main\";\nimport {Loader} from \"../../../Loader\";\nimport {ButtonSystem} from \"./Menu/ButtonSystem\";\nimport {MenuLogoVisualizer} from \"../../AudioVisualizers/impl/MenuLogoVisualizer\";\nimport {LogoVisualizer} from \"../../AudioVisualizers/LogoVisualizer\";\nimport {Effect} from \"../../../Util/Beatmap/Data/Sections/TimingPoints/Effect\";\nimport {UnInheritedTimingPoint} from \"../../../Util/Beatmap/Data/Sections/TimingPoints/UnInheritedTimingPoint\";\nimport {MathUtil} from \"../../../Util/MathUtil\";\n\nexport class OsuLogo extends PIXI.Container {\n\n private readonly outline: PIXI.Sprite;\n private readonly visualizer: MenuLogoVisualizer = new MenuLogoVisualizer();\n private readonly triangles: Triangles = new Triangles();\n private readonly flash;\n private readonly logoContainer = new PIXI.Container;\n private readonly logoBounceContainer = new PIXI.Container();\n private readonly logoBeatContainer = new PIXI.Container();\n private readonly logoAmplitudeContainer = new PIXI.Container();\n private readonly logoHoverContainer = new PIXI.Container();\n private readonly rippleContainer = new PIXI.Container();\n private readonly ripple;\n private readonly defaultVisualizerAlpha = 0.5;\n private readonly early_activation = 60;\n private timeElapsedSinceLastBeat = 0;\n private timeUntilNextBeat = 0;\n private lastTimeElapasedSinceLastBeat = 0;\n\n private selectSample = Loader.GetAudio(\"mainMenu.osuLogo.select\");\n private backToLogoSample = Loader.GetAudio(\"mainMenu.osuLogo.backToLogo\");\n\n private isMouseDown = false;\n private mouseDownPosition = {x: 0, y: 0};\n\n public Action: (() => boolean) | null = null;\n\n public IsTracking: boolean = false;\n\n public get SizeForFlow() {\n return this.outline.width * this.logoBounceContainer.scale.x * this.logoHoverContainer.scale.x;\n }\n\n\n public constructor() {\n super();\n this.visualizer.start();\n\n\n this.outline = PIXI.Sprite.from(\"mainMenu.logoOutline\");\n this.outline.anchor.set(0.5, 0.5);\n //approximation of size in actual osu!lazer\n let scale = 0.7;\n this.visualizer.scale.set(scale);\n this.visualizer.pivot.set(LogoVisualizer.size/2, LogoVisualizer.size/2);\n this.visualizer.alpha = this.defaultVisualizerAlpha;\n\n let mask = new PIXI.Graphics();\n mask.circle(0,0,450);\n mask.fill({color:\"white\"});\n mask.scale = scale;\n\n\n this.flash = PIXI.Sprite.from(\"mainMenu.logoMask\");\n this.flash.anchor.set(0.5, 0.5);\n this.flash.scale = scale;\n this.flash.blendMode = \"add\";\n this.flash.alpha = 0;\n\n this.triangles.flash.anchor.set(0.5, 0.5);\n this.triangles.flash.scale = scale;\n\n this.outline.scale.set(scale);\n this.triangles.scale.set(scale);\n this.triangles.position.set(-(this.outline.width / 2), -(this.outline.height / 2));\n this.triangles.mask = mask;\n\n this.ripple = PIXI.Sprite.from(\"mainMenu.logoMask\");\n this.ripple.anchor.set(0.5, 0.5);\n this.ripple.scale = scale;\n this.ripple.alpha = 0;\n this.ripple.blendMode = \"add\";\n\n this.rippleContainer.addChild(this.ripple);\n this.logoContainer.addChild(this.visualizer);\n this.logoContainer.addChild(this.triangles);\n this.logoContainer.addChild(this.triangles.flash);\n this.logoContainer.addChild(mask);\n this.logoContainer.addChild(this.flash);\n this.logoContainer.addChild(this.outline);\n this.logoContainer.hitArea = new PIXI.Circle(0, 0, 480 * scale);\n this.logoContainer.eventMode = \"static\";\n\n this.logoContainer.onmouseenter = this._onmouseenter;\n this.logoContainer.onmouseleave = this._onmouseleave;\n this.logoContainer.onmousedown = this._onmousedown;\n this.logoContainer.onclick = this._onclick;\n\n this.logoBeatContainer.addChild(this.logoContainer);\n this.logoAmplitudeContainer.addChild(this.logoBeatContainer);\n this.logoBounceContainer.addChild(this.rippleContainer);\n this.logoBounceContainer.addChild(this.logoAmplitudeContainer);\n this.logoHoverContainer.addChild(this.logoBounceContainer);\n this.addChild(this.logoHoverContainer)\n\n // register event listeners\n Main.app.stage.addEventListener(\"mouseup\", (e) => {\n this._onmouseup(e);\n });\n\n }\n\n\n public _onmouseenter = (e: PIXI.FederatedMouseEvent) => {\n Ease.getEase(this.logoHoverContainer).ScaleTo(1.1, 500, TWEEN.Easing.Elastic.Out);\n }\n\n public _onmouseleave = (e: PIXI.FederatedMouseEvent) => {\n Ease.getEase(this.logoHoverContainer).ScaleTo(1, 500, TWEEN.Easing.Elastic.Out);\n }\n\n public _onmousedown = (e: PIXI.FederatedMouseEvent) => {\n this.isMouseDown = true;\n Ease.getEase(this.logoBounceContainer).ClearEasings().ScaleTo(0.9, 1000, TWEEN.Easing.Sinusoidal.Out);\n this.mouseDownPosition = {x: Main.mousePos.x, y: Main.mousePos.y};\n }\n\n public _onclick = (e: PIXI.FederatedMouseEvent) => {\n this.flash.alpha = 0.4;\n Ease.getEase(this.flash).ClearEasings()\n .FadeOut(1500, TWEEN.Easing.Exponential.Out);\n if (this.Action) {\n if(this.Action()){\n Main.AudioEngine.PlayEffect(Loader.GetAudio(\"mainMenu.osuLogo.select\"));\n }\n }\n }\n\n public _onmouseup = (e: PIXI.FederatedMouseEvent) => {\n this.isMouseDown = false;\n Ease.getEase(this.logoBounceContainer).ClearEasings().ScaleTo(1, 500, TWEEN.Easing.Elastic.Out)\n .TransformTo({x: 0, y: 0}, 800, TWEEN.Easing.Elastic.Out);\n }\n\n public draw(ticker: PIXI.Ticker) {\n this.visualizer.draw(ticker);\n this.triangles.draw(ticker);\n //this.timeElapsedSinceLastBeat += ticker.deltaMS;\n let audio = Main.AudioEngine.GetCurrentPlayingMusic();\n let audioTime = audio.GetCurrentTime();\n let timingPoint = audio.beatmap.TimingPoints.GetCurrentUninheritedTimingPoint(audioTime);\n this.timeUntilNextBeat = (timingPoint.time - audioTime) % timingPoint.beatLength;\n if (this.timeUntilNextBeat <= 0) {\n this.timeUntilNextBeat += timingPoint.beatLength;\n }\n this.timeElapsedSinceLastBeat = timingPoint.beatLength - this.timeUntilNextBeat;\n if (!Main.AudioEngine.useSilentMusic) {\n let maxAmplitude = audio.GetMaximumAudioLevel();\n this.logoAmplitudeContainer.scale.set(MathUtil.Damp(this.logoAmplitudeContainer.scale.x,\n 1 - Math.max(0, maxAmplitude - 0.4) * 0.04, 0.9, ticker.deltaMS))\n this.triangles.Velocity = MathUtil.Damp(this.triangles.Velocity,\n 0.5 * (timingPoint.effects == Effect.KiaiTime ? 4 : 2), 0.995, ticker.deltaMS);\n } else {\n this.logoAmplitudeContainer.scale = 1;\n this.triangles.Velocity = MathUtil.Damp(this.triangles.Velocity, 0.5, 0.9, ticker.deltaMS);\n }\n if (this.lastTimeElapasedSinceLastBeat > this.timeElapsedSinceLastBeat) {\n this.onNewBeat();\n }\n\n this.lastTimeElapasedSinceLastBeat = this.timeElapsedSinceLastBeat;\n\n if (this.isMouseDown) {\n let change = {x: Main.mousePos.x - this.mouseDownPosition.x, y: Main.mousePos.y - this.mouseDownPosition.y};\n let length = Math.sqrt(change.x * change.x + change.y * change.y);\n // Diminish the drag distance as we go further to simulate \"rubber band\" feeling.\n change.x *= length <= 0 ? 0 : Math.pow(length, 0.6) / length;\n change.y *= length <= 0 ? 0 : Math.pow(length, 0.6) / length;\n this.logoBounceContainer.x = change.x;\n this.logoBounceContainer.y = change.y;\n }\n\n\n }\n\n private onNewBeat() {\n let audio = Main.AudioEngine.GetCurrentPlayingMusic();\n let audioTime = audio.GetCurrentTime();\n let timingPointUninherited = audio.beatmap.TimingPoints.GetCurrentUninheritedTimingPoint(audioTime);\n let beatLength = timingPointUninherited.beatLength;\n let timingPoint = audio.beatmap.TimingPoints.GetCurrentTimingPoints(audioTime)[0];\n let maxAmplitude = !Main.AudioEngine.useSilentMusic ? audio.GetMaximumAudioLevel() : 0;\n let amplitudeAdjust = Math.min(1, 0.2 + maxAmplitude);\n Ease.getEase(this.logoBeatContainer).ScaleTo(1 - 0.02 * amplitudeAdjust, this.early_activation, TWEEN.Easing.Linear.None).Then()\n .ScaleTo(1, beatLength * 2, TWEEN.Easing.Quintic.Out);\n this.rippleContainer.scale = 1.02;\n Ease.getEase(this.rippleContainer).ClearEasings().ScaleTo(1.02 * (1 + 0.04 * amplitudeAdjust), beatLength, TWEEN.Easing.Quintic.Out);\n this.ripple.alpha = 0.15 * amplitudeAdjust;\n Ease.getEase(this.ripple).ClearEasings().FadeOut(beatLength, TWEEN.Easing.Quintic.Out);\n\n\n if (timingPoint.effects == Effect.KiaiTime) {\n Ease.getEase(this.triangles.flash).ClearEasings()\n .FadeTo(0.2 * amplitudeAdjust, this.early_activation, TWEEN.Easing.Linear.None).Then()\n .FadeTo(0, beatLength, TWEEN.Easing.Linear.None);\n Ease.getEase(this.visualizer).ClearEasings()\n .FadeTo(this.defaultVisualizerAlpha * 1.8 * amplitudeAdjust, this.early_activation, TWEEN.Easing.Linear.None).Then()\n .FadeTo(this.defaultVisualizerAlpha, beatLength, TWEEN.Easing.Linear.None);\n }\n setTimeout(() => {\n this.triangles.Velocity += amplitudeAdjust * (timingPoint.effects == Effect.KiaiTime ? 6 : 3);\n }, 60)\n\n }\n\n}\n","import * as PIXI from \"pixi.js\";\nimport {Main} from \"../../../main\";\nimport glVertShader from \"./osuCircleTriangles.vert\";\nimport glFragShader from \"./osuCircleTriangles.frag\";\nimport gpuShader from \"./osuCircleTriangles.wgsl\";\n\nexport class Triangles extends PIXI.Container {\n\n public flash: PIXI.Sprite;\n public Velocity: number = 1;\n private readonly bgGradient: PIXI.FillGradient;\n private triangles: Triangle[] = [];\n private graphics: PIXI.Graphics = new PIXI.Graphics();\n private timeSinceLastSpawn = 0;\n private instancePositionBuffer;\n private readonly totalTriangles = 15;\n\n public constructor() {\n super();\n\n let colorStops = [0xff66ab, 0xcc5289];\n this.bgGradient = new PIXI.FillGradient(0, 0, 0, 1024);\n colorStops.forEach((number, index) => {\n const ratio = index / colorStops.length;\n this.bgGradient.addColorStop(ratio, number);\n });\n\n for (let i = 0; i < this.totalTriangles; i++) {\n this.triangles.push({x: this.random(0, 1024), y: this.random(0, 1024), velocity: this.randVelocity()});\n }\n this.timeSinceLastSpawn = Date.now();\n\n this.graphics.rect(0, 0, 1024, 1024);\n this.graphics.fill(this.bgGradient);\n this.addChild(this.graphics);\n\n this.flash = PIXI.Sprite.from(\"mainMenu.logoMask\");\n //this.flash.anchor.set(0.5, 0.5);\n this.flash.alpha = 0;\n this.flash.blendMode = \"add\";\n\n this.instancePositionBuffer = new PIXI.Buffer({\n data: new Float32Array(this.totalTriangles * 2),\n usage: PIXI.BufferUsage.VERTEX | PIXI.BufferUsage.COPY_DST\n });\n const color = new PIXI.Color(\"rgb(182, 52, 111)\");\n const size = 30;\n const geometry = new PIXI.Geometry({\n attributes: {\n aPosition: [\n -10*size,\n -10*size, // x, y\n 10*size,\n -10*size, // x, y\n 10*size,\n 7.5*size, // x, y,\n -10*size,\n 7.5*size, // x, y,\n ],\n aUV: [0, 0, 1, 0, 1, 1, 0, 1],\n aColorTint: [\n color.red, color.green, color.blue, 1,\n color.red, color.green, color.blue, 1,\n color.red, color.green, color.blue, 1,\n color.red, color.green, color.blue, 1\n ],\n aPositionOffset: {\n buffer: this.instancePositionBuffer,\n instance: true\n }\n },\n indexBuffer: [0, 1, 2, 0, 2, 3],\n instanceCount: this.totalTriangles\n });\n const gl = {\n vertex: glVertShader,\n fragment: glFragShader\n };\n\n const gpu = {\n vertex: {\n entryPoint: \"mainVert\",\n source: gpuShader\n },\n fragment: {\n entryPoint: \"mainFrag\",\n source: gpuShader\n }\n };\n\n const triangleGraphic = new PIXI.Graphics();\n triangleGraphic.moveTo(0, 0);\n triangleGraphic.lineTo(-256, 512);\n triangleGraphic.lineTo(256, 512);\n triangleGraphic.lineTo(0, 0);\n triangleGraphic.stroke({color: \"white\", width: 4});\n\n const triangleTexture = Main.app.renderer.generateTexture(triangleGraphic);\n\n const shader = PIXI.Shader.from({\n gl,\n gpu,\n resources: {\n uTexture: triangleTexture.source,\n uSampler: triangleTexture.source.style,\n waveUniforms: {\n time: { value: 1, type: \"f32\" }\n }\n }\n });\n\n const triangleMesh = new PIXI.Mesh({\n geometry,\n shader\n });\n\n this.addChild(triangleMesh);\n\n\n\n }\n\n public destroy(options?: PIXI.DestroyOptions) {\n super.destroy(options);\n }\n\n public draw(ticker: PIXI.Ticker) {\n const data = this.instancePositionBuffer.data;\n let count = 0;\n\n for (let i = 0; i < this.totalTriangles; i++) {\n const triangle = this.triangles[i];\n\n triangle.y -= ((ticker.deltaTime * this.Velocity * triangle.velocity)*1.2);\n\n if (triangle.y + 100 < 0) {\n triangle.y = 1024 + 250;\n }\n\n data[count++] = triangle.x;\n data[count++] = triangle.y;\n }\n\n this.instancePositionBuffer.update();\n }\n\n private random(min: number, max: number) {\n return Math.random() * (max - min) + min;\n }\n\n private randVelocity() {\n let u1 = 1 - this.random(0, 1);\n let u2 = 1 - this.random(0, 1);\n let randStdNormal = (Math.sqrt(-2.0 * Math.log(u1)) * Math.sin(2.0 * Math.PI * u2));\n return Math.max(0.5 + 0.16 * randStdNormal, 0.1);\n }\n}\n\nexport interface Triangle {\n x: number;\n y: number;\n velocity: number;\n}\n","import * as PIXI from \"pixi.js\";\nimport {Main} from \"../../main\";\nimport {Loader} from \"../../Loader\";\nimport {MathUtil} from \"../../Util/MathUtil\";\nimport {Screen} from \"../../Screens/Screen\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\n\nexport class MenuCursor extends PIXI.Container {\n private mouseCursor = PIXI.Sprite.from(\"menu.cursor\");\n private mouseCursorAdditive = PIXI.Sprite.from(\"menu.cursor.additive\");\n private mouseContainer = new PIXI.Container();\n private animContainer = new PIXI.Container();\n private animRotationContainer = new PIXI.Container();\n private dragRotationState: DragRotationState = DragRotationState.NotDragging;\n private lastDragRotationState: DragRotationState = DragRotationState.NotDragging;\n private mouseHideContainer = new PIXI.Container();\n private readonly elastic_const2 = 0.075;\n private readonly elastic_const = 20.943951023931955;\n private readonly elastic_offset_quarter = Math.pow(2, -10) * Math.sin((.25 - this.elastic_const2) * this.elastic_const);\n\n private posMouseDown: { x: number, y: number } = {x: 0, y: 0};\n\n private mouseIsDown = false;\n\n private cursorTapSample = Loader.GetAudio(\"menu.cursor.sample.tap\");\n\n private mouseButtonClicked: number = -9999;\n\n public constructor(visible: boolean) {\n super();\n this.updateMouse();\n this.mouseContainer.scale.set(0.07 * Screen.getScaleBasedOffScreenSize());\n this.mouseCursorAdditive.alpha = 0;\n this.mouseCursorAdditive.blendMode = \"add\";\n this.mouseCursorAdditive.tint = \"0xFF66AA\"\n this.mouseContainer.addChild(this.mouseCursor);\n this.mouseContainer.addChild(this.mouseCursorAdditive);\n this.animContainer.addChild(this.mouseContainer);\n this.animRotationContainer.addChild(this.animContainer);\n this.mouseHideContainer.addChild(this.animRotationContainer);\n this.addChild(this.mouseHideContainer);\n if (!visible) {\n this.mouseHideContainer.scale.set(0.6);\n this.mouseHideContainer.alpha = 0;\n this.animRotationContainer.angle = 0;\n }\n this.zIndex = 999999;\n this.eventMode = \"none\";\n Main.app.stage.addChild(this);\n this.addEventListeners();\n }\n\n public addEventListeners() {\n Main.app.stage.addEventListener(\"mousedown\", (e) => {\n this.mouseButtonClicked = e.button;\n if (this.visible) {\n this.posMouseDown = {x: Main.mousePos.x, y: Main.mousePos.y};\n this.mouseIsDown = true;\n this.dragRotationState = DragRotationState.DragStarted;\n Ease.getEase(this.animContainer).ClearEasings().ScaleTo(0.9, 800, TWEEN.Easing.Quintic.Out);\n Ease.getEase(this.mouseCursorAdditive).ClearEasings().FadeIn(800, TWEEN.Easing.Quintic.Out);\n Main.AudioEngine.PlayEffect(this.cursorTapSample);\n }\n });\n Main.app.stage.addEventListener(\"mouseup\", (e) => {\n if (this.visible && e.button == this.mouseButtonClicked) {\n this.mouseIsDown = false;\n Ease.getEase(this.animContainer).ClearEasings().ScaleTo(1, 500, TWEEN.Easing.Elastic.Out);\n Ease.getEase(this.mouseCursorAdditive).ClearEasings().FadeOut(500, TWEEN.Easing.Quintic.Out);\n if (this.dragRotationState != DragRotationState.NotDragging) {\n if (this.dragRotationState == DragRotationState.Rotating) {\n Ease.getEase(this.animRotationContainer).ClearEasings().createTween({value: this.animRotationContainer.angle},\n {value: 0}, true, \"angle\", 800 * (0.5 + Math.abs(this.animRotationContainer.angle / 960)), (time: number) => {\n return Math.pow(2, -10 * time) * \n Math.sin((.25 * time - this.elastic_const2) * this.elastic_const) + 1 - this.elastic_offset_quarter * time;\n });\n }\n this.dragRotationState = DragRotationState.NotDragging;\n }\n Main.AudioEngine.PlayEffect(this.cursorTapSample, 0.8);\n }\n });\n }\n\n public PopIn() {\n Ease.getEase(this.animRotationContainer).ClearEasings();\n this.visible = true;\n Ease.getEase(this.mouseHideContainer).ClearEasings().FadeIn(250, TWEEN.Easing.Quintic.Out)\n .ScaleTo(1, 400, TWEEN.Easing.Quintic.Out);\n this.dragRotationState = DragRotationState.NotDragging\n }\n\n public PopOut() {\n Ease.getEase(this.mouseHideContainer).ClearEasings().FadeOut(250, TWEEN.Easing.Quintic.Out)\n .ScaleTo(0.6, 250, TWEEN.Easing.Quintic.Out);\n Ease.getEase(this.animRotationContainer).ClearEasings().createTween({value: this.animRotationContainer.angle},\n {value: 0}, true, \"angle\", 400, TWEEN.Easing.Quintic.Out);\n this.dragRotationState = DragRotationState.NotDragging;\n }\n\n public updateMouse() {\n this.mouseContainer.scale.set(0.07 * Screen.getScaleBasedOffScreenSize());\n this.position.set(Main.mousePos.x, Main.mousePos.y);\n if (this.dragRotationState != DragRotationState.NotDragging && this.visible) {\n let distance = Math.sqrt((((Math.abs(this.posMouseDown.x - Main.mousePos.x)) ^ 2) +\n ((Math.abs(this.posMouseDown.y - Main.mousePos.y)) ^ 2)));\n if (this.dragRotationState == DragRotationState.DragStarted && distance > 15) {\n this.dragRotationState = DragRotationState.Rotating;\n if (this.lastDragRotationState != this.dragRotationState) {\n this.posMouseDown = {x: Main.mousePos.x, y: Main.mousePos.y};\n }\n }\n\n if (this.dragRotationState == DragRotationState.Rotating && distance > 0) {\n let offsetX = Main.mousePos.x - this.posMouseDown.x;\n let offsetY = Main.mousePos.y - this.posMouseDown.y;\n let degrees = MathUtil.RadiansToDegrees(Math.atan2(-offsetX, offsetY)) + 24.3;\n\n let diff = (degrees - this.animRotationContainer.angle) % 360;\n if (diff < -180) {\n diff += 360;\n }\n if (diff > 180) {\n diff -= 360;\n }\n degrees = this.animRotationContainer.angle + diff;\n this.animRotationContainer.angle = degrees\n Ease.getEase(this.animRotationContainer).createTween({value: this.animRotationContainer.angle},\n {value: degrees}, true, \"angle\", 120, TWEEN.Easing.Quintic.Out);\n }\n }\n this.lastDragRotationState = this.dragRotationState;\n\n }\n\n\n}\n\nenum DragRotationState {\n NotDragging,\n DragStarted,\n Rotating\n}\n","import * as PIXI from \"pixi.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {DestroyOptions} from \"pixi.js\";\n\nexport class Background extends PIXI.Sprite {\n public static readonly fadeOutDuration = 800;\n public destroying = false;\n\n public constructor(texture: PIXI.Texture) {\n super();\n this.texture = texture;\n this.visible = false;\n this.anchor.set(0.5, 0.5);\n\n }\n\n public show() {\n this.visible = true;\n }\n\n public destroy(options?: PIXI.DestroyOptions) {\n this.destroying = true;\n Ease.getEase(this).FadeOut(Background.fadeOutDuration, TWEEN.Easing.Linear.None).Then(() => {\n this.visible = false;\n super.destroy(options);\n this.destroying = false;\n });\n this.zIndex = 1;\n }\n}\n\nexport class BackgroundContainer extends PIXI.Container {\n public constructor() {\n super();\n this.visible = false;\n }\n\n public show() {\n this.visible = true;\n for (let i = 0; i < this.children?.length; i++) {\n let child = this.children[i];\n if (child instanceof Background) {\n child.show();\n }\n }\n }\n\n public destroy(options?: DestroyOptions) {\n for (let i = 0; i < this.children?.length; i++) {\n let child = this.children[i];\n if (child instanceof Background) {\n if (!child.destroyed && !child.destroying) {\n child.destroy(options);\n }\n }\n }\n setTimeout(() => {\n super.destroy(options);\n }, Background.fadeOutDuration);\n this.zIndex = 1;\n }\n\n\n}","import * as PIXI from \"pixi.js\";\nimport {Loader} from \"../../Loader\";\nimport {Screen} from \"../../Screens/Screen\";\nimport {Main} from \"../../main\";\nimport {Background, BackgroundContainer} from \"./Background\";\nimport {EventTypes} from \"../../Util/Beatmap/Data/Sections/Events/EventTypes\";\nimport {EventVideo} from \"../../Util/Beatmap/Data/Sections/Events/EventVideo\";\nimport {EventBackground} from \"../../Util/Beatmap/Data/Sections/Events/EventBackground\";\n\nexport class RandomBackground extends Screen {\n\n private bgContainer = new PIXI.Container;\n\n private readonly parallaxMultiplier = 60;\n\n public start() {\n this.bgContainer.pivot.set(0.5, 0.5);\n this.bgContainer.position.set((Main.mousePos.x - (this.getScreenWidth() / 2)) / this.parallaxMultiplier,\n (Main.mousePos.y - (this.getScreenHeight() / 2)) / this.parallaxMultiplier);\n this.addChild(this.bgContainer);\n this.newRandomBG();\n Main.AudioEngine.addMusicChangeEventListener((audio) => {\n let background = audio.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.BACKGROUND){\n return e;\n }\n }) as EventBackground;\n\n let backgroundVideo = audio.beatmap.Events.Events.find((e) => {\n if (e.eventType == EventTypes.VIDEO){\n return e;\n }\n }) as EventVideo;\n\n let bgContainer = new BackgroundContainer();\n\n if (background) {\n if (background.texture) {\n bgContainer.addChild(new Background(background.texture));\n }\n }\n if (backgroundVideo) {\n if (backgroundVideo.texture) {\n let video = backgroundVideo.texture.source.resource as HTMLVideoElement;\n let bg = new Background(backgroundVideo.texture);\n bgContainer.addChild(bg);\n backgroundVideo.texture.source.resource.startPromise = new Promise((resolve) => {\n if (backgroundVideo.startTime > 0) {\n setTimeout(() => {\n video.play();\n resolve();\n }, backgroundVideo.startTime);\n } else {\n video.currentTime = Math.abs(backgroundVideo.startTime)/1000;\n video.play();\n resolve();\n }\n });\n video.onended = () => {\n bg.destroy();\n }\n }\n }\n if (background || backgroundVideo) {\n this.setBGContainer(bgContainer);\n }\n if (!background && !backgroundVideo) {\n this.newRandomBG();\n }\n });\n this.zIndex = -100;\n }\n\n public setBG(texture: PIXI.Texture) {\n let bgSprite = new Background(texture);\n this.bgContainer.addChild(bgSprite);\n bgSprite.show();\n if (this.bgContainer.children?.length == 0) {\n } else {\n let previous = this.bgContainer.children[0] as Background;\n previous.destroy();\n }\n this.onResize();\n }\n\n public setBGContainer(container: BackgroundContainer) {\n this.bgContainer.addChild(container);\n container.show();\n if (this.bgContainer.children?.length == 0) {\n } else {\n let previous = this.bgContainer.children[0] as Background;\n previous.destroy();\n }\n this.onResize();\n }\n\n public newRandomBG() {\n function random(min: number, max: number) {\n return Math.round(Math.random() * (max - min) + min);\n }\n\n let useSeasonalBackgrounds = Loader.seasonalBackgroundsNum > 0;\n let randomNum = random(1, useSeasonalBackgrounds ? Loader.seasonalBackgroundsNum : Loader.defaultBackgroundsNum);\n this.setBG(PIXI.Texture.from((useSeasonalBackgrounds ? \"seasonal_bg\" : \"default_bg\") + randomNum));\n }\n\n public draw(deltaTime: PIXI.Ticker) {\n this.bgContainer.position.set((Main.mousePos.x - (this.getScreenWidth() / 2)) / this.parallaxMultiplier,\n (Main.mousePos.y - (this.getScreenHeight() / 2)) / this.parallaxMultiplier);\n }\n\n public onClose(): Promise {\n return Promise.resolve(this);\n }\n\n public onResize() {\n this.bgContainer.children.forEach((sprite) => {\n if (sprite instanceof BackgroundContainer) {\n sprite.children?.forEach((sprite) => {\n if (sprite instanceof Background) {\n this.resizeSprite(sprite);\n }\n });\n }\n if (sprite instanceof Background) {\n this.resizeSprite(sprite)\n }\n });\n }\n\n private resizeSprite(sprite: Background) {\n let texWidth = sprite.texture.width;\n let texHeight = sprite.texture.height;\n\n let scaleFactor: number;\n if (window.innerWidth > window.innerHeight) {\n scaleFactor = window.innerWidth / texWidth;\n } else {\n scaleFactor = window.innerHeight / texHeight;\n }\n\n if (texHeight * scaleFactor < window.innerHeight) {\n scaleFactor = window.innerHeight / texHeight;\n } else if (texWidth * scaleFactor < window.innerWidth) {\n\n }\n\n sprite.scale.set(scaleFactor + 0.05);\n sprite.position.set((this.getScreenWidth() / 2) - (this.getScreenWidth() / (this.parallaxMultiplier * 2)),\n this.getScreenHeight() / 2 - (this.getScreenHeight() / (this.parallaxMultiplier * 2)));\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Screen} from \"../../Screens/Screen\";\n\nexport class SettingsPane extends PIXI.Container {\n private bg: PIXI.Graphics = new PIXI.Graphics();\n private isOpen = false;\n\n public constructor() {\n super();\n this.bg.rect(0, 0, 1, 1);\n this.bg.fill({color: \"rgb(20,20,20)\"});\n this.addChild(this.bg);\n this.resize();\n }\n\n public open() {\n Ease.getEase(this).TransformTo({x: 0, y: 0}, 400, TWEEN.Easing.Cubic.Out);\n this.isOpen = true;\n }\n\n public toggle() {\n if (this.isOpen) {this.close()} else {this.open()}\n }\n\n public close() {\n Ease.getEase(this).TransformTo({x: -this.getWidth(), y: 0}, 400, TWEEN.Easing.Cubic.Out);\n this.isOpen = false;\n }\n\n private getWidth() {\n return 500 * Screen.getScaleBasedOffScreenSize();\n }\n\n public resize() {\n this.width = this.getWidth();\n this.height = window.innerHeight;\n this.x = this.isOpen ? 0 : -this.getWidth();\n this.y = 0;\n }\n}","import * as PIXI from \"pixi.js\";\n\nexport class Loader {\n private static loadList: LoaderObject[] = [];\n private static loadedList: LoadedObject[] = [];\n public static readonly defaultBackgroundsNum = 8;\n public static seasonalBackgroundsNum: number = 0;\n\n private static addToLoadList() {\n // intro and interaction screen\n this.loadList.push({id: \"introTrianglesTrack\", url: \"assets/osu-assets/osu.Game.Resources/Tracks/triangles.osz\"});\n this.loadList.push({id: \"sample_dialog_ok\", url: \"assets/osu-assets/osu.Game.Resources/Samples/UI/dialog-ok-select.wav\", isAudio: true});\n this.loadList.push({id: \"TorusRegular\", url: \"assets/fonts/TorusRegular.otf\", pixiBundleName: \"fonts\"});\n this.loadList.push({id: \"TorusLight\", url: \"assets/fonts/TorusLight.otf\", pixiBundleName: \"fonts\"});\n this.loadList.push({id: \"TorusThin\", url: \"assets/fonts/TorusThin.otf\", pixiBundleName: \"fonts\"});\n this.loadList.push({id: \"icon_ruleset_std\", url: \"assets/icons/ruleset-standard.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"icon_ruleset_mania\", url: \"assets/icons/ruleset-mania.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"icon_ruleset_taiko\", url: \"assets/icons/ruleset-taiko.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"icon_ruleset_ctb\", url: \"assets/icons/ruleset-ctb.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"intro_triangles_osuLogo_anim_highlight\",\n url: \"assets/osu-assets/osu.Game.Resources/Textures/Intro/Triangles/logo-highlight.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"intro_triangles_osuLogo_anim_background\",\n url: \"assets/osu-assets/osu.Game.Resources/Textures/Intro/Triangles/logo-background.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"mainMenu.logoOutline\", url: \"assets/osu-assets/osu.Game.Resources/Textures/Menu/logo.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"mainMenu.logoMask\", url: \"assets/menu/logo-mask.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"mainMenu.osuLogo.select\", url: \"assets/osu-assets/osu.Game.Resources/Samples/Menu/osu-logo-select.wav\", isAudio: true});\n this.loadList.push({id: \"mainMenu.osuLogo.backToLogo\", url: \"assets/osu-assets/osu.Game.Resources/Samples/Menu/back-to-logo.wav\", isAudio: true});\n this.loadList.push({id: \"menu.cursor\", url: \"assets/osu-assets/osu.Game.Resources/Textures/Cursor/menu-cursor.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"menu.cursor.additive\", url: \"assets/osu-assets/osu.Game.Resources/Textures/Cursor/menu-cursor-additive.png\",\n pixiBundleName: \"textures\"});\n this.loadList.push({id: \"menu.cursor.sample.tap\", url: \"assets/osu-assets/osu.Game.Resources/Samples/UI/cursor-tap.wav\", isAudio: true});\n this.loadList.push({id: \"menu.kiaiFountains.star\", url: \"assets/osu-assets/osu.Game.Resources/Textures/Menu/fountain-star.png\", pixiBundleName: \"textures\"});\n this.loadList.push({id: \"workers.ffmpeg\", url: \"assets/workers/814.ffmpeg.js\"});\n this.loadList.push({id: \"ffmpeg.core\", url: \"https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm/ffmpeg-core.js\"});\n this.loadList.push({id: \"ffmpeg.wasm\", url: \"https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm/ffmpeg-core.wasm\"});\n this.loadList.push({id: \"ffmpeg.coreWorker\", url: \"https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm/ffmpeg-core.worker.js\"});\n }\n\n public static Get(id: string): Blob {\n let result;\n this.loadedList.forEach((loadedObj) => {\n if (loadedObj.id == id){\n result = loadedObj.data;\n }\n });\n if (!result){\n throw new Error(\"Asset not found!\");\n }\n return result;\n }\n\n public static GetString(id: string): string {\n let result;\n this.loadedList.forEach((loadedObj) => {\n if (loadedObj.id == id){\n result = loadedObj.dataString;\n }\n });\n if (!result){\n throw new Error(\"Asset not found or is not a string!\");\n }\n return result;\n }\n\n public static GetAudio(id: string): AudioBuffer {\n let result;\n this.loadedList.forEach((loadedObj) => {\n if (loadedObj.id == id){\n result = loadedObj.dataAudio;\n }\n });\n if (!result){\n throw new Error(\"Asset not found or was not marked as audio during loading!\");\n }\n return result;\n }\n\n private static addBackgrounds() {\n return new Promise(resolve => {\n for (let i = 1; i < this.defaultBackgroundsNum + 1; i++) {\n this.loadList.push({id: \"default_bg\"+i, url: \"assets/osu-assets/osu.Game.Resources/Textures/Menu/menu-background-\"+i+\".jpg\", pixiBundleName: \"textures\"});\n }\n fetch(\"https://corsproxy.io/?\"+ encodeURIComponent(\"https://osu.ppy.sh/api/v2/seasonal-backgrounds\"))\n .then(res => res.json()).then(res => {\n res.backgrounds.forEach((background: any, index: number) => {\n this.loadList.push({id: \"seasonal_bg\"+(index+1), url: \"https://corsproxy.io/?\"+ encodeURIComponent(background.url),\n pixiBundleName: \"textures\", loadParser: \"loadTextures\"});\n this.seasonalBackgroundsNum = index+1;\n });\n resolve();\n }).catch(error => {\n console.warn(\"Could not fetch seasonal backgrounds.\", error);\n resolve();\n });\n });\n }\n\n public static Load(audioContext: AudioContext) {\n this.addToLoadList();\n return new Promise((resolve) => {\n this.addBackgrounds().then(() => {\n let nonPixi: LoaderObject[] = [];\n let pixi: LoaderObject[] = [];\n let pixiwithBundles: LoaderObject[][] = [];\n\n let loadedAssets: number = 0;\n let erroredAssets: number = 0;\n\n this.loadList.forEach((loadObj) => {\n if (loadObj.pixiBundleName){\n pixi.push(loadObj);\n }\n else {\n nonPixi.push(loadObj);\n }\n });\n\n pixi.forEach((loadObj) => {\n let added = false;\n pixiwithBundles.forEach((loadObjs) => {\n if (loadObjs.length > 0){\n if (loadObjs[0].pixiBundleName == loadObj.pixiBundleName){\n loadObjs.push(loadObj);\n added = true;\n }\n }\n });\n if (!added){\n pixiwithBundles.push([loadObj]);\n }\n });\n\n const incrementLoadAssetNumber = (errored?: boolean) => {\n if (errored){\n erroredAssets++;\n }\n else {\n loadedAssets++;\n }\n\n if (erroredAssets + loadedAssets >= this.loadList.length){\n resolve();\n }\n }\n\n nonPixi.forEach((loadObj) => {\n fetch(loadObj.url)\n .then(response => response.blob())\n .then((response) => {\n if (!loadObj.isText && !loadObj.isAudio){\n incrementLoadAssetNumber();\n this.loadedList.push({id: loadObj.id, data: response});\n }\n else if (loadObj.isText) {\n response.text().then((text) => {\n incrementLoadAssetNumber();\n this.loadedList.push({id: loadObj.id, data: response, dataString: text});\n });\n }\n else if (loadObj.isAudio){\n response.arrayBuffer().then(arrBuff => audioContext.decodeAudioData(arrBuff))\n .then((audioBuff) => {\n incrementLoadAssetNumber();\n this.loadedList.push({id: loadObj.id, data: response, dataAudio: audioBuff});\n });\n }\n\n })\n .catch((error) => {\n incrementLoadAssetNumber(true);\n console.warn(\"Asset '\"+loadObj.id+\"' failed to load: \"+error);\n });\n });\n\n pixiwithBundles.forEach((bundle) => {\n if (bundle.length > 0){\n if (!bundle[0].pixiBundleName){\n throw new Error(\"wtf????\");\n }\n let assets: PIXI.UnresolvedAsset[] = [];\n bundle.forEach((loadObj) => {\n if (loadObj.loadParser){\n assets.push({alias: loadObj.id, src: loadObj.url, loadParser: loadObj.loadParser});\n }\n else {\n assets.push({alias: loadObj.id, src: loadObj.url});\n }\n\n });\n PIXI.Assets.addBundle(bundle[0].pixiBundleName, assets);\n PIXI.Assets.loadBundle(bundle[0].pixiBundleName).then(() => {\n bundle.forEach(() => {\n incrementLoadAssetNumber();\n });\n });\n }\n\n })\n });\n });\n }\n}\n\ninterface LoaderObject {\n id: string;\n url: string;\n pixiBundleName?: string;\n isText?: boolean;\n isAudio?: boolean;\n loadParser?: PIXI.LoadParserName;\n}\n\ninterface LoadedObject {\n id: string;\n data: Blob;\n dataString?: string;\n dataAudio?: AudioBuffer;\n}\n","import {Screen} from \"../Screen\";\nimport * as PIXI from \"pixi.js\";\nimport {Ticker} from \"pixi.js\";\nimport {Main} from \"../../main\";\nimport {IntroScreen} from \"../IntroScreen/IntroScreen\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\n\nexport class InteractScreen extends Screen {\n\n private readonly text: PIXI.Text;\n private readonly text2: PIXI.Text;\n private readonly textContainer = new PIXI.Container();\n private readonly textContainerContainer = new PIXI.Container();\n\n private readonly introTrack: Blob;\n private clickSound: AudioBuffer;\n\n private readonly clickArea: PIXI.Graphics = new PIXI.Graphics();\n\n public constructor(introTrack: Blob, clickSound: AudioBuffer) {\n super();\n this.introTrack = introTrack;\n this.clickSound = clickSound;\n\n this.text = new PIXI.Text({\n text: \"Click anywhere to play!\",\n style: {\n fontFamily: 'TorusRegular',\n fontSize: 36,\n fill: \"white\"\n }\n });\n this.text2 = new PIXI.Text({\n text: \"(this is for enabling audio because it's required by web-browsers\\n to have interaction on this webpage before playing audio.)\",\n style: {\n fontFamily: 'TorusRegular',\n fontSize: 26,\n fill: \"gray\",\n align: \"center\"\n }\n });\n }\n\n public start() {\n this.text.anchor.set(0.5, 0.5);\n this.text2.anchor.set(0.5, 0.5);\n this.text2.position.set(0, this.text.height + 15);\n this.textContainer.addChild(this.text);\n this.textContainer.addChild(this.text2);\n this.textContainer.scale.set(0.5);\n this.textContainer.alpha = 0;\n this.textContainerContainer.addChild(this.textContainer);\n this.textContainerContainer.scale = Screen.getScaleBasedOffScreenSize();\n this.textContainerContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.addChild(this.textContainerContainer);\n\n this.clickArea.rect(0, 0, 1, 1);\n this.clickArea.fill(\"rgba(0,0,0,0)\");\n this.clickArea.width = this.getScreenWidth();\n this.clickArea.height = this.getScreenHeight();\n this.clickArea.position.set(0, 0);\n this.addChild(this.clickArea);\n\n this.clickArea.eventMode = \"static\";\n this.clickArea.cursor = \"pointer\";\n\n const clicked = () => {\n this.clickArea.eventMode = \"none\";\n Main.AudioEngine.PlayEffect(this.clickSound);\n Main.switchScreen(new IntroScreen(this.introTrack));\n document.body.style.cursor = \"none\";\n Main.pointerLock();\n Main.lockKeyboard();\n }\n\n this.clickArea.onclick = () => {\n clicked();\n\n }\n this.clickArea.ontap = () => {\n clicked();\n }\n Ease.getEase(this.textContainer).FadeIn(400, TWEEN.Easing.Quadratic.Out)\n .ScaleTo(1, 400, TWEEN.Easing.Quadratic.Out);\n }\n\n public onClose(): Promise {\n return new Promise((resolve) => {\n Ease.getEase(this.textContainer).FadeOut(200, TWEEN.Easing.Quadratic.Out)\n .ScaleTo(0.5, 200, TWEEN.Easing.Quadratic.InOut);\n setTimeout(() => {\n resolve(this);\n }, 200);\n });\n }\n\n public draw(deltaTime: Ticker) {\n\n }\n\n public onResize() {\n this.textContainerContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.clickArea.width = this.getScreenWidth();\n this.clickArea.height = this.getScreenHeight();\n this.clickArea.position.set(0, 0);\n this.textContainerContainer.scale = Screen.getScaleBasedOffScreenSize();\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\n\nexport class GlitchingTriangles extends PIXI.Container {\n public constructor(bounds: GlitchingTrianglesBounds) {\n super();\n let triangle = new PIXI.Graphics();\n let scale = random(0.2, 1.2);\n triangle.moveTo(0, 0);\n triangle.lineTo(-50 * scale, 100 * scale);\n triangle.lineTo(50 * scale, 100 * scale);\n triangle.lineTo(0, 0);\n if (Math.random() < 0.5) {\n triangle.fill(\"white\");\n } else {\n triangle.stroke({color: \"white\", width: 1});\n }\n\n //triangle.anchor.set(0.5, 0.5)\n function random(min: number, max: number) {\n return Math.random() * (max - min) + min;\n }\n\n let randX = random(bounds.x1, bounds.x2);\n let randY = random(bounds.y1, bounds.y2);\n\n triangle.position.set(randX, randY);\n\n Ease.getEase(triangle, true).FadeOut(200, TWEEN.Easing.Linear.None);\n setTimeout(() => {\n this.destroy();\n }, 200);\n\n this.addChild(triangle);\n }\n\n}\n\nexport interface GlitchingTrianglesBounds {\n x1: number;\n x2: number;\n y1: number;\n y2: number;\n}\n","import {Screen} from \"../Screen\";\nimport * as PIXI from \"pixi.js\";\nimport {Ticker} from \"pixi.js\";\nimport {unzip} from 'unzipit';\nimport {Main} from \"../../main\";\nimport {GlitchingTriangles} from \"./GlitchingTriangles\";\nimport {MainMenu} from \"../MainMenu/MainMenu\";\nimport {LazerLogo} from \"./LazerLogo\";\nimport {BeatmapParser} from \"../../Util/Beatmap/Parser/BeatmapParser\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\nimport {UIUtils} from \"../../Util/UI/UIUtils\";\nimport {CenteredList} from \"../../Util/UI/CenteredList\";\n\nexport class IntroScreen extends Screen {\n\n private readonly introTrackUrl: string;\n\n private doTextSpacingAnim = false;\n private triangles = new PIXI.Container();\n private ruleSetContainer = new PIXI.Container();\n private ruleSetList = new CenteredList({});\n private flash = new PIXI.Graphics();\n\n private logoContainerContainer = new PIXI.Container();\n\n private logoContainer = new PIXI.Container();\n\n private lazerLogo = new LazerLogo();\n\n private flashed = false;\n\n private standard = PIXI.Sprite.from('icon_ruleset_std');\n private taiko = PIXI.Sprite.from('icon_ruleset_taiko');\n private ctb = PIXI.Sprite.from('icon_ruleset_ctb');\n private mania = PIXI.Sprite.from('icon_ruleset_mania');\n\n private bg: PIXI.Graphics = new PIXI.Graphics();\n\n private completionPromise!: Promise;\n\n private welcomeText: PIXI.Text = new PIXI.Text({\n text: \"\",\n style: {\n fontFamily: \"TorusThin\",\n fontSize: 42,\n fill: \"white\",\n letterSpacing: 5\n }\n });\n\n public constructor(introTrack: Blob) {\n super();\n this.introTrackUrl = URL.createObjectURL(introTrack);\n this.bg.rect(0, 0, 1, 1,);\n this.bg.fill(\"black\");\n }\n\n public start() {\n this.bg.width = window.innerWidth;\n this.bg.height = window.innerHeight;\n this.bg.x = 0;\n this.bg.y = 0;\n this.addChild(this.bg);\n this.lazerLogo.scale.set(Screen.getScaleBasedOffScreenSize());\n this.logoContainer.addChild(this.lazerLogo);\n this.logoContainer.scale.set(1.2);\n\n this.logoContainerContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.logoContainerContainer.pivot.set(0.5, 0.5);\n this.logoContainerContainer.addChild(this.logoContainer);\n this.logoContainerContainer.alpha = 0;\n this.addChild(this.logoContainerContainer);\n\n this.flash.rect(0, 0, 1, 1);\n this.flash.fill(\"white\");\n this.flash.position.set(0, 0);\n this.flash.width = this.getScreenWidth();\n this.flash.height = this.getScreenHeight();\n this.flash.blendMode = \"add\";\n this.welcomeText.anchor.set(0.5, 0.5);\n this.welcomeText.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n (async () => {\n const {entries} = await unzip(this.introTrackUrl);\n for (const [name, entry] of Object.entries(entries)) {\n if (name.endsWith(\".osu\")) {\n entry.text().then(async (osuFile) => {\n let beatmapData = BeatmapParser.Parse(osuFile);\n for (const [name, entry] of Object.entries(entries)) {\n let blob = await entry.blob();\n beatmapData.files.set(name, blob);\n }\n await BeatmapParser.LoadFiles(beatmapData);\n let audioFile = beatmapData.General.audioFile;\n if (audioFile) {\n let url = URL.createObjectURL(audioFile);\n setTimeout(() => {\n Main.AudioEngine.PlayMusicImmediately(url, beatmapData, () => {\n this.afterAudioPlay();\n });\n }, 200);\n }\n console.log(beatmapData);\n });\n break;\n }\n }\n })();\n }\n\n public afterAudioPlay() {\n this.completionPromise = new Promise((resolve) => {\n this.welcomeText.scale.set(Screen.getScaleBasedOffScreenSize());\n this.addChild(this.welcomeText);\n setTimeout(() => {\n this.welcomeText.text = \"wel\";\n this.onResize();\n }, 200);\n setTimeout(() => {\n this.welcomeText.text = \"welcome\";\n this.onResize();\n }, 400);\n setTimeout(() => {\n this.welcomeText.text = \"welcome to\";\n this.onResize();\n }, 700);\n let glitchingInterval: NodeJS.Timeout;\n\n this.triangles.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.triangles.scale.set(Screen.getScaleBasedOffScreenSize());\n this.addChild(this.triangles);\n setTimeout(() => {\n this.welcomeText.text = \"welcome to kosu!\";\n this.doTextSpacingAnim = true;\n glitchingInterval = setInterval(() => {\n let triangle = new GlitchingTriangles({\n x1: -(this.welcomeText.width / 2) - 100,\n x2: (this.welcomeText.width / 2) + 100,\n y1: -(this.welcomeText.height / 2) - 150,\n y2: (this.welcomeText.height / 2) + 100\n });\n this.triangles.addChild(triangle);\n }, 30);\n this.onResize();\n }, 900);\n\n this.standard.scale = 0.5 * Screen.getScaleBasedOffScreenSize();\n this.ctb.scale = 0.5 * Screen.getScaleBasedOffScreenSize();\n this.mania.scale = 0.5 * Screen.getScaleBasedOffScreenSize();\n this.taiko.scale = 0.5 * Screen.getScaleBasedOffScreenSize();\n\n\n this.ruleSetList.addChild(this.standard);\n this.ruleSetList.addChild(this.taiko);\n this.ruleSetList.addChild(this.ctb);\n this.ruleSetList.addChild(this.mania);\n this.ruleSetList.padding = 0;\n this.ruleSetList.elementsMargin = 200 * Screen.getScaleBasedOffScreenSize();\n this.ruleSetList.type = \"horizontal\";\n this.ruleSetList.scale = 1;\n this.ruleSetContainer.addChild(this.ruleSetList);\n\n setTimeout(() => {\n this.doTextSpacingAnim = false;\n this.onResize();\n clearInterval(glitchingInterval);\n this.welcomeText.destroy();\n this.triangles.destroy();\n this.ruleSetContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.addChild(this.ruleSetContainer);\n this.ruleSetList.elementsMargin = 200 * Screen.getScaleBasedOffScreenSize();\n Ease.getEase(this.ruleSetContainer).ScaleTo(0.8, 1000, TWEEN.Easing.Linear.None);\n }, 1450);\n\n setTimeout(() => {\n this.ruleSetList.elementsMargin = 30 * Screen.getScaleBasedOffScreenSize();\n this.ruleSetList.scale = 2;\n UIUtils.centerPivotOfList(this.ruleSetList);\n }, 1650);\n\n setTimeout(() => {\n this.ruleSetList.elementsMargin = 10 * Screen.getScaleBasedOffScreenSize();\n this.ruleSetList.scale = 4;\n Ease.getEase(this.ruleSetContainer).ScaleTo(1.3, 1000, TWEEN.Easing.Linear.None);\n }, 1850);\n\n setTimeout(() => {\n this.ruleSetContainer.destroy();\n this.lazerLogo.start();\n\n this.logoContainerContainer.alpha = 1;\n\n this.logoContainerContainer.scale.set(1.2);\n Ease.getEase(this.logoContainerContainer).ScaleTo(1.2 - 0.8 * 0.25, 920, TWEEN.Easing.Quadratic.In);\n\n setTimeout(() => {\n Ease.getEase(this.logoContainer).ScaleTo(1.2 - 0.8, 920 * 0.3, TWEEN.Easing.Quintic.In);\n }, 920 * 0.7);\n }, 2080);\n\n setTimeout(() => {\n this.addChild(this.flash);\n this.bg.destroy();\n this.flash.eventMode = \"none\";\n this.flashed = true;\n this.logoContainerContainer.visible = false;\n Ease.getEase(this.flash).FadeOut(1000, TWEEN.Easing.Quadratic.Out).Then(() => {\n resolve();\n });\n Main.cursor.PopIn();\n }, 3000);\n });\n Main.switchScreen(new MainMenu());\n }\n\n public draw(deltaTime: Ticker) {\n if (this.doTextSpacingAnim) {\n this.welcomeText.style.letterSpacing += 0.15 * deltaTime.deltaTime;\n this.onResize();\n }\n }\n\n public onClose(): Promise {\n return new Promise((resolve) => {\n this.completionPromise.then(() => {\n resolve(this);\n })\n });\n }\n\n public onResize() {\n if (!this.bg.destroyed) {\n this.bg.width = window.innerWidth;\n this.bg.height = window.innerHeight;\n this.bg.x = 0;\n this.bg.y = 0;\n }\n if (!this.welcomeText.destroyed) {\n this.welcomeText.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n }\n if (!this.triangles.destroyed) {\n this.triangles.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.triangles.scale.set(Screen.getScaleBasedOffScreenSize());\n }\n if (!this.ruleSetContainer.destroyed) {\n this.ruleSetContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n }\n if (!this.flash.destroyed) {\n this.flash.position.set(0, 0);\n this.flash.width = this.getScreenWidth();\n this.flash.height = this.getScreenHeight();\n }\n if (!this.logoContainerContainer.destroyed) {\n this.logoContainerContainer.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n }\n if (!this.lazerLogo.destroyed) {\n this.lazerLogo.scale.set(Screen.getScaleBasedOffScreenSize());\n }\n if (!this.welcomeText.destroyed) {\n this.welcomeText.scale.set(Screen.getScaleBasedOffScreenSize());\n }\n if (!this.standard.destroyed) {\n this.standard.scale.set(0.5 * Screen.getScaleBasedOffScreenSize());\n }\n if (!this.mania.destroyed) {\n this.mania.scale.set(0.5 * Screen.getScaleBasedOffScreenSize());\n }\n if (!this.ctb.destroyed) {\n this.ctb.scale.set(0.5 * Screen.getScaleBasedOffScreenSize());\n }\n if (!this.taiko.destroyed) {\n this.taiko.scale.set(0.5 * Screen.getScaleBasedOffScreenSize());\n }\n if (!this.ruleSetList.destroyed) {\n this.ruleSetList.ReCenter();\n }\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport {LogoAnimation} from \"./LogoAnimation\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {Ease} from \"../../Util/TweenWrapper/Ease\";\n\nexport class LazerLogo extends PIXI.Container {\n private readonly highlight: LogoAnimation;\n private readonly background: LogoAnimation;\n private textureHighlight = PIXI.Texture.from(\"intro_triangles_osuLogo_anim_highlight\");\n private textureBackground = PIXI.Texture.from(\"intro_triangles_osuLogo_anim_background\");\n\n public constructor() {\n super();\n this.highlight = new LogoAnimation(this.textureHighlight, new PIXI.Color(\"white\"));\n this.background = new LogoAnimation(this.textureBackground, new PIXI.Color(\"rgb(128, 128, 128)\"));\n this.addChild(this.highlight);\n this.addChild(this.background);\n }\n\n public start() {\n let dummy = new PIXI.Container();\n dummy.scale.set(0.0, 0.0);\n Ease.getEase(dummy).ScaleTo(1, 920, TWEEN.Easing.Linear.None).OnEach(() => {\n this.highlight.setProgress(dummy.scale.x);\n this.background.setProgress(dummy.scale.x);\n });\n }\n}\n","import * as PIXI from \"pixi.js\"\nimport glVertShader from \"./logoAnimation.vert\";\nimport glFragShader from \"./logoAnimation.frag\";\nimport gpuShader from \"./logoAnimation.wgsl\";\n\nexport class LogoAnimation extends PIXI.Container {\n private shader: PIXI.Shader;\n private texture: PIXI.Texture;\n\n public constructor(texture: PIXI.Texture, color: PIXI.Color) {\n super();\n this.texture = texture\n this.shader = PIXI.Shader.from({\n gl: {\n vertex: glVertShader,\n fragment: glFragShader,\n },\n gpu: {\n vertex: {\n entryPoint: 'mainVert',\n source: gpuShader\n },\n fragment: {\n entryPoint: 'mainFrag',\n source: gpuShader\n }\n },\n resources: {\n uTexture: this.texture.source,\n uSampler: this.texture.source.style,\n uProgress: {\n progress: {value: 0.0, type: 'f32'},\n },\n },\n });\n const quadGeometry = new PIXI.Geometry({\n attributes: {\n aPosition: [\n -this.texture.width / 2,\n -this.texture.height / 2, // x, y\n this.texture.width / 2,\n -this.texture.height / 2, // x, y\n this.texture.width / 2,\n this.texture.width / 2, // x, y,\n -this.texture.width / 2,\n this.texture.width / 2, // x, y,\n ],\n aUV: [0, 0, 1, 0, 1, 1, 0, 1],\n aColor: [\n color.red, color.green, color.blue, color.alpha,\n color.red, color.green, color.blue, color.alpha,\n color.red, color.green, color.blue, color.alpha,\n color.red, color.green, color.blue, color.alpha\n ]\n },\n indexBuffer: [0, 1, 2, 0, 2, 3],\n });\n const quad = new PIXI.Mesh({\n geometry: quadGeometry,\n shader: this.shader,\n });\n this.addChild(quad);\n }\n\n public setProgress(progress: number) {\n this.shader.resources.uProgress.uniforms.progress = progress;\n }\n}\n","import {Screen} from \"../Screen\";\nimport {LoadAnim} from \"../../Elements/LoadAnim/LoadAnim\";\nimport * as PIXI from \"pixi.js\";\n\nexport class LoadScreen extends Screen {\n\n private loadAnim = new LoadAnim(\"rgba(255,255,255,0.7)\", \"black\");\n\n public start() {\n this.loadAnim.scale.set(0.8 * Screen.getScaleBasedOffScreenSize());\n this.loadAnim.position.set(this.getScreenWidth() - this.loadAnim.getWidth() - 15, this.getScreenHeight() - this.loadAnim.getHeight() - 15);\n this.addChild(this.loadAnim);\n }\n\n public draw(deltaTime: PIXI.Ticker) {\n this.loadAnim?.draw(deltaTime);\n }\n\n public onClose(): Promise {\n return new Promise((resolve) => {\n if (this.loadAnim != null) {\n this.loadAnim.destroy();\n }\n setTimeout(() => {\n resolve(this);\n }, 400);\n });\n }\n\n public onResize() {\n this.loadAnim.position.set(this.getScreenWidth() - this.loadAnim.getWidth() - 20, this.getScreenHeight() - this.loadAnim.getHeight() - 20);\n this.loadAnim.scale.set(0.8 * Screen.getScaleBasedOffScreenSize());\n }\n}\n","import {Screen} from \"../Screen\";\nimport * as PIXI from \"pixi.js\";\nimport {RandomBackground} from \"../../Elements/RandomBackground/RandomBackground\";\nimport {OsuLogo} from \"../../Elements/MainMenu/OsuCircle/OsuLogo\";\nimport {ButtonSystem} from \"../../Elements/MainMenu/OsuCircle/Menu/ButtonSystem\";\n\nexport class MainMenu extends Screen {\n private bg = new RandomBackground();\n private osuCircle = new OsuLogo();\n private menu: ButtonSystem = new ButtonSystem(this.osuCircle);\n\n public start() {\n this.bg.start();\n this.addChild(this.bg);\n this.osuCircle.scale = Screen.getScaleBasedOffScreenSize();\n this.addChild(this.menu);\n this.menu.onResize();\n this.addChild(this.osuCircle);\n }\n\n public draw(deltaTime: PIXI.Ticker) {\n this.bg.draw(deltaTime);\n this.osuCircle.draw(deltaTime);\n }\n\n public onClose(): Promise {\n return new Promise((resolve) => {\n this.bg.onClose().then(() => {\n resolve(this);\n });\n })\n }\n\n public onResize() {\n this.osuCircle.position.set(this.getScreenWidth() / 2, this.getScreenHeight() / 2);\n this.bg.onResize();\n this.menu.onResize();\n this.osuCircle.scale = !this.menu.isOpen() ? Screen.getScaleBasedOffScreenSize() :\n Screen.getScaleBasedOffScreenSize() * 0.5;\n }\n}\n","import * as PIXI from \"pixi.js\";\nimport {Settings} from \"../Settings/Settings\";\nimport {UIScale} from \"../Settings/impl/Graphics/UIScale\";\n\nexport abstract class Screen extends PIXI.Container {\n\n public constructor() {\n super();\n }\n\n public static getScaleBasedOffScreenSize() {\n // this was made with 1080p screens in mind.\n const uiScale = Settings.getSetting(UIScale).getValue();\n return ((((window.innerWidth / 1920) + (window.innerHeight / 1080)) / 2)) * uiScale\n }\n\n /**\n * Called once before the first frame is drawn\n */\n public abstract start(): void;\n\n\n /**\n * Called every frame\n */\n public abstract draw(deltaTime: PIXI.Ticker): void;\n\n /**\n * Called when screen will be closed, but has to return a promise to clean up after, for example, the screen's close animations are done.\n * Make sure you also pass in `this` into the promise's resolve.\n */\n public abstract onClose(): Promise;\n\n public abstract onResize(): void;\n\n protected getScreenWidth(): number {\n return window.innerWidth;\n }\n\n protected getScreenHeight(): number {\n return window.innerHeight;\n }\n}\n","import {Settings} from \"./Settings\";\n\nexport abstract class Setting {\n public readonly info: Settings;\n\n public constructor(SettingData: SettingInfo) {\n this.info = SettingData;\n Settings.register({setting: this, info: SettingData});\n }\n\n public abstract getValue(): any;\n\n public abstract getDefaultValue(): any;\n\n public abstract setValue(value: any): void;\n\n protected onValueChanged(): void {}\n\n /** When implementing this method, do **NOT** save the settings. This is so that loading won't reset most settings. */\n public abstract loadFromSaveValue(value: any): void;\n}\n\nexport interface SettingInfo {\n name: string;\n category: SettingsCategory;\n}\n\nexport enum SettingsCategory {\n General = \"General\",\n Skin = \"Skin\",\n Input = \"Input\",\n UserInterface = \"User Interface\",\n Gameplay = \"Gameplay\",\n Rulesets = \"Rulesets\",\n Audio = \"Audio\",\n Graphics = \"Graphics\",\n Online = \"Online\",\n Maintenance = \"Maintenance\",\n Debug = \"Debug\"\n}\n","import {Setting} from \"../Setting\";\nimport {Settings} from \"../Settings\";\n\nexport abstract class DropdownSetting extends Setting {\n public abstract readonly list: DropDownOption[];\n public abstract readonly defaultValue: DropDownOption;\n protected value: DropDownOption | undefined;\n\n public getValue(): DropDownOption {\n if (!this.value)\n throw new Error(\"Value is undefined!\");\n return this.value;\n }\n\n public getDefaultValue(): DropDownOption {\n return this.defaultValue;\n }\n\n public setValue(value: DropDownOption) {\n if (this.list.find((option) => option.value == value.value && option.displayName == value.displayName )) {\n this.value = value;\n Settings.save();\n this.onValueChanged();\n } else {\n console.warn('The value provided to this DropDownSetting does not exist in the option list! Ignoring value provided.');\n }\n }\n\n public loadFromSaveValue(value: DropDownOption) {\n if (this.list.find((option) => option.value == value.value && option.displayName == value.displayName)) {\n this.value = value;\n this.onValueChanged();\n } else {\n console.warn('The value provided to this DropDownSetting does not exist in the option list! Ignoring value provided.');\n }\n }\n}\n\nexport interface DropDownOption {\n displayName: string;\n value: string;\n}\n","import {Setting} from \"../Setting\";\nimport {Settings} from \"../Settings\";\nimport {MathUtil} from \"../../Util/MathUtil\";\n\nexport abstract class RangeSetting extends Setting {\n public abstract readonly minValue: number;\n public abstract readonly maxValue: number;\n public abstract readonly increment: number;\n public abstract readonly defaultValue: number;\n protected value: number = 0;\n\n public getValue(): number {\n return this.value;\n }\n\n public getDefaultValue(): number {\n return this.defaultValue;\n }\n\n public setValue(value: number) {\n this.value = MathUtil.clamp(this.minValue, this.maxValue, value);\n Settings.save();\n this.onValueChanged();\n }\n\n public loadFromSaveValue(value: number) {\n this.value = MathUtil.clamp(this.minValue, this.maxValue, value);\n this.onValueChanged();\n }\n}\n","import {Setting, SettingInfo} from \"./Setting\";\nimport {UIScale} from \"./impl/Graphics/UIScale\";\nimport {Renderer} from \"./impl/Graphics/Renderer\";\nimport {MouseSensitivity} from \"./impl/Input/MouseSensitivity\";\n\nexport class Settings {\n private static settingsList: SettingData[] = [];\n\n public static registerAll() {\n new UIScale();\n new Renderer();\n new MouseSensitivity();\n }\n\n public static load() {\n let settingSaveDataString = window.localStorage.getItem(\"settings\");\n if (settingSaveDataString == null) {\n return;\n }\n let settings = this.getList();\n try {\n let settingSaveData: SettingSaveData[] = JSON.parse(settingSaveDataString) as SettingSaveData[];\n settingSaveData.forEach((setting) => {\n let corrupt = false;\n try {\n if (!setting.value) {\n console.warn(\"Setting '\" + JSON.stringify(setting) + \"' may be corrupted, skipping!\");\n corrupt = true;\n }\n if (setting.info) {\n if (!setting.info.name) {\n console.warn(\"Setting '\" + JSON.stringify(setting) + \"' may be corrupted, skipping!\");\n corrupt = true;\n }\n if (!setting.info.category) {\n console.warn(\"Setting '\" + JSON.stringify(setting) + \"' may be corrupted, skipping!\");\n corrupt = true;\n }\n }\n else {\n console.warn(\"Setting '\" + JSON.stringify(setting) + \"' may be corrupted, skipping!\");\n corrupt = true;\n }\n }\n catch (e) {\n console.warn(\"Something went wrong when validating saved settings!\", e);\n console.warn(\"The setting may be REALLY corrupted, skipping!\");\n corrupt = true;\n }\n if (!corrupt) {\n let settingObj = settings.filter((_settingObj) => (_settingObj.info.name == setting.info.name) &&\n _settingObj.info.category == setting.info.category)[0];\n if (settingObj) {\n settingObj.setting.loadFromSaveValue(setting.value);\n } else {\n console.warn(\"Could not find setting object '\" + setting.info.name + \"', maybe it has been removed in this version of kosu?, skipping setting\")\n }\n }\n });\n }\n catch (e) {\n console.warn(\"Failed to load settings! Resetting Settings due to corrupted save!\", e);\n this.reset();\n }\n }\n\n public static save() {\n let settings = this.getList();\n let settingSaveData: SettingSaveData[] = [];\n settings.forEach((setting: SettingData) => {\n // only save if setting is different from default value\n if (setting.setting.getValue() != setting.setting.getDefaultValue()) {\n settingSaveData.push({info: setting.info, value: setting.setting.getValue()});\n }\n });\n window.localStorage.setItem(\"settings\", JSON.stringify(settingSaveData));\n }\n\n public static reset() {\n console.warn(\"Resetting Settings!\");\n window.localStorage.removeItem(\"settings\");\n }\n\n public static register(setting: SettingData) {\n this.settingsList.push(setting);\n }\n\n public static getSetting(setting: new (...args: any[]) => T): T {\n return this.settingsList.filter((_setting) => {\n return _setting.setting instanceof setting\n })[0].setting as T;\n }\n\n public static getSettingData(setting: new (...args: any[]) => T): SettingData {\n return this.settingsList.filter((_setting) => {\n return _setting.setting instanceof setting\n })[0];\n }\n\n public static getList() {\n return this.settingsList;\n }\n}\n\nexport interface SettingData {\n readonly setting: Setting;\n readonly info: SettingInfo;\n}\n\nexport interface SettingSaveData {\n readonly info: SettingInfo;\n readonly value: any;\n}\n","import {SettingsCategory} from \"../../Setting\";\nimport {DropDownOption, DropdownSetting} from \"../../SettingType/DropdownSetting\";\n\nexport class Renderer extends DropdownSetting {\n public readonly list: DropDownOption[] = [];\n\n public readonly webglOption: DropDownOption = {displayName: \"WebGL\", value: \"webgl\"}\n public readonly webGpuOption: DropDownOption = {displayName: \"WebGPU\", value: \"webgpu\"}\n public readonly defaultValue = this.webglOption;\n\n public constructor() {\n super({name: \"Renderer\", category: SettingsCategory.Graphics});\n this.list.push(this.webglOption, this.webGpuOption);\n this.value = this.defaultValue;\n }\n}\n","import {RangeSetting} from \"../../SettingType/RangeSetting\";\nimport {SettingsCategory} from \"../../Setting\";\n\nexport class UIScale extends RangeSetting {\n public readonly maxValue = 1.6;\n public readonly minValue = 0.8;\n public readonly increment = 0.1;\n public readonly defaultValue = 1;\n\n public constructor() {\n super({name: \"UI scaling\", category: SettingsCategory.Graphics});\n this.value = this.defaultValue;\n }\n}\n","import {RangeSetting} from \"../../SettingType/RangeSetting\";\nimport {SettingsCategory} from \"../../Setting\";\nimport {EventSystem} from \"pixi.js\";\n\nexport class MouseSensitivity extends RangeSetting{\n public readonly defaultValue: number = 1.0;\n public readonly increment: number = 0.01;\n public readonly maxValue: number = 10.0;\n public readonly minValue: number = 0.10;\n\n public constructor() {\n super({name: \"Sensitivity\", category: SettingsCategory.Input});\n this.value = this.defaultValue;\n this.onValueChanged();\n }\n\n public onValueChanged() {\n EventSystem.cursorSensitivity = this.getValue();\n }\n}\n","import {GeneralData} from \"./Sections/General/GeneralData\";\nimport {EditorData} from \"./Sections/Editor/EditorData\";\nimport {Metadata} from \"./Sections/Metadata/Metadata\";\nimport {DifficultyData} from \"./Sections/Difficulty/DifficultyData\";\nimport {EventsData} from \"./Sections/Events/EventsData\";\nimport {TimingPoint} from \"./Sections/TimingPoints/TimingPoint\";\nimport {TimingPointsData} from \"./Sections/TimingPoints/TimingPointsData\";\nimport {ColorsData} from \"./Sections/Colors/ColorsData\";\n\n/**\n * .osu (file format)\n */\nexport class BeatmapData {\n public files: Map = new Map();\n\n /**\n * General information about the beatmap\n */\n public General: GeneralData = new GeneralData();\n /**\n * Saved settings for the beatmap editor\n */\n public Editor: EditorData = new EditorData();\n /**\n * Information used to identify the beatmap\n */\n public Metadata: Metadata = new Metadata();\n /**\n * Difficulty settings\n */\n public Difficulty: DifficultyData = new DifficultyData();\n /**\n * Beatmap and storyboard graphic events\n */\n public Events: EventsData = new EventsData();\n /**\n * Timing and control points\n */\n public TimingPoints: TimingPointsData = new TimingPointsData();\n /**\n * Combo and skin colours\n */\n public Colors: ColorsData = new ColorsData();\n\n //TODO: add hitobject data\n\n}\n","import {Color} from \"./Color\";\n\n/**\n * \tCombo and skin colours\n */\nexport class ColorsData {\n public Colors: Color[] = [];\n}\n","/**\n * Difficulty settings\n */\nexport class DifficultyData {\n /**\n * HP setting (0–10)\n */\n public HPDrainRate!: number;\n /**\n * CS setting (0–10)\n */\n public CircleSize!: number;\n /**\n * OD setting (0–10)\n */\n public OverallDifficulty!: number;\n /**\n * AR setting (0–10)\n */\n public ApproachRate!: number;\n /**\n * Base slider velocity in hundreds of osu! pixels per beat\n */\n public SliderMultiplier!: number;\n /**\n * Amount of slider ticks per beat\n */\n public SliderTickRate!: number;\n}\n","/**\n * Saved settings for the beatmap editor\n */\nexport class EditorData {\n /**\n * Time in milliseconds of bookmarks\n */\n public Bookmarks: number[] = [];\n /**\n * Distance snap multiplier\n */\n public DistanceSpacing: number | undefined;\n /**\n * Beat snap divisor\n */\n public BeatDivisor: number | undefined;\n /**\n * Grid size\n */\n public GridSize: number | undefined;\n /**\n * Scale factor for the object timeline\n */\n public TimelineZoom: number | undefined;\n}\n","import {EventTypes} from \"./EventTypes\";\n\nexport class Event {\n /**\n * Type of the event. Some events may be referred to by either a name or a number.\n */\n public eventType!: EventTypes;\n /**\n * Start time of the event, in milliseconds from the beginning of the beatmap's audio. For events that do not use a start time, the default is 0.\n */\n public startTime: number = 0;\n}\n","import {Event} from \"./Event\";\nimport {EventTypes} from \"./EventTypes\";\nimport * as PIXI from \"pixi.js\";\n\nexport class EventBackground extends Event {\n public eventType = EventTypes.BACKGROUND;\n public startTime = 0;\n /**\n * Location of the background image relative to the beatmap directory. Double quotes are\n * usually included surrounding the filename, but they are not required.\n */\n public filename!: string;\n /**\n * Offset in osu! pixels from the centre of the screen.\n * For example, an offset of 50,100 would have the background shown 50 osu! pixels to the\n * right and 100 osu! pixels down from the centre of the screen. If the offset is 0,0, writing it is optional.\n */\n public xOffset!: number;\n /**\n * Offset in osu! pixels from the centre of the screen.\n * For example, an offset of 50,100 would have the background shown 50 osu! pixels to the\n * right and 100 osu! pixels down from the centre of the screen. If the offset is 0,0, writing it is optional.\n */\n public yOffset!: number;\n\n public texture?: PIXI.Texture;\n}\n","import {Event} from \"./Event\";\nimport {EventTypes} from \"./EventTypes\";\n\nexport class EventBreak extends Event {\n public eventType = EventTypes.BREAK;\n public endTime: number = 0;\n}","export enum EventTypes {\n BACKGROUND = \"0\",\n VIDEO = \"Video\",\n BREAK = \"Break\",\n // storyboard\n SPRITE = \"Sprite\",\n ANIMATION = \"Animation\"\n}\n","import {Event} from \"./Event\";\nimport {EventTypes} from \"./EventTypes\";\nimport * as PIXI from \"pixi.js\";\n\nexport class EventVideo extends Event {\n public eventType = EventTypes.VIDEO;\n /**\n * Location of the background video relative to the beatmap directory. Double quotes are\n * usually included surrounding the filename, but they are not required.\n */\n public filename!: string;\n /**\n * Offset in osu! pixels from the centre of the screen.\n * For example, an offset of 50,100 would have the background shown 50 osu! pixels to the\n * right and 100 osu! pixels down from the centre of the screen. If the offset is 0,0, writing it is optional.\n */\n public xOffset!: number;\n /**\n * Offset in osu! pixels from the centre of the screen.\n * For example, an offset of 50,100 would have the background shown 50 osu! pixels to the\n * right and 100 osu! pixels down from the centre of the screen. If the offset is 0,0, writing it is optional.\n */\n public yOffset!: number;\n\n\n public texture?: PIXI.Texture;\n}\n","import {Event} from \"./Event\";\n\n/**\n * Beatmap and storyboard graphic events\n */\nexport class EventsData {\n public Events: Event[] = [];\n}\n","export enum Countdown {\n NoCountdown = 0,\n Normal = 1,\n Half = 2,\n Double = 3\n}","import {Countdown} from \"./Countdown\";\nimport {SampleSet} from \"./SampleSet\";\nimport {Mode} from \"./Mode\";\nimport {OverlayPosition} from \"./OverlayPosition\";\n/**\n * General information about the beatmap\n */\nexport class GeneralData {\n\n public audioFile?: Blob;\n\n /**\n * Location of the audio file relative to the current folder.\n */\n public AudioFilename: string | null = null;\n /**\n * Milliseconds of silence before the audio starts playing\n */\n public AudioLeadIn: number = 0;\n /**\n * @deprecated The `AudioHash` property is deprecated according to the osu! wiki.\n */\n public AudioHash: string | null = null;\n /**\n * Time in milliseconds when the audio preview should start\n */\n public PreviewTime: number = -1;\n /**\n * Speed of the countdown before the first hit object (0 = no countdown, 1 = normal, 2 = half, 3 = double)\n */\n public Countdown: Countdown = Countdown.Normal;\n /**\n * Sample set that will be used if timing points do not override it (Normal, Soft, Drum)\n */\n public SampleSet: SampleSet = SampleSet.Normal;\n /**\n * Multiplier for the\n * threshold in time where hit objects placed close together stack (0–1)\n */\n public StackLeniency: number = 0.7;\n /**\n * Game mode (0 = osu!, 1 = osu!taiko, 2 = osu!catch, 3 = osu!mania)\n */\n public Mode: Mode = Mode.OSU;\n /**\n * Whether or not breaks have a letterboxing effect\n */\n public LetterboxInBreaks: boolean = false;\n /**\n * @deprecated The `StoryFireInFront` property is deprecated according to the osu! wiki.\n */\n public StoryFireInFront: boolean = true;\n /**\n * Whether or not the storyboard can use the user's skin images\n */\n public UseSkinSprites: boolean = false;\n /**\n * @deprecated The `AlwaysShowPlayfield` property is deprecated according to the osu! wiki.\n */\n public AlwaysShowPlayfield: boolean = false;\n /**\n * Draw order of hit circle overlays compared to hit numbers (NoChange = use skin setting,\n * Below = draw overlays under numbers, Above = draw overlays on top of numbers)\n */\n public OverlayPosition: OverlayPosition = OverlayPosition.NoChange;\n /**\n * Preferred skin to use during gameplay\n */\n public SkinPreference: string | null = null;\n /**\n * Whether or not a warning about flashing colours should be shown at the beginning of the map\n */\n public EpilepsyWarning: boolean = false;\n /**\n * Time in beats that the countdown starts before the first hit object\n */\n public CountdownOffset: number = 0;\n /**\n * Whether or not the \"N+1\" style key layout is used for osu!mania\n */\n public SpecialStyle: boolean = false;\n /**\n * Whether or not the storyboard allows widescreen viewing\n */\n public WidescreenStoryboard: boolean = false;\n /**\n * Whether or not sound samples will change rate when playing with speed-changing mods\n */\n public SamplesMatchPlaybackRate: boolean = false;\n}\n","export enum Mode {\n OSU = 0,\n TAIKO = 1,\n CATCH = 2,\n MANIA = 3\n}","export enum OverlayPosition {\n NoChange = \"NoChange\",\n Below = \"Below\",\n Above = \"Above\"\n}\n","export enum SampleSet {\n Normal = \"Normal\",\n Soft = \"Soft\",\n Drum = \"Drum\"\n}","/**\n * Information used to identify the beatmap\n */\nexport class Metadata {\n /**\n * Romanised song title\n */\n public Title!: string;\n /**\n * Song title\n */\n public TitleUnicode!: string;\n /**\n * Romanised song artist\n */\n public Artist!: string;\n /**\n * Song artist\n */\n public ArtistUnicode!: string;\n /**\n * Beatmap creator\n */\n public Creator!: string;\n /**\n * Difficulty name\n */\n public Version!: string;\n /**\n * Original media the song was produced for\n */\n public Source: string | undefined;\n /**\n * Search terms\n */\n public Tags!: string[];\n /**\n * Difficulty ID\n */\n public BeatmapID!: number;\n /**\n * Beatmap ID\n */\n public BeatmapSetID!: number;\n}\n","export enum Effect {\n KiaiTime = 1,\n None = 0,\n FirstBarLineOmittedInOsuTaikoAndOsuMania = 3\n}\n","import {TimingPoint} from \"./TimingPoint\";\n\nexport class InheritedTimingPoint extends TimingPoint {\n /**\n * a negative inverse slider velocity multiplier, as a percentage.\n * For example, `-50` would make all sliders in this timing section twice as fast as `SliderMultiplier`.\n */\n public sliderVelocityMultiplier!: number;\n\n}","import {TimingPointSampleSet} from \"./TimingPointSampleSet\";\nimport {Effect} from \"./Effect\";\n\nexport abstract class TimingPoint {\n /**\n * Start time of the timing section, in milliseconds from the beginning of the beatmap's audio.\n * The end of the timing section is the next timing point's time (or never, if this is the last timing point).\n */\n public time!: number;\n /**\n * Default sample set for hit objects (0 = beatmap default, 1 = normal, 2 = soft, 3 = drum).\n */\n public sampleSet!: TimingPointSampleSet;\n /**\n * Custom sample index for hit objects. 0 indicates osu!'s default hitsounds.\n */\n public sampleIndex!: number;\n /**\n * Volume percentage for hit objects.\n */\n public volume!: number;\n /**\n * Bit flags that give the timing point extra effects.\n * See the effects section.\n */\n public effects!: Effect\n}","import {TimingPoint} from \"./TimingPoint\";\nimport {UnInheritedTimingPoint} from \"./UnInheritedTimingPoint\";\nimport {InheritedTimingPoint} from \"./InheritedTimingPoint\";\n\n/**\n * Timing and control points\n */\nexport class TimingPointsData {\n public TimingPoints: TimingPoint[] = [];\n\n /**\n * Returns the current timing point in an array using the time provided.\n * If the current timing point is inherited, it will also return the parent\n * timing point along with it in the array as the second index.\n */\n public GetCurrentTimingPoints(time: number) {\n let toReturn: TimingPoint[] = [];\n let filter = this.TimingPoints.filter((timingPoint) => {if (timingPoint.time <= time) {return timingPoint}});\n if (filter.length == 0) {\n filter.push(this.TimingPoints[0]);\n }\n toReturn.push(filter[filter.length-1]);\n\n if (toReturn[0] instanceof InheritedTimingPoint) {\n let filter = this.TimingPoints.filter((timingPoint) => {return timingPoint instanceof UnInheritedTimingPoint})\n .filter((timingPoint) => {if (timingPoint.time <= time) {return timingPoint}});\n if (filter.length == 0) {\n throw new Error(\"Could not find a parent timing point for the un-inherited timing point!\");\n }\n toReturn.push(filter[filter.length-1]);\n }\n if (toReturn.length == 0) {\n throw new Error(\"Could not find any timing points!\");\n }\n return toReturn;\n }\n\n public GetCurrentUninheritedTimingPoint(time: number) {\n let timingPoint = this.GetCurrentTimingPoints(time);\n let unInheritedTimingPoint: UnInheritedTimingPoint;\n if (timingPoint[0] instanceof UnInheritedTimingPoint) {\n unInheritedTimingPoint = timingPoint[0];\n }\n else if(timingPoint[1] instanceof UnInheritedTimingPoint){\n unInheritedTimingPoint = timingPoint[1];\n }\n else {\n throw new Error(\"Could not find any UnInherited Timing Points!\")\n }\n return unInheritedTimingPoint;\n }\n\n}\n","import {TimingPoint} from \"./TimingPoint\";\n\nexport class UnInheritedTimingPoint extends TimingPoint {\n /**\n * The duration of a beat, in milliseconds.\n */\n public beatLength!: number;\n /**\n * Amount of beats in a measure.\n */\n public meter!: number;\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {TimingPointsParser} from \"./TimingPointsParser\";\nimport {GeneralParser} from \"./GeneralParser\";\nimport {EditorParser} from \"./EditorParser\";\nimport {MetadataParser} from \"./MetadataParser\";\nimport {DifficultyParser} from \"./DifficultyParser\";\nimport {EventsParser} from \"./EventsParser\";\n\nexport class BeatmapParser {\n public static Parse(osuFileContent: string, storyBoardFileContent?: string): BeatmapData {\n const beatMapData = new BeatmapData();\n let osuFileContentLines = osuFileContent.split(/\\r?\\n|\\r|\\n/g);\n GeneralParser.ParseGeneral(beatMapData, BeatmapParser.GetSection(\"General\", osuFileContentLines));\n EditorParser.ParseEditor(beatMapData, BeatmapParser.GetSection(\"Editor\", osuFileContentLines));\n MetadataParser.ParseMetadata(beatMapData, BeatmapParser.GetSection(\"Metadata\", osuFileContentLines));\n DifficultyParser.ParseDifficulty(beatMapData, BeatmapParser.GetSection(\"Difficulty\", osuFileContentLines));\n EventsParser.ParseEvents(beatMapData, BeatmapParser.GetSection(\"Events\", osuFileContentLines));\n TimingPointsParser.ParseTimingPoints(beatMapData, BeatmapParser.GetSection(\"TimingPoints\", osuFileContentLines));\n return beatMapData\n }\n\n public static async LoadFiles(beatMapData: BeatmapData) {\n await GeneralParser.LoadFiles(beatMapData);\n await EventsParser.LoadFiles(beatMapData);\n }\n\n public static GetSection(sectionName: string, osuFileContentLines: string[]) {\n let section: string[] = [];\n osuFileContentLines.forEach((str, index) => {\n if (str == \"[\" + sectionName + \"]\") {\n for (let i = index + 1; i < osuFileContentLines.length; i++) {\n if (osuFileContentLines[i] == \"\") {\n continue;\n }\n if (osuFileContentLines[i].startsWith(\"[\")) {\n break;\n }\n section.push(osuFileContentLines[i]);\n }\n }\n });\n return section;\n }\n\n public static AutoParse(sectionType: new (...args: any[]) => T, propValue: string[], beatmapDataSection: T) {\n let key = propValue[0] as keyof T;\n let keyExists = false;\n for (let sectionKey in beatmapDataSection) {\n if (sectionKey == key) {\n keyExists = true;\n }\n }\n if (!keyExists) {\n console.warn(key.toString() + \" does not exist on \" + sectionType.name + \"!\");\n return;\n }\n let isNumber = /^[0-9]+$|^[0-9]+.+$|^-[0-9]+$|^-[0-9]+.+$/.test(propValue[1]);\n let isBoolean = typeof beatmapDataSection[key] == \"boolean\";\n let value;\n if (isBoolean) {\n value = propValue[1] == \"1\";\n } else if (isNumber) {\n value = parseFloat(propValue[1]);\n } else {\n value = propValue[1];\n }\n\n // @ts-ignore\n beatmapDataSection[key] = value;\n }\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {BeatmapParser} from \"./BeatmapParser\";\nimport {DifficultyData} from \"../Data/Sections/Difficulty/DifficultyData\";\n\nexport class DifficultyParser {\n public static ParseDifficulty(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let propValue = str.split(\":\");\n if (propValue[1].startsWith(\" \")){\n propValue[1] = propValue[1].substring(1, propValue[1].length);\n }\n\n BeatmapParser.AutoParse(DifficultyData, propValue, beatmapData.Difficulty);\n });\n }\n\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {BeatmapParser} from \"./BeatmapParser\";\nimport {EditorData} from \"../Data/Sections/Editor/EditorData\";\n\nexport class EditorParser {\n public static ParseEditor(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let propValue = str.split(\":\");\n if (propValue[1].startsWith(\" \")){\n propValue[1] = propValue[1].substring(1, propValue[1].length);\n }\n if (propValue[0] != \"Bookmarks\") {\n BeatmapParser.AutoParse(EditorData, propValue, beatmapData.Editor);\n }\n else {\n propValue[1].split(\",\")\n .forEach((num) => {beatmapData.Editor.Bookmarks.push(parseFloat(num));});\n }\n });\n }\n\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {EventTypes} from \"../Data/Sections/Events/EventTypes\";\nimport {EventBackground} from \"../Data/Sections/Events/EventBackground\";\nimport {EventVideo} from \"../Data/Sections/Events/EventVideo\";\nimport {EventBreak} from \"../Data/Sections/Events/EventBreak\";\nimport { FFmpeg } from '@ffmpeg/ffmpeg';\nimport * as PIXI from \"pixi.js\";\nimport {Loader} from \"../../../Loader\";\n\nexport class EventsParser {\n public static aviTranscodedVideoCache: {beatmapSID: number, filePath: string, blob: Blob}[] = [];\n\n public static ParseEvents(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let values = str.split(\",\");\n let event;\n switch (values[0]) {\n case EventTypes.BACKGROUND:\n event = new EventBackground();\n event.filename = values[2].replaceAll('\"', \"\");\n event.xOffset = parseInt(values[3]);\n event.yOffset = parseInt(values[4]);\n if (isNaN(event.xOffset)) {\n event.xOffset = 0;\n }\n if (isNaN(event.yOffset)) {\n event.yOffset = 0;\n }\n break;\n case EventTypes.VIDEO:\n case \"1\":\n event = new EventVideo();\n event.startTime = parseInt(values[1]);\n event.filename = values[2].replaceAll('\"', \"\");\n event.xOffset = parseInt(values[3]);\n event.yOffset = parseInt(values[4]);\n if (isNaN(event.xOffset)) {\n event.xOffset = 0;\n }\n if (isNaN(event.yOffset)) {\n event.yOffset = 0;\n }\n break;\n case EventTypes.BREAK:\n case \"2\":\n event = new EventBreak();\n event.startTime = parseInt(values[1]);\n event.endTime = parseInt(values[2]);\n break;\n }\n if (event) {\n beatmapData.Events.Events.push(event);\n }\n });\n }\n\n public static async LoadFiles(beatmapData: BeatmapData) {\n for (const event of beatmapData.Events.Events) {\n for (let eventKey in event) {\n if (eventKey == \"filename\" || eventKey == \"filepath\") {\n // @ts-ignore\n let file = beatmapData.files.get(event[eventKey]);\n if (file) {\n let url = URL.createObjectURL(file);\n if (event instanceof EventBackground) {\n try {\n event.texture = await PIXI.Assets.load({src: url, loadParser: \"loadTextures\"});\n } catch (e) {\n console.warn(e);\n }\n }\n if (event instanceof EventVideo) {\n let failed = false;\n // @ts-ignore\n if (event[eventKey].endsWith(\".avi\")) {\n // @ts-ignore\n let cacheHit = this.aviTranscodedVideoCache.find(\n (cache) => {\n // @ts-ignore\n if (cache.beatmapSID == beatmapData.Metadata.BeatmapSetID && cache.filePath == event[eventKey]) {\n return cache;\n }\n }\n );\n try {\n if (!cacheHit) {\n console.warn(\"AVI video is not natively supported! Transcoding to .mp4, this may take a few minutes!\");\n let ffmpeg = new FFmpeg();\n ffmpeg.on('progress', ({progress, time}) => {\n console.log(`.avi to .mp4 transcoding: ${Math.round(progress * 1000) / 10}% (transcoded time: ${Math.round(time / 100000) / 10}s)`);\n });\n console.log(\"FFmpeg initialized\");\n const baseURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm';\n let classWorker = Loader.Get(\"workers.ffmpeg\");\n let core = Loader.Get(\"ffmpeg.core\");\n let wasm = Loader.Get(\"ffmpeg.wasm\");\n let worker = Loader.Get(\"ffmpeg.coreWorker\");\n await ffmpeg.load({\n classWorkerURL: URL.createObjectURL(classWorker),\n coreURL: URL.createObjectURL(core),\n wasmURL: URL.createObjectURL(wasm),\n workerURL: URL.createObjectURL(worker)\n });\n console.log(\"FFmpeg loaded\");\n await ffmpeg.writeFile('input.avi', new Uint8Array(await file.arrayBuffer()));\n console.log(\"Written file to FFmpeg's vfs\");\n await ffmpeg.exec([\"-i\", \"input.avi\", \"-c:v\", \"libx264\", \"-preset\",\n \"ultrafast\", \"-an\", \"-movflags\", \"faststart\", \"output.mp4\"]);\n console.log(\"Transcoding done\");\n const data = await ffmpeg.readFile(\"output.mp4\");\n ffmpeg.terminate();\n console.log(\"FFmpeg terminated\");\n let newFile = new Blob([data], {type: 'video/mp4'});\n this.aviTranscodedVideoCache.push({\n beatmapSID: beatmapData.Metadata.BeatmapSetID,\n // @ts-ignore\n filePath: event[eventKey],\n blob: newFile\n });\n // @ts-ignore\n beatmapData.files.delete(event[eventKey]);\n // @ts-ignore\n event[eventKey] = event[eventKey].substring(0, event[eventKey].length - 4) + \".mp4\";\n // @ts-ignore\n beatmapData.files.set(event[eventKey], newFile);\n URL.revokeObjectURL(url);\n url = URL.createObjectURL(newFile);\n console.log(\"Successfully transcoded from .avi to .mp4!\");\n } else {\n // @ts-ignore\n beatmapData.files.delete(event[eventKey]);\n // @ts-ignore\n event[eventKey] = event[eventKey].substring(0, event[eventKey].length - 4) + \".mp4\";\n // @ts-ignore\n beatmapData.files.set(event[eventKey], cacheHit.blob);\n URL.revokeObjectURL(url);\n url = URL.createObjectURL(cacheHit.blob);\n }\n } catch (e) {\n console.warn(e);\n failed = true;\n }\n }\n if (!failed) {\n try {\n event.texture = await PIXI.Assets.load({src: url, loadParser: \"loadVideo\"});\n if (event.texture) {\n event.texture.source.resource.volume = 0;\n event.texture.source.resource.pause();\n }\n } catch (e) {\n console.warn(e);\n }\n }\n }\n } else {\n // @ts-ignore\n console.warn(\"Could not find referenced file: \" + event[eventKey]);\n }\n }\n }\n }\n }\n}","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {GeneralData} from \"../Data/Sections/General/GeneralData\";\nimport {BeatmapParser} from \"./BeatmapParser\";\n\nexport class GeneralParser {\n public static ParseGeneral(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let propValue = str.split(\":\");\n if (propValue[1].startsWith(\" \")) {\n propValue[1] = propValue[1].substring(1, propValue[1].length);\n }\n\n BeatmapParser.AutoParse(GeneralData, propValue, beatmapData.General);\n });\n }\n\n public static async LoadFiles(beatmapData: BeatmapData) {\n if (beatmapData.General.AudioFilename) {\n beatmapData.General.audioFile = beatmapData.files.get(beatmapData.General.AudioFilename);\n }\n }\n\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {BeatmapParser} from \"./BeatmapParser\";\nimport {Metadata} from \"../Data/Sections/Metadata/Metadata\";\n\nexport class MetadataParser {\n public static ParseMetadata(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let propValue = str.split(\":\");\n if (propValue[1].startsWith(\" \")){\n propValue[1] = propValue[1].substring(1, propValue[1].length);\n }\n\n BeatmapParser.AutoParse(Metadata, propValue, beatmapData.Metadata);\n });\n }\n\n}\n","import {BeatmapData} from \"../Data/BeatmapData\";\nimport {UnInheritedTimingPoint} from \"../Data/Sections/TimingPoints/UnInheritedTimingPoint\";\nimport {InheritedTimingPoint} from \"../Data/Sections/TimingPoints/InheritedTimingPoint\";\nimport {Effect} from \"../Data/Sections/TimingPoints/Effect\";\n\nexport class TimingPointsParser {\n public static ParseTimingPoints(beatmapData: BeatmapData, section: string[]) {\n section.forEach((str) => {\n let prop = str.split(\",\");\n let timingPoint;\n if (prop[6] == \"1\") {\n timingPoint = new UnInheritedTimingPoint();\n timingPoint.beatLength = Number.parseFloat(prop[1]);\n timingPoint.meter = Number.parseInt(prop[2]);\n }\n else {\n timingPoint = new InheritedTimingPoint();\n timingPoint.sliderVelocityMultiplier = Number.parseFloat(prop[1]);\n }\n timingPoint.time = Number.parseInt(prop[0]);\n timingPoint.sampleSet = Number.parseInt(prop[3]);\n timingPoint.sampleIndex = Number.parseInt(prop[4]);\n timingPoint.volume = Number.parseInt(prop[5]);\n if (prop[7] == \"1\" || prop[7] == \"3\"){\n timingPoint.effects = Number.parseInt(prop[7]);\n } else {\n timingPoint.effects = Effect.None;\n }\n\n beatmapData.TimingPoints.TimingPoints.push(timingPoint);\n });\n }\n}\n","export class MathUtil {\n public static RadiansToDegrees(radians: number) {\n return radians * 180 / Math.PI;\n }\n\n public static DegreesToRadians(degrees: number) {\n return degrees * Math.PI / 180;\n }\n\n public static clamp(min: number, max: number, value: number) {\n return Math.min(Math.max(value, min), max);\n }\n\n public static clamp01(value: number) {\n return MathUtil.clamp(0, 1, value);\n }\n\n public static Damp(start: number, final: number, base: number, exponent: number) {\n return MathUtil.Lerp(start, final, 1 - Math.pow(base, exponent));\n }\n\n public static Lerp(start: number, final: number, ammount: number) {\n return start + (final - start) * ammount;\n }\n\n}\n","import * as TWEEN from \"@tweenjs/tween.js\";\nimport * as PIXI from \"pixi.js\";\n\nexport class Ease {\n private static previousEases: Ease[] = [];\n private easings: Easing[] = [];\n private readonly obj: PIXI.Container;\n private delay: TWEEN.Tween | null = null;\n\n private constructor(obj: PIXI.Container, dontStore: boolean) {\n this.obj = obj;\n if (!dontStore) {\n Ease.previousEases.push(this);\n }\n }\n\n public static getEase(obj: PIXI.Container, dontStore?: boolean) {\n if (dontStore == null) {\n dontStore = false;\n }\n let checkIfEaseExists = Ease.previousEases.filter((ease) => {\n return ease.obj == obj;\n });\n if (checkIfEaseExists.length > 0) {\n return checkIfEaseExists[0];\n }\n return new Ease(obj, dontStore);\n }\n\n public createTween>(value: T, newValue: T, isPrimitive: boolean, property: keyof PIXI.Container, duration: number, easingFunc: (ammount: number) => number) {\n const tweenValue = {value: 0}\n const tween = new TWEEN.Tween(isPrimitive ? tweenValue : value);\n const easing = new Easing(tween);\n tween.to(isPrimitive ? {value: 1} : newValue, duration);\n tween.easing(easingFunc);\n tween.onUpdate(() => {\n if (!this.obj.destroyed) {\n if (!isPrimitive) {\n // @ts-ignore\n this.obj[property] = value;\n } else {\n // @ts-ignore\n this.obj[property] = (tweenValue.value * (newValue.value - value.value)) + value.value;\n }\n }\n easing.onUpdate();\n });\n\n tween.onStart(() => {\n if (isPrimitive) {\n // @ts-ignore\n value.value = this.obj[property];\n }\n });\n\n\n if (this.delay == null) {\n\n tween.start();\n } else {\n this.delay.chain(tween);\n this.delay = null;\n }\n this.easings.push(easing);\n\n tween.onStop(() => {\n this.onDone(tween);\n });\n tween.onComplete(() => {\n this.onDone(tween);\n });\n return this;\n }\n\n public TransformTo(newPosition: PIXI.PointData, duration: number, easing: (ammount: number) => number) {\n this.createTween(this.obj.position, newPosition, false, \"position\", duration, easing);\n return this;\n }\n\n private onDone(tween: TWEEN.Tween) {\n this.easings = this.easings.filter((tweenInArray) => {\n return tweenInArray.tween != tween\n })\n }\n\n public ScaleTo(newScale: PIXI.PointData | number, duration: number, easing: (ammount: number) => number) {\n let _newScale: PIXI.PointData = {x: 0, y: 0};\n if (typeof newScale == \"number\") {\n _newScale.x = newScale;\n _newScale.y = newScale;\n }\n this.createTween(this.obj.scale, _newScale, false, \"scale\", duration, easing);\n return this;\n }\n\n public FadeTo(newAlpha: number, duration: number, easing: (ammount: number) => number) {\n this.createTween({value: this.obj.alpha}, {value: newAlpha}, true, \"alpha\", duration, easing);\n return this;\n }\n\n public FadeOut(duration: number, easing: (ammount: number) => number) {\n this.FadeTo(0, duration, easing);\n return this;\n }\n\n public FadeIn(duration: number, easing: (ammount: number) => number) {\n this.FadeTo(1, duration, easing);\n return this;\n }\n\n public ClearEasings() {\n this.easings.forEach((tween) => {\n tween.tween.stop();\n });\n this.easings = [];\n return this;\n }\n\n public Then(cb?: () => void) {\n let largestDuration = this.easings.sort((a, b) => {\n return a.tween.getDuration() - b.tween.getDuration()\n });\n if (largestDuration.length > 0) {\n this.delay = largestDuration[0].tween;\n if (cb != undefined) {\n largestDuration[0].tween.onComplete(() => {this.onDone(largestDuration[0].tween); cb();});\n largestDuration[0].tween.onStop(() => {this.onDone(largestDuration[0].tween); cb();});\n }\n }\n return this;\n }\n\n public OnEach(cb: () => void) {\n let largestDuration = this.easings.sort((a, b) => {\n return a.tween.getDuration() - b.tween.getDuration()\n });\n if (largestDuration.length > 0) {\n largestDuration[0].registerOnUpdate(cb);\n }\n }\n}\n\nclass Easing {\n public tween: TWEEN.Tween;\n private updateEventListeners: (() => void)[] = [];\n public constructor(tween: TWEEN.Tween) {\n this.tween = tween;\n }\n public onUpdate() {\n this.updateEventListeners.forEach((eventListener) => {\n eventListener();\n })\n }\n public registerOnUpdate(cb: () => void) {\n this.updateEventListeners.push(cb);\n }\n public unRegisterOnUpdate(cb: () => void) {\n this.updateEventListeners = this.updateEventListeners.filter((ev) => {return !(cb === ev);});\n }\n}\n","import {List} from \"@pixi/ui\";\nimport {UIUtils} from \"./UIUtils\";\n\nexport class CenteredList extends List {\n public get elementsMargin() {\n return super.elementsMargin;\n }\n public set elementsMargin(margin: number) {\n super.elementsMargin = margin;\n UIUtils.centerPivotOfList(this);\n }\n\n\n public ReCenter() {\n UIUtils.centerPivotOfList(this);\n }\n}\n","import {List} from \"@pixi/ui\";\n\nexport class UIUtils {\n public static centerPivotOfList(list: List) {\n let width = list.leftPadding;\n let height = list.topPadding;\n for (let i = 0; i < list.children.length; i++) {\n let isLast = i + 1 == list.children.length;\n switch (list.type) {\n case \"horizontal\":\n width += list.children[i].width + (!isLast? list.elementsMargin : 0);\n height += list.children[i].height;\n break;\n case \"vertical\":\n width += list.children[i].width;\n height += list.children[i].height + (!isLast? list.elementsMargin : 0);\n break;\n default:\n width += list.children[i].width + (!isLast? list.elementsMargin : 0);\n height += list.children[i].height + (!isLast? list.elementsMargin : 0);\n break;\n }\n }\n switch (list.type) {\n case \"horizontal\":\n height /= list.children.length;\n break;\n case \"vertical\":\n width /= list.children.length;\n break;\n }\n width += list.rightPadding;\n height += list.bottomPadding;\n\n list.pivot.set(width/2, height/2);\n }\n}\n","import \"./style.css\";\nimport {Application, EventSystem} from \"pixi.js\";\nimport {Main} from \"./main\";\nimport {Settings} from \"./Settings/Settings\";\nimport {Renderer} from \"./Settings/impl/Graphics/Renderer\";\nimport {MouseSensitivity} from \"./Settings/impl/Input/MouseSensitivity\";\nimport {UIScale} from \"./Settings/impl/Graphics/UIScale\";\nSettings.registerAll();\nSettings.load();\nconst gameWidth = window.innerWidth;\nconst gameHeight = window.innerHeight;\n\nconst app = new Application();\n// @ts-ignore\nglobalThis.__PIXI_APP__ = app;\nwindow.onload = async (): Promise => {\n // @ts-ignore\n const renderer = Settings.getSetting(Renderer).getValue().value as \"webgl\" | \"webgpu\";\n app.init({\n backgroundColor: \"black\",\n width: gameWidth,\n height: gameHeight,\n antialias: true,\n preference: renderer,\n resolution: window.devicePixelRatio,\n autoDensity: true\n }).then(() => {\n new Main(app);\n });\n};\n\nnavigator.mediaSession.setActionHandler('play', () => {Main.AudioEngine.GetCurrentPlayingMusicNoSilent()?.Play();});\nnavigator.mediaSession.setActionHandler('pause', () => {Main.AudioEngine.GetCurrentPlayingMusicNoSilent()?.Pause();});\nnavigator.mediaSession.setActionHandler('stop', () => {});\nnavigator.mediaSession.setActionHandler('seekbackward', () => {});\nnavigator.mediaSession.setActionHandler('seekforward', () => {});\nnavigator.mediaSession.setActionHandler('seekto', () => {});\nnavigator.mediaSession.setActionHandler('previoustrack', () => {});\nnavigator.mediaSession.setActionHandler('nexttrack', () => {});\n\nObject.defineProperty(window, \"setSensitivity\", {value: (sensitivity: number) => {\n Settings.getSetting(MouseSensitivity).setValue(sensitivity);\n}});\n\nObject.defineProperty(window, \"setRenderer\", {value: (renderer: string) => {\n let rendererSetting = Settings.getSetting(Renderer);\n rendererSetting.setValue(renderer == \"webgl\" ? rendererSetting.webglOption : rendererSetting.webGpuOption);\n window.location.reload();\n}});\n\nObject.defineProperty(window, \"setUIScale\", {value: (scale: number) => {\n Settings.getSetting(UIScale).setValue(scale);\n window.location.reload();\n}});\n","import * as PIXI from \"pixi.js\";\nimport {Application} from \"pixi.js\";\nimport {Screen} from \"./Screens/Screen\";\nimport {LoadScreen} from \"./Screens/LoadScreen/LoadScreen\";\nimport {InteractScreen} from \"./Screens/InteractScreen/InteractScreen\";\nimport {Loader} from \"./Loader\";\nimport {MenuCursor} from \"./Elements/MenuCursor/MenuCursor\";\nimport {AudioEngine} from \"./Audio/AudioEngine\";\nimport * as TWEEN from \"@tweenjs/tween.js\";\nimport {SettingsPane} from \"./Elements/Settings/SettingsPane\";\nimport {unzip} from \"unzipit\";\nimport {BeatmapParser} from \"./Util/Beatmap/Parser/BeatmapParser\";\n\nexport class Main {\n public static app: Application;\n public static mousePos = {x: 0, y: 0};\n public static pointerLockExitTime: number;\n public static cursor: MenuCursor;\n public static AudioEngine: AudioEngine;\n private static currentScreen: Screen | null;\n private static allScreens: Screen[] = [];\n private static clickArea: PIXI.Graphics = new PIXI.Graphics();\n private static doPointerLock: boolean = false;\n private static settingsPane: SettingsPane;\n private static processingOsuFile: boolean = false;\n\n public constructor(app: Application) {\n Main.app = app;\n // for testing purposes\n Main.setDropEvents();\n\n document.body.appendChild(Main.app.canvas);\n\n Main.settingsPane = new SettingsPane();\n Main.settingsPane.zIndex = 999998;\n Main.app.stage.addChild(Main.settingsPane);\n\n document.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (e.ctrlKey && e.code == \"KeyO\") {\n Main.settingsPane.toggle();\n }\n });\n\n this.doResize();\n window.addEventListener(\"resize\", this.doResize);\n Main.app.ticker.add(() => {\n TWEEN.update();\n })\n Main.app.stage.eventMode = \"static\";\n Main.AudioEngine = new AudioEngine();\n Main.app.stage.addEventListener(\"mousemove\", (e) => {\n Main.mousePos.x = e.clientX;\n Main.mousePos.y = e.clientY;\n if (Main.cursor) {\n Main.cursor.updateMouse();\n }\n });\n document.addEventListener(\"pointerlockchange\", this.pointerLockChanged, false);\n Main.switchScreen(new LoadScreen());\n Loader.Load(Main.AudioEngine.audioContext).then(() => {\n Main.cursor = new MenuCursor(false);\n let dialogOk = Loader.GetAudio(\"sample_dialog_ok\");\n let introTrack = Loader.Get(\"introTrianglesTrack\");\n Main.switchScreen(new InteractScreen(introTrack, dialogOk));\n });\n }\n\n // for testing purposes\n private static setDropEvents() {\n Object.defineProperty(window, \"onDropEvent\", {\n value: (e: DragEvent) => {\n e.preventDefault();\n if (Main.processingOsuFile) {\n alert(\"Another BeatMap is still processing. (Most likely transcoding a .avi file, check the console for progress) \" +\n \"Please wait for it to process and start playing before processing another one!\");\n return;\n }\n Main.processingOsuFile = true;\n if (e.dataTransfer!.items) {\n let item = [...e.dataTransfer!.items][0];\n if (item.kind == \"file\") {\n\n const file = item.getAsFile()!;\n unzip(file).then(({entries}) => {\n for (const [name, entry] of Object.entries(entries)) {\n if (name.endsWith(\".osu\")) {\n entry.text().then(async (osuFile) => {\n let beatmapData = BeatmapParser.Parse(osuFile);\n for (const [name, entry] of Object.entries(entries)) {\n let blob = await entry.blob();\n beatmapData.files.set(name, blob);\n }\n await BeatmapParser.LoadFiles(beatmapData);\n let audioFile = beatmapData.General.audioFile;\n if (audioFile) {\n let url = URL.createObjectURL(audioFile);\n Main.AudioEngine.PlayMusicImmediately(url, beatmapData, () => {\n console.log(\"Now playing \" + beatmapData.Metadata.TitleUnicode + \" - \" + beatmapData.Metadata.ArtistUnicode +\n \" (\" + beatmapData.Metadata.Title + \" - \" + beatmapData.Metadata.Artist + \")\");\n });\n }\n Main.processingOsuFile = false;\n console.log(beatmapData);\n });\n break;\n }\n }\n });\n\n }\n }\n }\n });\n\n Object.defineProperty(window, \"onDragEvent\", {\n value: (e: DragEvent) => {\n e.preventDefault();\n }\n });\n Main.app.canvas.setAttribute(\"ondrop\", \"window.onDropEvent(event);\");\n Main.app.canvas.setAttribute(\"ondragover\", \"window.onDragEvent(event);\");\n }\n\n public static lockKeyboard() {\n // @ts-ignore\n if (navigator.keyboard) {\n // @ts-ignore\n navigator.keyboard.lock([]).then(() => {\n console.log(\"Locked keyboard!\");\n if (!document.fullscreenElement) {\n console.warn(\"Keyboard lock won't work unless the user is in fullscreen (as requested by the game, not if the user just presses F11)!\");\n }\n });\n }\n }\n\n public static pointerLock() {\n try {\n this.doPointerLock = true;\n // @ts-ignore\n Main.app.canvas.requestPointerLock({\n unadjustedMovement: true,\n });\n } catch (e) {\n console.warn(\"Failed to lock cursor, error:\", e);\n this.doPointerLock = false;\n }\n\n }\n\n public static exitPointerLock() {\n this.doPointerLock = false;\n // @ts-ignore\n Main.app.canvas.exitPointerLock();\n }\n\n public static switchScreen(screen: Screen) {\n if (this.currentScreen != null) {\n this.currentScreen.zIndex = 1;\n this.currentScreen.onClose().then((lastScreen) => {\n for (let i = 0; i < this.allScreens.length; i++) {\n if (this.allScreens[i] == lastScreen) {\n this.allScreens.splice(i, 1);\n }\n }\n Main.app.ticker.remove(lastScreen.draw);\n Main.app.stage.removeChild(lastScreen);\n lastScreen.destroy();\n });\n }\n Main.app.stage.addChild(screen);\n this.allScreens.push(screen);\n this.currentScreen = screen;\n screen.start();\n screen.onResize();\n Main.app.ticker.add(screen.draw, screen);\n }\n\n public doResize(): void {\n Main.app.renderer.resize(window.innerWidth, window.innerHeight);\n Main.app.stage.scale.x = 1;\n Main.app.stage.scale.y = 1;\n if (!Main.clickArea.destroyed) {\n Main.clickArea.width = window.innerWidth;\n Main.clickArea.height = window.innerHeight;\n Main.clickArea.position.set(0, 0);\n }\n Main.allScreens.forEach((screen) => {\n screen.onResize();\n })\n Main.settingsPane.resize();\n }\n\n private pointerLockChanged(): void {\n if (!document.pointerLockElement && Main.doPointerLock) {\n PIXI.EventSystem.isPointerLocked = false;\n Main.pointerLockExitTime = Date.now();\n Main.clickArea = new PIXI.Graphics();\n Main.clickArea.rect(0, 0, 1, 1);\n Main.clickArea.fill(\"rgba(0,0,0,0.1)\");\n Main.clickArea.width = window.innerWidth;\n Main.clickArea.height = window.innerHeight;\n Main.clickArea.position.set(0, 0);\n Main.app.stage.addChild(Main.clickArea);\n Main.clickArea.eventMode = \"static\";\n Main.clickArea.cursor = \"pointer\";\n Main.cursor.PopOut();\n Main.clickArea.zIndex = 9999999;\n Main.clickArea.onclick = () => {\n if (Date.now() - Main.pointerLockExitTime < 1500) {\n return;\n }\n Main.clickArea.removeFromParent();\n Main.clickArea.destroy();\n Main.pointerLock();\n Main.cursor.PopIn();\n }\n } else {\n PIXI.EventSystem.isPointerLocked = true;\n }\n }\n\n}\n","export default \"in vec2 vUV;\\nin vec2 vPositionOffset;\\nin vec2 vPosition;\\nin vec4 vColorTint;\\nuniform sampler2D uTexture;\\nuniform float time;\\n\\nvoid main() {\\n float a = ((vPositionOffset.y + vPosition.y)/1200.0) - 0.1;\\n vec4 color = texture(uTexture, vUV);\\n if (a > 1.0) {\\n a = 1.0;\\n }\\n gl_FragColor = (color*vColorTint)*a;\\n}\";","export default \"in vec2 aPosition;\\nin vec2 aUV;\\nin vec2 aPositionOffset;\\nin vec4 aColorTint;\\n\\nout vec2 vUV;\\nout vec2 vPositionOffset;\\nout vec2 vPosition;\\nout vec4 vColorTint;\\n\\nuniform mat3 uProjectionMatrix;\\nuniform mat3 uWorldTransformMatrix;\\nuniform mat3 uTransformMatrix;\\n\\n\\nvoid main() {\\n\\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\\n gl_Position = vec4((mvp * vec3(aPosition + aPositionOffset, 1.0)).xy, 0.0, 1.0);\\n vPositionOffset = aPositionOffset;\\n vUV = aUV;\\n vPosition = aPosition;\\n vColorTint = aColorTint;\\n}\";","export default \"struct GlobalUniforms {\\n uProjectionMatrix:mat3x3,\\n uWorldTransformMatrix:mat3x3,\\n uWorldColorAlpha: vec4,\\n uResolution: vec2,\\n}\\n\\nstruct LocalUniforms {\\n uTransformMatrix:mat3x3,\\n uColor:vec4,\\n uRound:f32,\\n}\\n\\n\\n@group(0) @binding(0) var globalUniforms : GlobalUniforms;\\n@group(1) @binding(0) var localUniforms : LocalUniforms;\\n\\nstruct VertexOutput {\\n @builtin(position) position: vec4,\\n @location(0) vUV: vec2,\\n @location(1) vPositionOffset: vec2,\\n @location(2) vPosition: vec2,\\n @location(3) vColorTint: vec4\\n};\\n\\n\\n@vertex\\nfn mainVert(\\n @location(0) aPosition : vec2,\\n @location(1) aUV : vec2,\\n @location(2) aColorTint : vec4,\\n @location(3) aPositionOffset : vec2,\\n) -> VertexOutput {\\n var mvp = globalUniforms.uProjectionMatrix\\n * globalUniforms.uWorldTransformMatrix\\n * localUniforms.uTransformMatrix;\\n\\n var output: VertexOutput;\\n\\n output.position = vec4(mvp * vec3(aPosition+aPositionOffset, 1.0), 1.0);\\n output.vUV = aUV;\\n output.vPosition = aPosition;\\n output.vPositionOffset = aPositionOffset;\\n output.vColorTint = aColorTint;\\n\\n return output;\\n};\\n\\nstruct WaveUniforms {\\n time:f32,\\n}\\n\\n@group(2) @binding(1) var uTexture : texture_2d;\\n@group(2) @binding(2) var uSampler : sampler;\\n@group(2) @binding(3) var waveUniforms : WaveUniforms;\\n\\n@fragment\\nfn mainFrag(\\n @location(0) vUV: vec2,\\n @location(1) vPositionOffset: vec2,\\n @location(2) vPosition: vec2,\\n @location(3) vColorTint: vec4\\n) -> @location(0) vec4 {\\n var a: f32 = ((vPositionOffset.y + vPosition.y)/1200.0) - 0.1;\\n let color: vec4 = textureSample(uTexture, uSampler, vUV);\\n if (a > 1.0){\\n a = 1.0;\\n }\\n return (color*vColorTint)*a;\\n};\";","export default \"in vec4 vColor;\\nin vec2 vUV;\\n\\nuniform sampler2D uTexture;\\nuniform float progress;\\n\\nvoid main() {\\n vec4 color = texture2D(uTexture, vUV);\\n float a = vColor.a * color.a;\\n vec4 _vColor = vec4(smoothstep(0.88, 1.0, color.a))*vColor;\\n vec4 outColor = (color.r < progress) ? vec4(_vColor.rgb * a, a) : vec4(0.0);\\n gl_FragColor = outColor;\\n}\\n\";","export default \"in vec2 aPosition;\\nin vec4 aColor;\\nin vec2 aUV;\\n\\nout vec4 vColor;\\nout vec2 vUV;\\n\\nuniform mat3 uProjectionMatrix;\\nuniform mat3 uWorldTransformMatrix;\\n\\nuniform mat3 uTransformMatrix;\\n\\n\\nvoid main() {\\n\\n mat3 mvp = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\\n gl_Position = vec4((mvp * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\\n\\n vColor = aColor;\\n vUV = aUV;\\n}\\n\";","export default \"struct GlobalUniforms {\\n uProjectionMatrix:mat3x3,\\n uWorldTransformMatrix:mat3x3,\\n uWorldColorAlpha: vec4,\\n uResolution: vec2,\\n}\\n\\nstruct LocalUniforms {\\n uTransformMatrix:mat3x3,\\n uColor:vec4,\\n uRound:f32,\\n}\\n\\n\\n@group(0) @binding(0) var globalUniforms : GlobalUniforms;\\n@group(1) @binding(0) var localUniforms : LocalUniforms;\\n\\nstruct VertexOutput {\\n @builtin(position) position: vec4,\\n @location(0) vUV: vec2,\\n @location(1) vColor: vec4,\\n};\\n\\n\\n@vertex\\nfn mainVert(@location(0) aPosition : vec2, @location(1) aUV : vec2, @location(2) aColor: vec4\\n) -> VertexOutput {\\n var mvp = globalUniforms.uProjectionMatrix\\n * globalUniforms.uWorldTransformMatrix\\n * localUniforms.uTransformMatrix;\\n\\n var output: VertexOutput;\\n\\n output.position = vec4(mvp * vec3(aPosition, 1.0), 1.0);\\n output.vUV = aUV;\\n output.vColor = aColor;\\n\\n return output;\\n};\\n\\nstruct ProgressUniform {\\n progress:f32\\n}\\n\\n@group(2) @binding(1) var uTexture : texture_2d;\\n@group(2) @binding(2) var uSampler : sampler;\\n@group(2) @binding(3) var uProgress : ProgressUniform;\\n\\n@fragment\\nfn mainFrag(@location(0) vUV: vec2, @location(1) vColor: vec4) -> @location(0) vec4 {\\n let color: vec4 = textureSample(uTexture, uSampler, vUV);\\n let a: f32 = color.a;\\n let _vColor: vec4 = smoothstep(0.88, 1.0, color.a) * vColor;\\n var outColor: vec4 = vec4(0.0);\\n if (color.r < uProgress.progress) {\\n outColor = vec4(_vColor.rgb * a, a);\\n }\\n return outColor;\\n};\\n\";","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.hmd = function(module) {\n\tmodule = Object.create(module);\n\tif (!module.children) module.children = [];\n\tObject.defineProperty(module, 'exports', {\n\t\tenumerable: true,\n\t\tset: function() {\n\t\t\tthrow new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);\n\t\t}\n\t});\n\treturn module;\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t179: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkkosu\"] = self[\"webpackChunkkosu\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [151], function() { return __webpack_require__(29820); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","main_1","require","EventTypes_1","Audio","audio","source","mediaSource","mediaAudioElement","id","isPaused","this","_useMediaSource","paused","isPlaying","nodes","tempArrayMain","Float32Array","tempArrayL","tempArrayR","LeftChannel","RightChannel","FrequencyAmplitudes","_connectedToContext","_onEndCallback","timeStarted","beatmap","GetMaximumAudioLevel","Math","max","GetAverageAudioLevel","Create","audioContext","useMediaSource","Error","createMediaElementSource","onpause","ended","Play","createBufferSource","buffer","AddAudioNode","node","push","GetNode","type","filter","length","ConnectToContext","howToConnectFunction","forEach","index","connect","AnalyserNode","destination","play","backgroundVideo","Events","find","e","eventType","EventTypes","VIDEO","texture","resource","startPromise","then","start","Pause","pause","Stop","stop","SetTime","timeMS","currentTime","video","time","startTime","Promise","resolve","setTimeout","abs","GetDuration","duration","GetCurrentTime","Date","now","RegisterEndCallBack","callback","onended","exports","fadingOut","fadeOutTimeout","playingCallback","FadeOut","clearTimeout","gainNodes","GainNode","gain","linearRampToValueAtTime","Main","AudioEngine","PlayingAudios_1","Audio_1","BeatmapData_1","UnInheritedTimingPoint_1","Effect_1","_playingAudios","_musicQueue","_audioIdTicker","_changeCallbacks","silentMusic","createSilentMusic","useSilentMusic","constructor","AudioContext","PlayingAudios","app","ticker","add","update","UpdateMusicQueue","_play","cb","mapAudio","MapAudio","BeatmapData","timingPoint","UnInheritedTimingPoint","beatLength","effects","Effect","None","TimingPoints","addMusicChangeEventListener","removeMusicChangeEventListener","GetCurrentPlayingMusic","GetCurrentPlayingMusicNoSilent","PlayEffect","pitch","audioObj","AddToMusicQueue","beatMapData","musicPlayingCallback","mapAudioObj","document","createElement","src","PlayMusicImmediately","currentPlaying","currentPlayingNoSilent","analyzerMain","analyzerL","analyzerR","getFloatFrequencyData","i","Infinity","getFloatTimeDomainData","avgL","avgR","value","createGain","analyzer","createAnalyser","fftSize","smoothingTimeConstant","splitter","createChannelSplitter","audios","playbackRate","splice","audioInArr","PIXI","__importStar","MathUtil_1","LogoVisualizer","Container","static","frequencyAmplitudes","temporalAmplitudes","graphics","Graphics","index_change","bar_length","bars_per_visualiser","visualiser_rounds","decay_per_millisecond","time_between_updates","amplitude_dead_zone","indexOffset","firstDraw","alpha","number","super","blendMode","addChild","eventMode","setInterval","updateAmplitudes","draw","clear","decayFactor","deltaMS","j","rotation","MathUtil","DegreesToRadians","rotationCos","cos","rotationSin","sin","barPosition","x","size","y","barSize","sqrt","amplitudeOffset","moveTo","lineTo","stroke","color","width","audioTime","GetCurrentTimingPoints","targetAmplitude","KiaiTime","LogoVisualizer_1","MenuLogoVisualizer","TWEEN","Ease_1","LoadAnim","bg","arc","arcContainer","animInterval","container","bgContainer","bgRotation","bgColor","arcColor","pivot","set","PI","roundRect","fill","cap","scale","Ease","getEase","ScaleTo","Easing","Quadratic","InOut","FadeIn","doAnims","createTween","angle","getWidth","getHeight","deltaTime","destroy","_options","clearInterval","Screen_1","LogoTrackingContainer_1","ButtonSystem","menuBG","isOpened","logo","state","ButtonSystemState","Initial","logoTrackingContainer","LogoTrackingContainer","menuHeight","State","lastState","updateLogoState","console","log","name","arguments","undefined","Exit","Close","TopLevel","Open","ClearEasings","Screen","getScaleBasedOffScreenSize","Linear","In","Quintic","Out","drawMenuBG","Action","onOsuLogo","rect","Edit","Sinusoidal","isOpen","onResize","position","window","innerHeight","innerWidth","Logo","easing","startPosition","visual_box_size","StartTracking","IsTracking","StopTracking","ComputeLogoTrackingPosition","pos","Update","Triangles_1","Loader_1","MenuLogoVisualizer_1","OsuLogo","outline","visualizer","triangles","Triangles","flash","logoContainer","logoBounceContainer","logoBeatContainer","logoAmplitudeContainer","logoHoverContainer","rippleContainer","ripple","defaultVisualizerAlpha","early_activation","timeElapsedSinceLastBeat","timeUntilNextBeat","lastTimeElapasedSinceLastBeat","selectSample","Loader","GetAudio","backToLogoSample","isMouseDown","mouseDownPosition","SizeForFlow","Sprite","from","anchor","mask","circle","height","hitArea","Circle","onmouseenter","_onmouseenter","onmouseleave","_onmouseleave","onmousedown","_onmousedown","onclick","_onclick","stage","addEventListener","_onmouseup","Elastic","mousePos","Exponential","TransformTo","GetCurrentUninheritedTimingPoint","Velocity","Damp","maxAmplitude","onNewBeat","change","pow","amplitudeAdjust","min","Then","FadeTo","osuCircleTriangles_vert_1","__importDefault","osuCircleTriangles_frag_1","osuCircleTriangles_wgsl_1","bgGradient","timeSinceLastSpawn","instancePositionBuffer","totalTriangles","colorStops","FillGradient","ratio","addColorStop","random","velocity","randVelocity","Buffer","data","usage","BufferUsage","VERTEX","COPY_DST","Color","geometry","Geometry","attributes","aPosition","aUV","aColorTint","red","green","blue","aPositionOffset","instance","indexBuffer","instanceCount","gl","vertex","default","fragment","gpu","entryPoint","triangleGraphic","triangleTexture","renderer","generateTexture","shader","Shader","resources","uTexture","uSampler","style","waveUniforms","triangleMesh","Mesh","options","count","triangle","u1","u2","randStdNormal","MenuCursor","mouseCursor","mouseCursorAdditive","mouseContainer","animContainer","animRotationContainer","dragRotationState","DragRotationState","NotDragging","lastDragRotationState","mouseHideContainer","elastic_const2","elastic_const","elastic_offset_quarter","posMouseDown","mouseIsDown","cursorTapSample","mouseButtonClicked","visible","updateMouse","tint","zIndex","addEventListeners","button","DragStarted","Rotating","PopIn","PopOut","distance","offsetX","offsetY","degrees","RadiansToDegrees","atan2","diff","Background","destroying","show","fadeOutDuration","BackgroundContainer","children","child","destroyed","Background_1","RandomBackground","parallaxMultiplier","getScreenWidth","getScreenHeight","newRandomBG","background","BACKGROUND","setBGContainer","setBG","bgSprite","useSeasonalBackgrounds","seasonalBackgroundsNum","randomNum","defaultBackgroundsNum","round","Texture","onClose","sprite","resizeSprite","scaleFactor","texWidth","texHeight","SettingsPane","resize","open","Cubic","toggle","close","addToLoadList","loadList","url","isAudio","pixiBundleName","Get","result","loadedList","loadedObj","GetString","dataString","dataAudio","addBackgrounds","fetch","encodeURIComponent","res","json","backgrounds","loadParser","catch","error","warn","Load","nonPixi","pixi","pixiwithBundles","loadedAssets","erroredAssets","loadObj","added","loadObjs","incrementLoadAssetNumber","errored","response","blob","isText","text","arrayBuffer","arrBuff","decodeAudioData","audioBuff","bundle","assets","alias","Assets","addBundle","loadBundle","IntroScreen_1","InteractScreen","text2","textContainer","textContainerContainer","introTrack","clickSound","clickArea","Text","fontFamily","fontSize","align","cursor","clicked","switchScreen","IntroScreen","body","pointerLock","lockKeyboard","ontap","GlitchingTriangles","bounds","randX","x1","x2","randY","y1","y2","unzipit_1","GlitchingTriangles_1","MainMenu_1","LazerLogo_1","BeatmapParser_1","UIUtils_1","CenteredList_1","introTrackUrl","doTextSpacingAnim","ruleSetContainer","ruleSetList","CenteredList","logoContainerContainer","lazerLogo","LazerLogo","flashed","standard","taiko","ctb","mania","completionPromise","welcomeText","letterSpacing","URL","createObjectURL","entries","unzip","entry","Object","endsWith","async","beatmapData","BeatmapParser","Parse","osuFile","files","LoadFiles","audioFile","General","afterAudioPlay","glitchingInterval","padding","elementsMargin","UIUtils","centerPivotOfList","MainMenu","ReCenter","LogoAnimation_1","highlight","textureHighlight","textureBackground","LogoAnimation","dummy","OnEach","setProgress","logoAnimation_vert_1","logoAnimation_frag_1","logoAnimation_wgsl_1","uProgress","progress","quadGeometry","aColor","quad","uniforms","LoadAnim_1","LoadScreen","loadAnim","RandomBackground_1","OsuLogo_1","ButtonSystem_1","osuCircle","menu","Settings_1","UIScale_1","uiScale","Settings","getSetting","UIScale","getValue","SettingsCategory","info","SettingData","register","setting","onValueChanged","Setting_1","DropdownSetting","Setting","getDefaultValue","defaultValue","setValue","list","option","displayName","save","loadFromSaveValue","RangeSetting","clamp","minValue","maxValue","Renderer_1","MouseSensitivity_1","registerAll","Renderer","MouseSensitivity","load","settingSaveDataString","localStorage","getItem","settings","getList","JSON","parse","corrupt","stringify","category","settingObj","_settingObj","reset","settingSaveData","setItem","removeItem","settingsList","_setting","getSettingData","DropdownSetting_1","webglOption","webGpuOption","RangeSetting_1","increment","pixi_js_1","Input","EventSystem","cursorSensitivity","GeneralData_1","EditorData_1","Metadata_1","DifficultyData_1","EventsData_1","TimingPointsData_1","ColorsData_1","Map","GeneralData","Editor","EditorData","Metadata","Difficulty","DifficultyData","EventsData","TimingPointsData","Colors","ColorsData","HPDrainRate","CircleSize","OverallDifficulty","ApproachRate","SliderMultiplier","SliderTickRate","Bookmarks","DistanceSpacing","BeatDivisor","GridSize","TimelineZoom","Event_1","EventBackground","Event","filename","xOffset","yOffset","EventBreak","BREAK","endTime","EventVideo","Countdown","Countdown_1","SampleSet_1","Mode_1","OverlayPosition_1","AudioFilename","AudioLeadIn","AudioHash","PreviewTime","Normal","SampleSet","StackLeniency","Mode","OSU","LetterboxInBreaks","StoryFireInFront","UseSkinSprites","AlwaysShowPlayfield","OverlayPosition","NoChange","SkinPreference","EpilepsyWarning","CountdownOffset","SpecialStyle","WidescreenStoryboard","SamplesMatchPlaybackRate","Title","TitleUnicode","Artist","ArtistUnicode","Creator","Version","Source","Tags","BeatmapID","BeatmapSetID","TimingPoint_1","InheritedTimingPoint","TimingPoint","sliderVelocityMultiplier","sampleSet","sampleIndex","volume","InheritedTimingPoint_1","toReturn","unInheritedTimingPoint","meter","TimingPointsParser_1","GeneralParser_1","EditorParser_1","MetadataParser_1","DifficultyParser_1","EventsParser_1","osuFileContent","storyBoardFileContent","osuFileContentLines","split","GeneralParser","ParseGeneral","GetSection","EditorParser","ParseEditor","MetadataParser","ParseMetadata","DifficultyParser","ParseDifficulty","EventsParser","ParseEvents","TimingPointsParser","ParseTimingPoints","sectionName","section","str","startsWith","AutoParse","sectionType","propValue","beatmapDataSection","key","keyExists","sectionKey","toString","isNumber","test","parseFloat","substring","num","EventBackground_1","EventVideo_1","EventBreak_1","ffmpeg_1","event","values","replaceAll","parseInt","isNaN","eventKey","file","get","failed","cacheHit","aviTranscodedVideoCache","cache","beatmapSID","filePath","delete","revokeObjectURL","ffmpeg","FFmpeg","on","_ref","classWorker","core","wasm","worker","classWorkerURL","coreURL","wasmURL","workerURL","writeFile","Uint8Array","exec","readFile","terminate","newFile","Blob","prop","Number","radians","clamp01","final","base","exponent","Lerp","ammount","easings","obj","delay","dontStore","previousEases","checkIfEaseExists","ease","newValue","isPrimitive","property","easingFunc","tweenValue","tween","Tween","to","onUpdate","onStart","chain","onStop","onDone","onComplete","newPosition","tweenInArray","newScale","_newScale","newAlpha","largestDuration","sort","a","b","getDuration","registerOnUpdate","updateEventListeners","eventListener","unRegisterOnUpdate","ev","ui_1","List","margin","leftPadding","topPadding","isLast","rightPadding","bottomPadding","gameWidth","gameHeight","Application","globalThis","__PIXI_APP__","onload","init","backgroundColor","antialias","preference","resolution","devicePixelRatio","autoDensity","navigator","mediaSession","setActionHandler","defineProperty","sensitivity","rendererSetting","location","reload","LoadScreen_1","InteractScreen_1","MenuCursor_1","AudioEngine_1","SettingsPane_1","setDropEvents","appendChild","canvas","settingsPane","ctrlKey","code","doResize","clientX","clientY","pointerLockChanged","dialogOk","preventDefault","processingOsuFile","alert","dataTransfer","items","item","kind","getAsFile","setAttribute","keyboard","lock","fullscreenElement","doPointerLock","requestPointerLock","unadjustedMovement","exitPointerLock","screen","currentScreen","lastScreen","allScreens","remove","removeChild","pointerLockElement","isPointerLocked","pointerLockExitTime","removeFromParent","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","module","loaded","__webpack_modules__","call","m","O","chunkIds","fn","priority","notFulfilled","fulfilled","keys","every","r","d","definition","o","enumerable","hmd","create","prototype","hasOwnProperty","Symbol","toStringTag","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","self","bind","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file diff --git a/index.html b/index.html index d3d8f4f..77c2528 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -kosu! \ No newline at end of file +kosu! \ No newline at end of file