diff --git a/Project.xml b/Project.xml index 440c0e7d..ef9f93f0 100644 --- a/Project.xml +++ b/Project.xml @@ -2,7 +2,7 @@ - + diff --git a/buildnumber.txt b/buildnumber.txt index 1fde7522..95bae2dc 100644 --- a/buildnumber.txt +++ b/buildnumber.txt @@ -1 +1 @@ -434 \ No newline at end of file +446 \ No newline at end of file diff --git a/source/BackgroundGirls.hx b/source/BackgroundGirls.hx deleted file mode 100644 index c37b16f9..00000000 --- a/source/BackgroundGirls.hx +++ /dev/null @@ -1,39 +0,0 @@ -package; - -import flixel.FlxSprite; -import flixel.graphics.frames.FlxAtlasFrames; - -class BackgroundGirls extends FlxSprite -{ - public function new(x:Float, y:Float) - { - super(x, y); - - // BG fangirls dissuaded - frames = Paths.getSparrowAtlas('weeb/bgFreaks'); - - animation.addByIndices('danceLeft', 'BG girls group', CoolUtil.numberArray(14), "", 24, false); - animation.addByIndices('danceRight', 'BG girls group', CoolUtil.numberArray(30, 15), "", 24, false); - - animation.play('danceLeft'); - } - - var danceDir:Bool = false; - - public function getScared():Void - { - animation.addByIndices('danceLeft', 'BG fangirls dissuaded', CoolUtil.numberArray(14), "", 24, false); - animation.addByIndices('danceRight', 'BG fangirls dissuaded', CoolUtil.numberArray(30, 15), "", 24, false); - dance(); - } - - public function dance():Void - { - danceDir = !danceDir; - - if (danceDir) - animation.play('danceRight', true); - else - animation.play('danceLeft', true); - } -} diff --git a/source/LoadingState.hx b/source/LoadingState.hx deleted file mode 100644 index 8859ce1b..00000000 --- a/source/LoadingState.hx +++ /dev/null @@ -1,304 +0,0 @@ -package; - -import lime.app.Promise; -import lime.app.Future; -import flixel.FlxG; -import flixel.FlxState; -import flixel.FlxSprite; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.util.FlxTimer; - -import openfl.utils.Assets; -import lime.utils.Assets as LimeAssets; -import lime.utils.AssetLibrary; -import lime.utils.AssetManifest; - -import haxe.io.Path; - -class LoadingState extends MusicBeatState -{ - inline static var MIN_TIME = 1.0; - - var target:FlxState; - var stopMusic = false; - var callbacks:MultiCallback; - - var logo:FlxSprite; - var gfDance:FlxSprite; - var danceLeft = false; - - function new(target:FlxState, stopMusic:Bool) - { - super(); - this.target = target; - this.stopMusic = stopMusic; - } - - override function create() - { - logo = new FlxSprite(-150, -100); - logo.frames = Paths.getSparrowAtlas('logoBumpin'); - logo.antialiasing = true; - logo.animation.addByPrefix('bump', 'logo bumpin', 24); - logo.animation.play('bump'); - logo.updateHitbox(); - // logoBl.screenCenter(); - // logoBl.color = FlxColor.BLACK; - - gfDance = new FlxSprite(FlxG.width * 0.4, FlxG.height * 0.07); - gfDance.frames = Paths.getSparrowAtlas('gfDanceTitle'); - gfDance.animation.addByIndices('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false); - gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false); - gfDance.antialiasing = true; - add(gfDance); - add(logo); - - initSongsManifest().onComplete - ( - function (lib) - { - callbacks = new MultiCallback(onLoad); - var introComplete = callbacks.add("introComplete"); - checkLoadSong(getSongPath()); - if (PlayState.SONG.needsVoices) - checkLoadSong(getVocalPath()); - checkLibrary("shared"); - if (PlayState.storyWeek > 0) - checkLibrary("week" + PlayState.storyWeek); - else - checkLibrary("tutorial"); - - var fadeTime = 0.5; - FlxG.camera.fade(FlxG.camera.bgColor, fadeTime, true); - new FlxTimer().start(fadeTime + MIN_TIME, function(_) introComplete()); - } - ); - } - - function checkLoadSong(path:String) - { - if (!Assets.cache.hasSound(path)) - { - var library = Assets.getLibrary("songs"); - final symbolPath = path.split(":").pop(); - // @:privateAccess - // library.types.set(symbolPath, SOUND); - // @:privateAccess - // library.pathGroups.set(symbolPath, [library.__cacheBreak(symbolPath)]); - var callback = callbacks.add("song:" + path); - Assets.loadSound(path).onComplete(function (_) { callback(); }); - } - } - - function checkLibrary(library:String) - { - trace(Assets.hasLibrary(library)); - if (Assets.getLibrary(library) == null) - { - @:privateAccess - if (!LimeAssets.libraryPaths.exists(library)) - throw "Missing library: " + library; - - var callback = callbacks.add("library:" + library); - Assets.loadLibrary(library).onComplete(function (_) { callback(); }); - } - } - - override function beatHit() - { - super.beatHit(); - - logo.animation.play('bump'); - danceLeft = !danceLeft; - - if (danceLeft) - gfDance.animation.play('danceRight'); - else - gfDance.animation.play('danceLeft'); - } - - override function update(elapsed:Float) - { - super.update(elapsed); - #if debug - if (FlxG.keys.justPressed.SPACE) - trace('fired: ' + callbacks.getFired() + " unfired:" + callbacks.getUnfired()); - #end - } - - function onLoad() - { - if (stopMusic && FlxG.sound.music != null) - FlxG.sound.music.stop(); - - FlxG.switchState(target); - } - - static function getSongPath() - { - return Paths.inst(PlayState.SONG.song); - } - - static function getVocalPath() - { - return Paths.voices(PlayState.SONG.song); - } - - static function getNextState(target:FlxState, stopMusic = false):FlxState - { - #if NO_PRELOAD_ALL - var loaded = isSoundLoaded(getSongPath()) - && (!PlayState.SONG.needsVoices || isSoundLoaded(getVocalPath())) - && isLibraryLoaded("shared"); - - if (!loaded) - return new LoadingState(target, stopMusic); - #end - if (stopMusic && FlxG.sound.music != null) - FlxG.sound.music.stop(); - - return target; - } - - #if NO_PRELOAD_ALL - static function isSoundLoaded(path:String):Bool - { - return Assets.cache.hasSound(path); - } - - static function isLibraryLoaded(library:String):Bool - { - return Assets.getLibrary(library) != null; - } - #end - - override function destroy() - { - super.destroy(); - - callbacks = null; - } - - static function initSongsManifest() - { - var id = "songs"; - var promise = new Promise(); - - var library = LimeAssets.getLibrary(id); - - if (library != null) - { - return Future.withValue(library); - } - - var path = id; - var rootPath = null; - - @:privateAccess - var libraryPaths = LimeAssets.libraryPaths; - if (libraryPaths.exists(id)) - { - path = libraryPaths[id]; - rootPath = Path.directory(path); - } - else - { - if (StringTools.endsWith(path, ".bundle")) - { - rootPath = path; - path += "/library.json"; - } - else - { - rootPath = Path.directory(path); - } - @:privateAccess - path = LimeAssets.__cacheBreak(path); - } - - AssetManifest.loadFromFile(path, rootPath).onComplete(function(manifest) - { - if (manifest == null) - { - promise.error("Cannot parse asset manifest for library \"" + id + "\""); - return; - } - - var library = AssetLibrary.fromManifest(manifest); - - if (library == null) - { - promise.error("Cannot open library \"" + id + "\""); - } - else - { - @:privateAccess - LimeAssets.libraries.set(id, library); - library.onChange.add(LimeAssets.onChange.dispatch); - promise.completeWith(Future.withValue(library)); - } - }).onError(function(_) - { - promise.error("There is no asset library with an ID of \"" + id + "\""); - }); - - return promise.future; - } -} - -class MultiCallback -{ - public var callback:Void->Void; - public var logId:String = null; - public var length(default, null) = 0; - public var numRemaining(default, null) = 0; - - var unfired = new MapVoid>(); - var fired = new Array(); - - public function new (callback:Void->Void, logId:String = null) - { - this.callback = callback; - this.logId = logId; - } - - public function add(id = "untitled") - { - id = '$length:$id'; - length++; - numRemaining++; - var func:Void->Void = null; - func = function () - { - if (unfired.exists(id)) - { - unfired.remove(id); - fired.push(id); - numRemaining--; - - if (logId != null) - log('fired $id, $numRemaining remaining'); - - if (numRemaining == 0) - { - if (logId != null) - log('all callbacks fired'); - callback(); - } - } - else - log('already fired $id'); - } - unfired[id] = func; - return func; - } - - inline function log(msg):Void - { - if (logId != null) - trace('$logId: $msg'); - } - - public function getFired() return fired.copy(); - public function getUnfired() return [for (id in unfired.keys()) id]; -} \ No newline at end of file diff --git a/source/MenuCharacter.hx b/source/MenuCharacter.hx deleted file mode 100644 index ca5f9b49..00000000 --- a/source/MenuCharacter.hx +++ /dev/null @@ -1,33 +0,0 @@ -package; - -import flixel.FlxSprite; -import flixel.graphics.frames.FlxAtlasFrames; - -class MenuCharacter extends FlxSprite -{ - public var character:String; - - public function new(x:Float, character:String = 'bf') - { - super(x); - - this.character = character; - - var tex = Paths.getSparrowAtlas('campaign_menu_UI_characters'); - frames = tex; - - animation.addByPrefix('bf', "BF idle dance white", 24); - animation.addByPrefix('bfConfirm', 'BF HEY!!', 24, false); - animation.addByPrefix('gf', "GF Dancing Beat WHITE", 24); - animation.addByPrefix('dad', "Dad idle dance BLACK LINE", 24); - animation.addByPrefix('spooky', "spooky dance idle BLACK LINES", 24); - animation.addByPrefix('pico', "Pico Idle Dance", 24); - animation.addByPrefix('mom', "Mom Idle BLACK LINES", 24); - animation.addByPrefix('parents-christmas', "Parent Christmas Idle", 24); - animation.addByPrefix('senpai', "SENPAI idle Black Lines", 24); - // Parent Christmas Idle - - animation.play(character); - updateHitbox(); - } -} diff --git a/source/MenuItem.hx b/source/MenuItem.hx deleted file mode 100644 index f41d893c..00000000 --- a/source/MenuItem.hx +++ /dev/null @@ -1,49 +0,0 @@ -package; - -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.group.FlxSpriteGroup; -import flixel.math.FlxMath; -import flixel.util.FlxColor; - -class MenuItem extends FlxSpriteGroup -{ - public var targetY:Float = 0; - public var week:FlxSprite; - public var flashingInt:Int = 0; - - public function new(x:Float, y:Float, weekNum:Int = 0) - { - super(x, y); - week = new FlxSprite().loadGraphic(Paths.image('storymenu/week' + weekNum)); - add(week); - } - - private var isFlashing:Bool = false; - - public function startFlashing():Void - { - isFlashing = true; - } - - // if it runs at 60fps, fake framerate will be 6 - // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still??? - // so it runs basically every so many seconds, not dependant on framerate?? - // I'm still learning how math works thanks whoever is reading this lol - var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10); - - override function update(elapsed:Float) - { - super.update(elapsed); - y = FlxMath.lerp(y, (targetY * 120) + 480, 0.17); - - if (isFlashing) - flashingInt += 1; - - if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) - week.color = 0xFF33ffff; - else - week.color = FlxColor.WHITE; - } -} diff --git a/source/OutdatedSubState.hx b/source/OutdatedSubState.hx deleted file mode 100644 index 74196fe2..00000000 --- a/source/OutdatedSubState.hx +++ /dev/null @@ -1,45 +0,0 @@ -package; - -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.FlxSubState; -import flixel.text.FlxText; -import flixel.util.FlxColor; -import lime.app.Application; - -class OutdatedSubState extends MusicBeatState -{ - public static var leftState:Bool = false; - - override function create() - { - super.create(); - var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); - add(bg); - var ver = "v" + Application.current.meta.get('version'); - var txt:FlxText = new FlxText(0, 0, FlxG.width, - "HEY! You're running an outdated version of the game!\nCurrent version is " - + ver - + " while the most recent version is " - // + NGio.GAME_VER - + "! Press Space to go to itch.io, or ESCAPE to ignore this!!", - 32); - txt.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, CENTER); - txt.screenCenter(); - add(txt); - } - - override function update(elapsed:Float) - { - if (controls.ACCEPT) - { - FlxG.openURL("https://ninja-muffin24.itch.io/funkin"); - } - if (controls.BACK) - { - leftState = true; - FlxG.switchState(new MainMenuState()); - } - super.update(elapsed); - } -} diff --git a/source/Snd.hx b/source/Snd.hx deleted file mode 100644 index 33aedae6..00000000 --- a/source/Snd.hx +++ /dev/null @@ -1,1288 +0,0 @@ -import faxe.Faxe; - -import SndTV; -using StringTools; - -//praise delahee, i'll figure out what this shit means later! - -class Channel { - public var name:String; - public var onEnd : Void -> Void = null; - public var isDebug = false; - - var started = true; - var paused = false; - var disposed = false; - var completed = false; - - inline function new( ?name:String = null ){ - if ( name == null ) - this.name = C.EMPTY_STRING; - else - this.name = name; - } - - public function poolBack(){ - #if false - //trace("pool back"); - #end - started = false; - paused = false; - disposed = true; - completed = true; - isDebug = false; - } - - public function reset(){ - started = false; - paused = false; - disposed = false; - completed = false; - isDebug = false; - } - - public function stop(){ - started = false; - } - - public function pause(){ - paused = false; - started = true; - } - - public function resume(){ - paused = true; - started = true; - } - - public function dispose(){ - setVolume(0);//prevent any further listen - disposed = true; - onEnd = null; - } - - public function onComplete() { - completed = true; - #if !prod - //trace("onComplete " + haxe.Timer.stamp() ); - #end - //stop(); - if( onEnd!=null ) { - var cb = onEnd; - onEnd = null; - cb(); - } - } - - public function isComplete(){ - #if !prod - if ( completed ){ - //trace("already completed"); - } - - if ( started ){ - //trace("started ok"); - } - #end - - return completed || (started && !isPlaying()); - } - - //returns in secs - public function getPlayCursorSec() : Float { - throw "override me"; - return 0.0; - } - - //returns in secs - public function getPlayCursorMs() : Float { - throw "override me"; - return 0.0; - } - - public function setPlayCursorSec(posSec:Float) { - setPlayCursorMs( posSec * 1000.0 ); - } - - public function setPlayCursorMs(posMs:Float) { - throw "override me"; - } - - public function isPlaying(){ - throw "override me"; - return false; - } - - public function getVolume():Float{ - throw "override me"; - return 0.0; - } - - public function setVolume(v:Float){ - throw "override me"; - } - - public function setNbLoops(nb:Int){ - - } -} - -class ChannelEventInstance extends Channel {//basically a sound instance - public static var EMPTY_STRING = ""; - public var data : FmodStudioEventInstanceRef = null; - - function new(?name:String){ - super(name); - started = false; - //instance does not start playing - } - - public static var pool = { - var p = new hxd.Pool(ChannelEventInstance); - //p.actives = null; - p; - } - - public static function alloc(data : FmodStudioEventInstanceRef, ?name:String=null ){ - var s = pool.alloc(); - - s.reset(); - - s.data = data; - s.name = name == null ? EMPTY_STRING : name; - return s; - } - - public static function delete( c : ChannelEventInstance){ - c.dispose(); - pool.delete(c); - } - - public function getData() return data; - - public override function dispose(){ - super.dispose(); - if ( data != null){ - data.release(); - data = null; - } - } - - public override function poolBack(){ - super.poolBack(); - ChannelEventInstance.delete(this); - } - - public override function stop(){ - if (data != null) data.stop(FmodStudioStopMode.StopAllowFadeout()); - super.stop(); - } - - public override function pause(){ - super.pause(); - if(data!=null) data.setPaused(true); - } - - public override function resume(){ - super.resume(); - if(data!=null) data.setPaused(false); - } - - public override function isPlaying(){ - if ( completed ) return false; - - if ( data == null ) { - //#if !prod - //trace("[CEI]no data " + name); - //#end - return false; - } - - var b : Bool = false; - data.getPaused( Cpp.addr(b)); - #if !prod - //trace("getPaused:"+b); - #end - return !b; - } - - //returns in secs - public override function getPlayCursorSec() : Float { - if ( data == null ) return 0.0; - - var pos : Int = 0; - var res = data.getTimelinePosition( Cpp.addr(pos) ); - var posF : Float = 1.0 * pos / 1000.0; - return posF; - } - - //returns in secs - public override function getPlayCursorMs() : Float { - if ( data == null ) return 0.0; - - var pos : Int = 0; - var res = data.getTimelinePosition( Cpp.addr(pos) ); - return 1.0 * pos; - } - - public override function setPlayCursorMs(posMs:Float) { - if ( data == null ) return; - - if ( posMs < 0.0) posMs = 0.0; - var pos : Int = 0; - pos = Math.round( posMs ); - var res = data.setTimelinePosition( pos ); - if ( res != FMOD_OK){ - #if debug - //trace("[SND][Channel]{"+name+"} Repositionning S err " + FaxeRef.fmodResultToString(res)+" to :"+pos+" ("+posMs+")"); - #end - } - - #if debug - //trace("setPlayCursorMs "+posMs); - #end - } - - public override function setNbLoops(nb:Int){ - - } - - public override function getVolume() : Float{ - if (data == null ) return 0.0; - - var vol : cpp.Float32 = 0.0; - var fvol : cpp.Float32 = 0.0; - var res = data.getVolume( Cpp.addr(vol),Cpp.addr(fvol) ); - if ( res != FMOD_OK){ - #if debug - //trace("[SND][Channel]{"+name+"} getVolume err " + FaxeRef.fmodResultToString(res)); - #end - } - return vol; - } - - public override function setVolume(v:Float){ - if (data == null ){ - //#if debug - //trace("no data for "+name); - //#end - return; - } - - var res = data.setVolume( hxd.Math.clamp(v,0,1) ); - if ( res != FMOD_OK){ - //#if debug - //trace("[SND][Channel]{"+name+"} setVolume err " + FaxeRef.fmodResultToString(res)); - //#end - } - else { - //if ( isDebug ){ - //#if !prod - //trace("[SND][Channel]{"+name+"} setVolume ok " + v); - //#end - //} - } - } -} - -class ChannelLowLevel extends Channel{ - - public static var EMPTY_STRING = ""; - public var data : FmodChannelRef = null; - - function new( data : FmodChannelRef, ?name:String ){ - super(name); - this.data = data; - started = true; - } - - public static var pool = { - var p = new hxd.Pool(ChannelLowLevel); - //p.actives = null; - p; - } - - public static function alloc(data : FmodChannelRef, ?name ){ - var s = pool.alloc(); - - s.reset(); - - s.data = data; - s.name = name == null?EMPTY_STRING:name; - - return s; - } - - public static function delete( c : ChannelLowLevel){ - c.dispose(); - pool.delete(c); - } - - public function getData(){ - return data; - } - - public override function poolBack(){ - super.poolBack(); - ChannelLowLevel.delete(this); - } - - public override function stop(){ - if (data != null) data.stop(); - super.stop(); - } - - public override function pause(){ - super.pause(); - if(data!=null) data.setPaused(true); - } - - public override function resume(){ - super.resume(); - if(data!=null) data.setPaused(false); - } - - public override function dispose(){ - super.dispose(); - data = null; - } - - public override function isPlaying(){ - if ( completed ) return false; - - if (data == null) { - //#if !prod - //trace("no data no playing! "+name); - //#end - return false; - } - var b : Bool = false; - var res = data.isPlaying( Cpp.addr(b)); - if ( res != FMOD_OK ){ - //#if debug - //trace("[SND][ChannelLowLevel]{"+name+"} isPlaying err " + FaxeRef.fmodResultToString(res)); - //#end - return false; - } - return b; - } - - //returns in secs - public override function getPlayCursorSec() : Float { - if (data == null) return 0.0; - - var pos : cpp.UInt32 = 0; - var res = data.getPosition( Cpp.addr(pos), faxe.Faxe.FmodTimeUnit.FTM_MS ); - var posF : Float = 1.0 * pos * 1000.0; - return posF; - } - - //returns in secs - public override function getPlayCursorMs() : Float { - if (data == null) return 0.0; - - var pos : cpp.UInt32 = 0; - var res = data.getPosition( Cpp.addr(pos), faxe.Faxe.FmodTimeUnit.FTM_MS ); - return 1.0 * pos; - } - - - public override function setPlayCursorMs(posMs:Float) { - if (data == null) return; - - if ( posMs < 0.0) posMs = 0.0; - var posU : cpp.UInt32 = 0; - posU = Math.round( posMs ); - var res = data.setPosition( posU, FmodTimeUnit.FTM_MS ); - if ( res != FMOD_OK){ - //#if debug - //trace("[SND][Channel]{"+name+"} Repositionning S err " + FaxeRef.fmodResultToString(res)+" to :"+posU+" ("+posMs+")"); - //#end - } - } - - public override function setNbLoops(nb:Int){ - if (data == null) return; - data.setMode(FmodMode.FMOD_LOOP_NORMAL); - data.setLoopCount(nb); - } - - public override function getVolume():Float{ - if (data == null) return 0.0; - - var vol : cpp.Float32 = 0.0; - var res = data.getVolume( Cpp.addr(vol) ); - if ( res != FMOD_OK){ - //#if debug - //trace("[SND][Channel]{"+name+"} getVolume err " + FaxeRef.fmodResultToString(res)); - //#end - } - return vol; - } - - public override function setVolume(v:Float){ - if (data == null) { - //if ( isDebug ){ - //#if !prod - //trace("[SND][Channel]{"+name+"} setVolume no data"); - //#end - //} - return; - } - - var vcl = hxd.Math.clamp(v, 0, 1); - var res = data.setVolume( vcl ); - if ( res != FMOD_OK){ - //#if !prod - //trace("[SND][Channel]{"+name+"} setVolume err " + FaxeRef.fmodResultToString(res)); - //#end - } - else { - if ( isDebug ){ - //#if !prod - //trace("[SND][Channel]{"+name+"} setVolume ok " + v+" corrected:"+vcl); - //#end - } - } - } - - -} - -class Sound { - /** - * length is in seconds - */ - public var name = ""; - public var length(get, null) : Float; - public var id3 : Dynamic = null; - public var isDebug = false; - - var disposed = false; - - function new( ?name:String=null ){ - disposed = false; - } - - function get_length() : Float{ - return 0.0; - } - - //returns in msec - public function getDuration(): Float{ - return getDurationMs(); - } - - public function getDurationSec() : Float{ - return length; - } - - public function getDurationMs() : Float{ - return length * 1000.0; - } - - public function dispose(){ - if (disposed) return; - disposed = true; - } - - public function play( ?offsetMs : Float = 0.0, ?nbLoops:Int = 1, ?volume:Float = 1.0 ) : Channel { - return null; - } -} - -class SoundLowLevel extends Sound{ - - public var data : FmodSoundRef = null; - - public function new( data : cpp.Pointer, ?name:String = null ){ - super(name); - this.data = Cpp.ref(data); - } - - public function getData(){ - return data; - } - - public override function dispose(){ - super.dispose(); - - if ( Snd.released ) { - data = null; - return; - } - - if(data!=null) - data.release(); - data = null; - } - - //returns in secs - override function get_length() : Float{ - if (disposed) return 0.0; - - var pos : cpp.UInt32 = 0; - var res = data.getLength( Cpp.addr(pos), FmodTimeUnit.FTM_MS ); - if ( res != FMOD_OK ){ - #if debug - //trace("impossible to retrieve sound len"); - #end - } - var posF = 1.0 * pos / 1000.0; - return posF; - } - - public override function play( ?offsetMs : Float = 0.0, ?nbLoops:Int = 1, ?volume:Float = 1.0) : Channel { - var nativeChan : FmodChannelRef = FaxeRef.playSoundWithHandle( data , false); - var chan = ChannelLowLevel.alloc( nativeChan, name ); - - #if debug - //trace("[Sound] offset " + offsetMs); - //trace("play " + haxe.Timer.stamp() ); - #end - - @:privateAccess chan.started = true; - @:privateAccess chan.completed = false; - @:privateAccess chan.disposed = false; - @:privateAccess chan.paused = false; - - - if( offsetMs != 0.0 ) chan.setPlayCursorMs( offsetMs ); - if( volume != 1.0 ) chan.setVolume( volume ); - if( nbLoops > 1 ) chan.setNbLoops( nbLoops ); - - return chan; - } -} - - -class SoundEvent extends Sound{ - - public var data : FmodStudioEventDescriptionRef = null; - - public function new( data : FmodStudioEventDescriptionRef, ?name:String = null ){ - super(name); - this.data = data; - } - - public override function dispose(){ - super.dispose(); - - if ( Snd.released ) { - data = null; - return; - } - - if ( data != null){ - data.releaseAllInstances(); - data = null; - } - } - public function getData(){ - return data; - } - - //returns in secs - override function get_length() : Float{ - if (disposed) return 0.0; - - var pos : Int = 0; - var res = data.getLength( Cpp.addr(pos) ); - if ( res != FMOD_OK ){ - //#if !prod - //trace("impossible to retrieve sound len"); - //#end - } - var posF = 1.0 * pos / 1000.0; - return posF; - } - - public override function play( ?offsetMs : Float = 0.0, ?nbLoops:Int = 1, ?volume:Float = 1.0) : Channel{ - var nativeInstance : FmodStudioEventInstanceRef = data.createInstance(); - var chan = ChannelEventInstance.alloc( nativeInstance, name ); - - //#if !prod - //trace("play " + haxe.Timer.stamp() ); - //#end - nativeInstance.start(); - - @:privateAccess chan.started = true; - @:privateAccess chan.completed = false; - @:privateAccess chan.disposed = false; - @:privateAccess chan.paused = false; - - if( offsetMs != 0.0 ) chan.setPlayCursorMs( offsetMs ); - if( volume != 1.0 ) chan.setVolume( volume ); - - return chan; - } -} - -class Snd { - public static var EMPTY_STRING = ""; - public static var PLAYING : hxd.Stack = new hxd.Stack(); - static var MUTED = false; - static var DISABLED = false; - static var GLOBAL_VOLUME = 1.0; - static var TW = new SndTV(); - - public var name : String ; - public var pan : Float = 0.0; - public var volume(default,set) : Float = 1.0; - public var curPlay : Null = null; - public var bus = otherBus; - public var isDebug = true; - /** - * for when stop is called explicitly - * allows disposal - */ - public var onStop = new hxd.Signal(); - public var sound : Sound = null; - - var onEnd : NullVoid> = null; - static var fmodSystem : FmodSystemRef = null; - - public static var otherBus = new SndBus(); - public static var sfxBus = new SndBus(); - public static var musicBus = new SndBus(); - - public function new( snd : Sound, ?name:String ) { - volume = 1; - pan = 0; - sound = snd; - muted = false; - this.name = name==null?EMPTY_STRING:name; - } - - public function isLoaded() { - return sound!=null; - } - - //does not dispose sound, only instanced - public function stop(){ - - TW.terminate(this);//prevent reentrancy of fadeStop() stop() not cutting any sound - - PLAYING.remove(this); - - if ( isPlaying() && !onStop.isTriggering ) - onStop.trigger(); - - if ( curPlay != null){ - curPlay.dispose(); - curPlay.poolBack(); - curPlay = null; - #if !prod - //trace(name+" stopped"); - //Lib.showStack(); - #end - } - - //bus = otherBus; - } - - public function dispose(){ - //#if !prod - //trace(name+" disposing"); - //#end - - if ( isPlaying() ){ - stop(); - } - - if ( curPlay != null){ - curPlay.dispose(); - curPlay.poolBack(); - curPlay = null; - //#if !prod - //trace(name+" disposed"); - //#end - } - - if ( sound != null) { - sound.dispose(); - sound = null; - } - - onStop.dispose(); - - onEnd = null; - curPlay = null; - } - - /** - * - * @return in ms - */ - public inline function getPlayCursor() : Float { - if ( curPlay == null) return 0.0; - return curPlay.getPlayCursorMs(); - } - - - public function play(?vol:Float, ?pan:Float) : Snd { - if( vol == null ) vol = volume; - if( pan == null ) pan = this.pan; - - start(0, vol, 0.0); - - return this; - } - - /** - * launches the sound, stops previous and rewrite the cur play dropping it into oblivion for the gc - */ - public function start(loops:Int=0, vol:Float=1.0, ?startOffsetMs:Float=0.0) { - if ( DISABLED ) { - //#if debug - //trace("[SND] Disabled"); - //#end - return; - } - if ( sound == null ){ - //#if debug - //trace("[SND] no inner sound"); - //#end - return; - } - - if ( isPlaying() ){ - //#if !prod - //trace(name+" interrupting "); - //#end - - stop(); - } - - TW.terminate(this); - - this.volume = vol; - this.pan = normalizePanning(pan); - - PLAYING.push(this); - curPlay = sound.play( startOffsetMs, loops, getRealVolume()); - - if ( curPlay == null){ - //#if !prod - //trace(" play missed?"); - //#end - } - else { - //#if !prod - //trace("started"); - //#end - } - } - - /** - * launches the sound and rewrite the cur play dropping it into oblivion for the gc - */ - public function startNoStop(?loops:Int=0, ?vol:Float=1.0, ?startOffsetMs:Float=0.0) : Null{ - if ( DISABLED ) { - //#if debug - //trace("[SND] Disabled"); - //#end - return null; - } - if ( sound == null ){ - //#if debug - //trace("[SND] no inner sound"); - //#end - return null; - } - - this.volume = vol; - this.pan = normalizePanning(pan); - - curPlay = sound.play( startOffsetMs, loops, getRealVolume()); - - return curPlay; - } - - public inline function getDuration() { - return getDurationMs(); - } - - public inline function getDurationSec() { - return sound.length; - } - - /** - * returns in ms - */ - public inline function getDurationMs() { - return sound.length * 1000.0; - } - - public static inline - function trunk(v:Float, digit:Int) : Float{ - var hl = Math.pow( 10.0 , digit ); - return Std.int( v * hl ) / hl; - } - - public static function dumpMemory(){ - var v0 : Int = 0; - var v1 : Int = 0; - var v2 : Int = 0; - - var v0p : cpp.Pointer = Cpp.addr(v0); - var v1p : cpp.Pointer = Cpp.addr(v1); - var v2p : cpp.Pointer = Cpp.addr(v2); - var str = ""; - var res = fmodSystem.getSoundRAM( v0p, v1p, v2p ); - if ( res != FMOD_OK){ - //#if debug - //trace("[SND] cannot fetch snd ram dump "); - //#end - } - - inline function f( val :Float) : Float{ - return trunk(val, 2); - } - - if( v2 > 0 ){ - str+="fmod Sound chip RAM all:" + f(v0 / 1024.0) + "KB \t max:" + f(v1 / 1024.0) + "KB \t total: " + f(v2 / 1024.0) + " KB\r\n"; - } - - v0 = 0; - v1 = 0; - - var res = FaxeRef.Memory_GetStats( v0p, v1p, false ); - str += "fmod Motherboard chip RAM all:" + f(v0 / 1024.0) + "KB \t max:" + f(v1 / 1024.0) + "KB \t total: " + f(v2 / 1024.0) + " KB"; - return str; - } - - public function playLoop(?loops = 9999, ?vol:Float=1.0, ?startOffset = 0.0) : Snd { - if( vol==null ) - vol = volume; - - start(loops, vol, startOffset); - return this; - } - - function set_volume(v:Float) { - volume = v; - refresh(); - return volume; - } - - public function setVolume(v:Float) { - set_volume(v); - } - - public inline function getRealPanning() { - return pan; - } - - public function setPanning(p:Float) { - pan = p; - refresh(); - } - - public function onEndOnce(cb:Void->Void) { - onEnd = cb; - } - - public function fadePlay(?fadeDuration = 100, ?endVolume:Float=1.0 ) { - var p = play(0.0001); - if ( p == null ){ - //trace("nothing ret"); - } - else { - if ( p.curPlay == null){ - //trace("no curplay wtf?"); - } - else - { - //trace("curplay ok"); - } - } - tweenVolume(endVolume, fadeDuration); - return p; - } - - public function fadePlayLoop(?fadeDuration = 100, ?endVolume:Float=1.0 , ?loops=9999) { - var p = playLoop(loops,0); - tweenVolume(endVolume, fadeDuration); - return p; - } - - public function fadeStop( ?fadeDuration = 100 ) { - if ( !isPlaying()){ - //#if !prod - //trace("not playing " + name+" winn not unfade");//can cause reentrancy issues - //#end - return null; - } - - isDebug = true; - var t = tweenVolume(0, fadeDuration); - t.onEnd = _stop; - return t; - } - - public var muted : Bool = false; - - public function toggleMute() { - muted = !muted;//todo - setVolume(volume); - } - public function mute() { - muted = true; - setVolume(volume); - } - public function unmute() { - muted = false; - setVolume(volume); - } - - public function isPlaying(){ - if ( curPlay == null ){ - #if !prod - //trace("no curplay"); - #end - return false; - } - return curPlay.isPlaying(); - } - - public static function init(){ - #if debug - trace("[Snd] fmod init"); - #end - Faxe.fmod_init( 256 ); - fmodSystem = FaxeRef.getSystem(); - released = false; - } - - public static var released = true; - - public static function release(){ - TW.terminateAll(); - for (s in PLAYING) - s.dispose(); - PLAYING.hardReset(); - released = true; - //trace("releasing fmod"); - Faxe.fmod_release(); - #if !prod - trace("fmod released"); - #end - } - - public static function setGlobalVolume(vol:Float) { - GLOBAL_VOLUME = normalizeVolume(vol); - refreshAll(); - } - - function refresh() { - if ( curPlay != null ) { - var vol = getRealVolume(); - //trace("r:"+vol); - curPlay.setVolume( vol ); - } - else { - //#if debug - //trace("[Snd] no playin no refresh "+name); - //#end - } - } - - public function setPlayCursorSec( pos:Float ) { - if (curPlay != null) { - curPlay.setPlayCursorSec(pos); - } - else { - //#if debug - //trace("setPlayCursorSec/no current instance"); - //#end - } - } - - public function setPlayCursorMs( pos:Float ){ - if (curPlay != null) - curPlay.setPlayCursorMs(pos); - else { - //#if debug - //trace("setPlayCursorMs/no current instance"); - //#end - } - } - - public function tweenVolume(v:Float, ?easing:h2d.Tweenie.TType, ?milliseconds:Float=100) : TweenV { - if ( easing == null ) easing = h2d.Tweenie.TType.TEase; - var t = TW.create(this, TVVVolume, v, easing, milliseconds); - //#if !prod - //trace("tweening " + name+" to " + v); - //#end - return t; - } - - public function tweenPan(v:Float, ?easing:h2d.Tweenie.TType, ?milliseconds:Float=100) : TweenV { - if ( easing == null ) easing = h2d.Tweenie.TType.TEase; - var t = TW.create(this, TVVPan, v, easing, milliseconds); - return t; - } - - public inline function getRealVolume() { - var v = volume * GLOBAL_VOLUME * (DISABLED?0:1) * (MUTED?0:1) * (muted?0:1) * bus.volume; - if ( v <= 0.001) - v = 0.0; - return normalizeVolume(v); - } - - static inline function normalizeVolume(f:Float) { - return hxd.Math.clamp(f, 0,1); - } - - static inline function normalizePanning(f:Float) { - return hxd.Math.clamp(f, -1,1); - } - - static var _stop = function(t:TweenV){ - #if !prod - //if( t.parent != null ) - //trace(t.parent.name+" cbk stopped"); - //else - //trace(" unbound stop called"); - #end - t.parent.stop(); - } - - static var _refresh = function(t:TweenV) { - - //avoid unwanted crash - if ( released ){ - //#if !prod - //trace("sorry released"); - //#end - return; - } - - t.parent.refresh(); - } - - static function refreshAll() { - for(s in PLAYING) - s.refresh(); - } - - function onComplete(){ - //#if debug - //trace("onComplete " + haxe.Timer.stamp()); - //#end - - if (curPlay != null) { - curPlay.onComplete(); - } - - stop(); - } - - public function isComplete(){ - if ( curPlay == null ) { - //#if!prod - //trace("comp: no cur play"); - //#end - return true; - } - return curPlay.isComplete(); - } - - ////////////////////////////////////// - /////////////////////STATICS////////// - ////////////////////////////////////// - - public static var DEBUG_TRACK = false; - - //@:noDebug - public static function loadSound( path:String, streaming : Bool, blocking : Bool ) : Sound { - - if ( released ) { - //#if(!prod) - //trace("FMOD not active "+path); - //#end - return null; - } - - var mode = FMOD_DEFAULT; - - if ( streaming ) mode |= FMOD_CREATESTREAM; - if ( !blocking ) mode |= FMOD_NONBLOCKING; - - mode |= FmodMode.FMOD_2D; - - - if( DEBUG_TRACK) trace("Snd:loading " + path); - - var snd : cpp.RawPointer = cast null; - var sndR : cpp.RawPointer> = cpp.RawPointer.addressOf(snd); - - #if switch - if ( !path.startsWith("rom:")) - path = "rom://" + path; - #end - - var res : FmodResult = fmodSystem.createSound( - Cpp.cstring(path), - mode, - Cpp.nullptr(), - sndR - ); - - if ( res != FMOD_OK){ - #if(!prod) - trace("unable to load " + path + " code:" + res+" msg:"+FaxeRef.fmodResultToString(res)); - #end - return null; - } - - var n:String = null; - - #if debug - n = new bm.Path(path).getFilename(); - #end - - return new SoundLowLevel(cpp.Pointer.fromRaw(snd),n); - } - - public static function loadEvent( path:String ) : Sound { - if ( released ) { - //#if (!prod) - //trace("FMOD not active "+path); - //#end - return null; - } - - - if( DEBUG_TRACK) trace("Snd:loadingEvent " + path); - - if ( !path.startsWith("event:/")) - path = "event:/" + path; - - var fss : FmodStudioSystemRef = faxe.FaxeRef.getStudioSystem(); - var ev = fss.getEvent( path); - - if ( ev == null ) return null; - - if ( !ev.isLoaded() ){ - var t0 = haxe.Timer.stamp(); - ev.loadSampleData(); - var t1 = haxe.Timer.stamp(); - #if debug - //trace("time to preload:" + (t1 - t0)); - #end - } - - return new SoundEvent( ev, path); - } - - public static function fromFaxe( path:String ) : Snd { - if ( released ) { - //#if (!prod) - //trace("FMOD not active "+path); - //#end - return null; - } - - var s : cpp.Pointer = faxe.Faxe.fmod_get_sound(path ); - if ( s == null){ - #if (!prod) - trace("unable to find " + path); - #end - return null; - } - - var n:String = null; - - #if debug - n = new bm.Path(path).getFilename(); - #end - - return new Snd( new SoundLowLevel(s,n), path); - } - - public static function loadSfx( path:String ) : Snd { - var s : Sound = loadSound(path, false, false); - if ( s == null) return null; - return new Snd( s, s.name); - } - - public static function loadSong( path:String ) : Snd { - var s : Sound = loadSound(path, true, true); - if ( s == null) return null; - return new Snd( s, s.name); - } - - public static function load( path:String, streaming=false,blocking=true ) : Snd { - var s : Sound = loadSound(path, streaming, blocking); - if ( s == null) { - #if !prod - trace("no such file " + path); - #end - return null; - } - return new Snd( s, s.name); - } - - public static function terminateTweens() { - TW.terminateAll(); - } - - public static function update() { - for ( p in PLAYING.backWardIterator()) - if ( p.isComplete()){ - #if !prod - //trace("[Snd] isComplete " + p); - #end - p.onComplete(); - } - TW.update();//let tweens complete - - if(!released ) Faxe.fmod_update(); - } - - public static function loadSingleBank( filename : String ) : Null{ - if ( released ) { - #if debug - trace("FMOD not active "+filename); - #end - return null; - } - - if ( filename.endsWith(".fsb")) { - #if debug - trace("fsb files not supported"); - #end - return null;//old fmod format is not supported - } - - var t0 = haxe.Timer.stamp(); - var fsys = FaxeRef.getStudioSystem(); - var fbank : cpp.RawPointer < FmodStudioBank > = null; - - //trace("trying to load " + filename); - - Lib.loadMode(); - var result = fsys.loadBankFile( - cpp.ConstCharStar.fromString( filename ), - FmodStudioLoadBank.FMOD_STUDIO_LOAD_BANK_NONBLOCKING, - cpp.RawPointer.addressOf(fbank)); - Lib.playMode(); - - if (result != FMOD_OK) { - #if debug - trace("FMOD failed to LOAD sound bank with errcode:" + result + " errmsg:" + FaxeRef.fmodResultToString(result) + "\n"); - #end - return null; - } - //else - // trace("loading..."); - - var t1 = haxe.Timer.stamp(); - #if debug - //trace("time to load bank:" + (t1 - t0)+"s"); - #end - return cast fbank; - } -} \ No newline at end of file diff --git a/source/SndTV.hx b/source/SndTV.hx deleted file mode 100644 index 62e69f45..00000000 --- a/source/SndTV.hx +++ /dev/null @@ -1,332 +0,0 @@ -import h2d.Tweenie.TType; - -//praise delahee, i'll figure out what this shit means later! - -enum TVVar{ - TVVVolume; - TVVPan; -} - -@:publicFields -class TweenV { - static var GUID = 0; - var uid = 0; - - var man : SndTV; - var parent : Snd; - var n : Float; - var ln : Float; - var speed : Float; - var from : Float; - var to : Float; - var type : TType; - var plays : Int; // -1 = infini, 1 et plus = nombre d'exécutions (1 par défaut) - var varType : TVVar; - var onUpdate : NullVoid>; - var onEnd : NullVoid>; - var isDebug = false; - - public inline function new ( - parent:Snd , - n:Float , - ln:Float , - varType:TVVar, - speed:Float , - from:Float , - to:Float , - type:h2d.Tweenie.TType , - plays , - onUpdate , - onEnd - ) { - this.parent = parent ; - this.n = n ; - this.ln = ln ; - this.varType = varType ; - this.speed = speed ; - this.from = from ; - this.to = to ; - this.type = type ; - this.plays = plays ; - this.onUpdate = onUpdate ; - this.onEnd = onEnd ; - } - - public inline function reset( - parent:Snd , - n:Float , - ln:Float , - varType:TVVar, - speed:Float , - from:Float , - to:Float , - type:TType , - plays:Int , - onUpdate , - onEnd - ) { - this.parent = parent ; - this.n = n ; - this.ln = ln ; - this.speed = speed ; - this.from = from ; - this.to = to ; - this.type = type ; - this.plays = plays ; - this.onUpdate = onUpdate ; - this.onEnd = onEnd ; - this.varType = varType ; - isDebug = false; - uid = GUID++; - } - - public function clear(){ - n = 0.0; - ln = 0.0; - speed = 0.0; - plays = 0; - from = 0.0; - to = 0.0; - parent = null; - onEnd = null; - onUpdate = null; - isDebug = false; - uid = GUID++; - } - - - public - inline - function apply( val ) { - switch(varType){ - case TVVVolume: { - parent.volume = val; - #if debug - if( isDebug ) - trace("tv:" + val); - #end - } - case TVVPan: parent.pan = val; - } - - } - - public inline function kill( withCbk = true ) { - if ( withCbk ) - man.terminateTween( this ); - else - man.forceTerminateTween( this) ; - } - -} - -/** - * tween order is not respected - */ -class SndTV { - static var DEFAULT_DURATION = DateTools.seconds(1); - public var fps = 60.0; - public var isDebug = false; - - var tlist : hxd.Stack; - - public function new() { - tlist = new hxd.Stack(); - tlist.reserve(8); - } - - function onError(e) { - trace(e); - } - - public function count() { - return tlist.length; - } - - public inline function create(parent:Snd, vartype:TVVar, to:Float, ?tp:h2d.Tweenie.TType, ?duration_ms:Float) : TweenV{ - return create_(parent, vartype, to, tp, duration_ms); - } - - public function exists(p:Snd) { - for (t in tlist) - if (t.parent == p ) - return true; - return false; - } - - public var pool : hxd.Stack = new hxd.Stack(); - - function create_(p:Snd, vartype:TVVar,to:Float, ?tp:h2d.Tweenie.TType, ?duration_ms:Float) : TweenV{ - if ( duration_ms==null ) - duration_ms = DEFAULT_DURATION; - - #if debug - if ( p == null ) trace("tween2 creation failed to:"+to+" tp:"+tp); - #end - - if ( tp==null ) tp = TEase; - - { - // on supprime les tweens précédents appliqués à la même variable - for(t in tlist.backWardIterator()) - if(t.parent==p && t.varType == vartype) { - forceTerminateTween(t); - } - } - - var from = switch( vartype ){ - case TVVVolume : p.volume; - case TVVPan : p.pan; - } - var t : TweenV; - if (pool.length == 0){ - t = new TweenV( - p, - 0.0, - 0.0, - vartype, - 1 / ( duration_ms*fps/1000 ), // une seconde - from, - to, - tp, - 1, - null, - null - ); - } - else { - t = pool.pop(); - t.reset( - p, - 0.0, - 0.0, - vartype, - 1 / ( duration_ms*fps/1000 ), // une seconde - from, - to, - tp, - 1, - null, - null - ); - - } - - if( t.from==t.to ) - t.ln = 1; // tweening inutile : mais on s'assure ainsi qu'un update() et un end() seront bien appelés - - t.man = this; - tlist.push(t); - - return t; - } - - public static inline - function fastPow2(n:Float):Float { - return n*n; - } - - public static inline - function fastPow3(n:Float):Float { - return n*n*n; - } - - public static inline - function bezier(t:Float, p0:Float, p1:Float,p2:Float, p3:Float) { - return - fastPow3(1-t)*p0 + - 3*( t*fastPow2(1-t)*p1 + fastPow2(t)*(1-t)*p2 ) + - fastPow3(t)*p3; - } - - // suppression du tween sans aucun appel aux callbacks onUpdate, onUpdateT et onEnd (!) - public function killWithoutCallbacks(parent:Snd) { - for (t in tlist.backWardIterator()) - if (t.parent==parent ){ - forceTerminateTween(t); - return true; - } - return false; - } - - public function terminate(parent:Snd) { - for (t in tlist.backWardIterator()) - if (t.parent==parent){ - forceTerminateTween(t); - } - } - - public function forceTerminateTween(t:TweenV) { - var tOk = tlist.remove(t); - if( tOk ){ - t.clear(); - pool.push(t); - } - } - - public function terminateTween(t:TweenV, ?fl_allowLoop=false) { - var v = t.from + (t.to - t.from) * h2d.Tweenie.interp(t.type, 1); - t.apply(v); - onUpdate(t, 1); - - var ouid = t.uid; - - onEnd(t); - - if( ouid == t.uid ){ - if( fl_allowLoop && (t.plays==-1 || t.plays>1) ) { - if( t.plays!=-1 ) - t.plays--; - t.n = t.ln = 0; - } - else { - forceTerminateTween(t); - } - } - } - - public function terminateAll() { - for(t in tlist) - t.ln = 1; - update(); - } - - inline - function onUpdate(t:TweenV, n:Float) { - if ( t.onUpdate!=null ) - t.onUpdate(t); - } - - inline - function onEnd(t:TweenV) { - if ( t.onEnd!=null ) - t.onEnd(t); - } - - public function update(?tmod = 1.0) { - if ( tlist.length > 0 ) { - for (t in tlist.backWardIterator() ) { - var dist = t.to-t.from; - if (t.type==TRand) - t.ln+=if(Std.random(100)<33) t.speed * tmod else 0; - else - t.ln += t.speed * tmod; - - t.n = h2d.Tweenie.interp(t.type, t.ln); - - if ( t.ln<1 ) { - // en cours... - var val = t.from + t.n*dist; - - t.apply(val); - - onUpdate(t, t.ln); - } - else // fini ! - { - terminateTween(t, true); - } - } - } - } -} \ No newline at end of file diff --git a/source/funkin/editors/ChartingState.hx b/source/funkin/editors/ChartingState.hx index 5982e235..f74aca22 100644 --- a/source/funkin/editors/ChartingState.hx +++ b/source/funkin/editors/ChartingState.hx @@ -1,7 +1,7 @@ package funkin.editors; import funkin.system.Conductor.BPMChangeEvent; -import Section.SwagSection; +import funkin.system.Section.SwagSection; import funkin.system.Conductor; import funkin.system.Song.SwagSong; import funkin.system.Song; diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index b9d2d476..479749e2 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -5,10 +5,10 @@ import flixel.util.FlxDestroyUtil; #if desktop import funkin.system.Discord.DiscordClient; #end -import Section.SwagSection; +import funkin.system.Section.SwagSection; import funkin.system.Song.SwagSong; import funkin.scripting.ScriptPack; -import WiggleEffect.WiggleEffectType; +import funkin.shaders.WiggleEffect.WiggleEffectType; import flixel.FlxBasic; import flixel.FlxCamera; import flixel.FlxG; diff --git a/source/import.hx b/source/funkin/import.hx similarity index 100% rename from source/import.hx rename to source/funkin/import.hx diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx index 65c2e041..e2cb83fc 100644 --- a/source/funkin/menus/StoryMenuState.hx +++ b/source/funkin/menus/StoryMenuState.hx @@ -17,6 +17,7 @@ import flixel.util.FlxTimer; import lime.net.curl.CURLCode; import funkin.system.Song; import funkin.game.Highscore; +import flixel.group.FlxSpriteGroup; using StringTools; @@ -446,3 +447,74 @@ class StoryMenuState extends MusicBeatState #end } } + + +class MenuCharacter extends FlxSprite +{ + public var character:String; + + public function new(x:Float, character:String = 'bf') + { + super(x); + + this.character = character; + + var tex = Paths.getSparrowAtlas('campaign_menu_UI_characters'); + frames = tex; + + animation.addByPrefix('bf', "BF idle dance white", 24); + animation.addByPrefix('bfConfirm', 'BF HEY!!', 24, false); + animation.addByPrefix('gf', "GF Dancing Beat WHITE", 24); + animation.addByPrefix('dad', "Dad idle dance BLACK LINE", 24); + animation.addByPrefix('spooky', "spooky dance idle BLACK LINES", 24); + animation.addByPrefix('pico', "Pico Idle Dance", 24); + animation.addByPrefix('mom', "Mom Idle BLACK LINES", 24); + animation.addByPrefix('parents-christmas', "Parent Christmas Idle", 24); + animation.addByPrefix('senpai', "SENPAI idle Black Lines", 24); + // Parent Christmas Idle + + animation.play(character); + updateHitbox(); + } +} + +class MenuItem extends FlxSpriteGroup +{ + public var targetY:Float = 0; + public var week:FlxSprite; + public var flashingInt:Int = 0; + + public function new(x:Float, y:Float, weekNum:Int = 0) + { + super(x, y); + week = new FlxSprite().loadGraphic(Paths.image('storymenu/week' + weekNum)); + add(week); + } + + private var isFlashing:Bool = false; + + public function startFlashing():Void + { + isFlashing = true; + } + + // if it runs at 60fps, fake framerate will be 6 + // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still??? + // so it runs basically every so many seconds, not dependant on framerate?? + // I'm still learning how math works thanks whoever is reading this lol + var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10); + + override function update(elapsed:Float) + { + super.update(elapsed); + y = FlxMath.lerp(y, (targetY * 120) + 480, 0.17); + + if (isFlashing) + flashingInt += 1; + + if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) + week.color = 0xFF33ffff; + else + week.color = FlxColor.WHITE; + } +} diff --git a/source/LatencyState.hx b/source/funkin/options/LatencyState.hx similarity index 98% rename from source/LatencyState.hx rename to source/funkin/options/LatencyState.hx index 1136330e..65e36300 100644 --- a/source/LatencyState.hx +++ b/source/funkin/options/LatencyState.hx @@ -1,4 +1,4 @@ -package; +package funkin.options; import flixel.FlxG; import flixel.FlxSprite; diff --git a/source/PlayerSettings.hx b/source/funkin/options/PlayerSettings.hx similarity index 99% rename from source/PlayerSettings.hx rename to source/funkin/options/PlayerSettings.hx index e733c108..d559ccd4 100644 --- a/source/PlayerSettings.hx +++ b/source/funkin/options/PlayerSettings.hx @@ -1,4 +1,4 @@ -package; +package funkin.options; import funkin.system.Controls; import flixel.FlxCamera; diff --git a/source/OverlayShader.hx b/source/funkin/shaders/OverlayShader.hx similarity index 96% rename from source/OverlayShader.hx rename to source/funkin/shaders/OverlayShader.hx index 4de9a555..caaaaa8c 100644 --- a/source/OverlayShader.hx +++ b/source/funkin/shaders/OverlayShader.hx @@ -1,4 +1,4 @@ -package; +package funkin.shaders; import flixel.system.FlxAssets.FlxShader; diff --git a/source/WiggleEffect.hx b/source/funkin/shaders/WiggleEffect.hx similarity index 99% rename from source/WiggleEffect.hx rename to source/funkin/shaders/WiggleEffect.hx index ac2bd3bb..291c8a85 100644 --- a/source/WiggleEffect.hx +++ b/source/funkin/shaders/WiggleEffect.hx @@ -1,4 +1,4 @@ -package; +package funkin.shaders; // STOLEN FROM HAXEFLIXEL DEMO LOL import flixel.system.FlxAssets.FlxShader; diff --git a/source/Main.hx b/source/funkin/system/Main.hx similarity index 82% rename from source/Main.hx rename to source/funkin/system/Main.hx index d518fa32..f6105cf7 100644 --- a/source/Main.hx +++ b/source/funkin/system/Main.hx @@ -1,5 +1,6 @@ -package; +package funkin.system; +import funkin.windows.WindowsAPI; import funkin.menus.TitleState; import funkin.game.Highscore; import funkin.options.Options; @@ -93,8 +94,31 @@ class Main extends Sprite #end } + @:dox(hide) + public static var audioDisconnected:Bool = false; + + @:dox(hide) + @:noCompletion + private #if !flash override #end function __enterFrame(deltaTime:Int):Void { + super.__enterFrame(deltaTime); + #if windows + if (audioDisconnected) { + lime.media.AudioManager.suspend(); + audioDisconnected = false; + lime.media.AudioManager.init(); + // @:privateAccess + // for(e in openfl.media.SoundMixer.__soundChannels) { + // @:privateAccess + // e.__source.__backend.parent.buffer.__srcBuffer = null; + // @:privateAccess + // e.__source.__backend.init(); + // } + } + #end + } + public function loadGameSettings() { - PlayerSettings.init(); + funkin.options.PlayerSettings.init(); FlxG.save.bind('Save'); Highscore.load(); @@ -120,6 +144,11 @@ class Main extends Sprite Options.load(); + WindowsAPI.registerAudio(); + // WindowsAPI.setAudioChangeCallback(function() { + // trace("test"); + // }); + var diamond:FlxGraphic = FlxGraphic.fromClass(GraphicTransTileDiamond); diamond.persist = true; diamond.destroyOnNoUse = false; diff --git a/source/funkin/system/MusicBeatState.hx b/source/funkin/system/MusicBeatState.hx index 2498e0a1..1ad2574c 100644 --- a/source/funkin/system/MusicBeatState.hx +++ b/source/funkin/system/MusicBeatState.hx @@ -9,6 +9,7 @@ import flixel.addons.ui.FlxUIState; import flixel.math.FlxRect; import flixel.math.FlxMath; import flixel.util.FlxTimer; +import funkin.options.PlayerSettings; class MusicBeatState extends FlxUIState { diff --git a/source/funkin/system/MusicBeatSubstate.hx b/source/funkin/system/MusicBeatSubstate.hx index b710eb0b..098e1777 100644 --- a/source/funkin/system/MusicBeatSubstate.hx +++ b/source/funkin/system/MusicBeatSubstate.hx @@ -2,6 +2,7 @@ package funkin.system; import funkin.system.Conductor.BPMChangeEvent; import funkin.system.Conductor; +import funkin.options.PlayerSettings; import flixel.FlxG; import flixel.FlxSubState; import flixel.math.FlxMath; diff --git a/source/Section.hx b/source/funkin/system/Section.hx similarity index 96% rename from source/Section.hx rename to source/funkin/system/Section.hx index f153da54..19de7112 100644 --- a/source/Section.hx +++ b/source/funkin/system/Section.hx @@ -1,4 +1,4 @@ -package; +package funkin.system; typedef SwagSection = { diff --git a/source/funkin/system/Song.hx b/source/funkin/system/Song.hx index 77ce46b8..4e2e6de8 100644 --- a/source/funkin/system/Song.hx +++ b/source/funkin/system/Song.hx @@ -1,6 +1,6 @@ package funkin.system; -import Section.SwagSection; +import funkin.system.Section.SwagSection; import haxe.Json; import haxe.format.JsonParser; import lime.utils.Assets; diff --git a/source/funkin/windows/WindowsAPI.hx b/source/funkin/windows/WindowsAPI.hx new file mode 100644 index 00000000..467c3a7a --- /dev/null +++ b/source/funkin/windows/WindowsAPI.hx @@ -0,0 +1,15 @@ + + +package funkin.windows; + +/** + * Class for Windows-only functions, such as transparent windows, message boxes, and more. + * Does not have any effect on other platforms. + */ +class WindowsAPI { + public static function registerAudio() { + #if windows + native.WinAPI.registerAudio(); + #end + } +} \ No newline at end of file diff --git a/source/native/WinAPI.hx b/source/native/WinAPI.hx new file mode 100644 index 00000000..70730fc5 --- /dev/null +++ b/source/native/WinAPI.hx @@ -0,0 +1,120 @@ +package native; + +#if windows +@:buildXml(' + + + + + + +') + +// majority is taken from microsofts doc +@:cppFileCode(' +#include "mmdeviceapi.h" +#include "combaseapi.h" +#include + +#define SAFE_RELEASE(punk) \\ + if ((punk) != NULL) \\ + { (punk)->Release(); (punk) = NULL; } + +static long lastDefId = 0; + +class AudioFixClient : public IMMNotificationClient { + LONG _cRef; + IMMDeviceEnumerator *_pEnumerator; + + public: + AudioFixClient() : + _cRef(1), + _pEnumerator(NULL) + { + HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator), + NULL, CLSCTX_INPROC_SERVER, + __uuidof(IMMDeviceEnumerator), + (void**)&_pEnumerator); + if (result == S_OK) { + _pEnumerator->RegisterEndpointNotificationCallback(this); + } + } + + ~AudioFixClient() + { + SAFE_RELEASE(_pEnumerator); + } + + ULONG STDMETHODCALLTYPE AddRef() + { + return InterlockedIncrement(&_cRef); + } + + ULONG STDMETHODCALLTYPE Release() + { + ULONG ulRef = InterlockedDecrement(&_cRef); + if (0 == ulRef) + { + delete this; + } + return ulRef; + } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, VOID **ppvInterface) + { + return S_OK; + } + + HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) + { + return S_OK; + }; + + HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) + { + return S_OK; + } + + HRESULT STDMETHODCALLTYPE OnDeviceStateChanged( + LPCWSTR pwstrDeviceId, + DWORD dwNewState) + { + return S_OK; + } + + HRESULT STDMETHODCALLTYPE OnPropertyValueChanged( + LPCWSTR pwstrDeviceId, + const PROPERTYKEY key) + { + return S_OK; + } + + HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged( + EDataFlow flow, ERole role, + LPCWSTR pwstrDeviceId) + { + std::cout << "fuck"; + ::funkin::_hx_system::Main_obj::audioDisconnected = true; + return S_OK; + }; +}; + +AudioFixClient *curAudioFix; +') +@:dox(hide) +class WinAPI { + + public static var __audioChangeCallback:Void->Void = function() { + trace("test"); + }; + + + @:functionCode(' + if (!curAudioFix) curAudioFix = new AudioFixClient(); + ') + public static function registerAudio() { + funkin.system.Main.audioDisconnected = true; + } +} +#end \ No newline at end of file