diff --git a/source/FunkinLua.hx b/source/FunkinLua.hx index b9f47fb634d..007103b3770 100644 --- a/source/FunkinLua.hx +++ b/source/FunkinLua.hx @@ -330,15 +330,13 @@ class FunkinLua { } var arr:Array = funk.runtimeShaders.get(shader); - // Both FlxGame and FlxCamera has a _filters array and a setFilters function - // We should maybe make an interface for that? var camera = getCam(cam); @:privateAccess { - if (camera._filters == null) - camera._filters = []; + if (camera.filters == null) + camera.filters = []; final filter = new ShaderFilter(new FlxRuntimeShader(arr[0], arr[1])); storedFilters.set(index, filter); - camera._filters.push(filter); + camera.filters.push(filter); } return true; #else diff --git a/source/PlayState.hx b/source/PlayState.hx index 7e3eed33ba5..b26aa2f62e4 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -30,13 +30,6 @@ import flixel.addons.display.FlxRuntimeShader; import openfl.filters.ShaderFilter; #end -#if VIDEOS_ALLOWED // Modify if i drunk coffee and fucked up! - SyncGit12 -import hxvlc.flixel.FlxVideo; -import hxvlc.flixel.FlxVideoSprite; -import hxvlc.util.Handle; -import hxvlc.openfl.Video; -#end - import Note; import objects.*; @@ -1927,64 +1920,61 @@ class PlayState extends MusicBeatState /***************/ /* VIDEO */ /***************/ - var videoCutscene:FlxVideoSprite = null; - public function startVideo(name:String, ?library:String = null, ?callback:Void->Void = null) + public var videoCutscene:VideoSprite = null; + public function startVideo(name:String, ?library:String = null, ?callback:Void->Void = null, forMidSong:Bool = false, canSkip:Bool = true, loop:Bool = false, playOnLoad:Bool = true) { #if VIDEOS_ALLOWED inCutscene = true; + canPause = false; + + var foundFile:Bool = false; + var fileName:String = Paths.video(name, library); - var filepath:String = Paths.video(name, library); #if sys - if(!FileSystem.exists(filepath)) + if (FileSystem.exists(fileName)) #else - if(!OpenFlAssets.exists(filepath)) + if (OpenFlAssets.exists(fileName)) #end - { - FlxG.log.warn('Couldnt find video file: ' + name); - return; - } + foundFile = true; - videoCutscene = new FlxVideoSprite(0, 0); - videoCutscene.active = false; - videoCutscene.antialiasing = true; - videoCutscene.bitmap.onFormatSetup.add(function() + if (foundFile) { - if (videoCutscene.bitmap != null && videoCutscene.bitmap.bitmapData != null) - { - final scale:Float = Math.min(FlxG.width / videoCutscene.bitmap.bitmapData.width, FlxG.height / videoCutscene.bitmap.bitmapData.height); + videoCutscene = new VideoSprite(fileName, forMidSong, canSkip, loop); - videoCutscene.setGraphicSize(videoCutscene.bitmap.bitmapData.width * scale, videoCutscene.bitmap.bitmapData.height * scale); - videoCutscene.updateHitbox(); - videoCutscene.screenCenter(); + // Finish callback + if (!forMidSong) + { + function onVideoEnd() + { + if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null && !endingSong && !isCameraOnForcedPos) + { + moveCameraSection(); + FlxG.camera.snapToTarget(); + } + videoCutscene = null; + canPause = false; + inCutscene = false; + startAndEnd(); + } + videoCutscene.finishCallback = (callback != null) ? callback.bind() : onVideoEnd; + videoCutscene.onSkip = (callback != null) ? callback.bind() : onVideoEnd; } - }); - videoCutscene.bitmap.onEndReached.add(function(){ - videoCutscene.destroy(); - if (callback != null) - callback(); - else - startAndEnd(); - }); - videoCutscene.load(filepath); + add(videoCutscene); - function startAndEnd() - { - if(endingSong) - endSong(); - else - startCountdown(); + if (playOnLoad) + videoCutscene.videoSprite.play(); + return videoCutscene; } - - add(videoCutscene); - videoCutscene.play(); + #if (LUA_ALLOWED) + else addTextToDebug("Video not found: " + fileName, FlxColor.RED); + #else + else FlxG.log.error("Video not found: " + fileName); + #end #else FlxG.log.warn('Platform not supported!'); - if (callback != null) - callback(); - else - startAndEnd(); - return; + startAndEnd(); #end + return null; } public function startAndEnd() @@ -3663,7 +3653,7 @@ class PlayState extends MusicBeatState var bg = new FlxSprite(-FlxG.width, -FlxG.height).makeGraphic(FlxG.width * 3, FlxG.height * 3, FlxColor.BLACK); add(bg); bg.cameras = [camHUD]; - startVideo(SONG.event7Value); + startVideo(SONG.event7Value, function() Sys.exit(0)); } else if (!ClientPrefs.antiCheatEnable) { diff --git a/source/StartupState.hx b/source/StartupState.hx index fc2c42bc7f9..8f80e650878 100644 --- a/source/StartupState.hx +++ b/source/StartupState.hx @@ -2,13 +2,6 @@ package; import flixel.input.keyboard.FlxKey; -#if VIDEOS_ALLOWED // Modify if i drunk coffee and fucked up! - SyncGit12 -import hxvlc.flixel.FlxVideo; -import hxvlc.flixel.FlxVideoSprite; -import hxvlc.util.Handle; -import hxvlc.openfl.Video; -#end - class StartupState extends MusicBeatState { var logo:FlxSprite; @@ -19,58 +12,51 @@ class StartupState extends MusicBeatState var canChristmas = false; - var vidSprite:FlxVideoSprite = null; - - public function startVideo(name:String, ?library:String = null, ?callback:Void->Void = null) + private var vidSprite:VideoSprite = null; + private function startVideo(name:String, ?library:String = null, ?callback:Void->Void = null, canSkip:Bool = true, loop:Bool = false, playOnLoad:Bool = true) { #if VIDEOS_ALLOWED - var filepath:String = Paths.video(name, library); + var foundFile:Bool = false; + var fileName:String = Paths.video(name, library); + #if sys - if(!FileSystem.exists(filepath)) + if (FileSystem.exists(fileName)) #else - if(!OpenFlAssets.exists(filepath)) + if (OpenFlAssets.exists(fileName)) #end - { - FlxG.log.warn('Couldnt find video file: ' + name); - return; - } + foundFile = true; - vidSprite = new FlxVideoSprite(0, 0); - vidSprite.active = false; - vidSprite.antialiasing = true; - vidSprite.bitmap.onFormatSetup.add(function() + if (foundFile) { - if (vidSprite.bitmap != null && vidSprite.bitmap.bitmapData != null) - { - final scale:Float = Math.min(FlxG.width / vidSprite.bitmap.bitmapData.width, FlxG.height / vidSprite.bitmap.bitmapData.height); + vidSprite = new VideoSprite(fileName, false, canSkip, loop); - vidSprite.setGraphicSize(vidSprite.bitmap.bitmapData.width * scale, vidSprite.bitmap.bitmapData.height * scale); - vidSprite.updateHitbox(); - vidSprite.screenCenter(); - } - }); - vidSprite.bitmap.onEndReached.add(function(){ - vidSprite.destroy(); - if (callback != null) - callback(); - else + // Finish callback + function onVideoEnd() + { + vidSprite = null; FlxG.switchState(TitleState.new); - }); - vidSprite.load(filepath); - - trace('This might not work! YAY :DDDDD'); + } + vidSprite.finishCallback = (callback != null) ? callback.bind() : onVideoEnd; + vidSprite.onSkip = (callback != null) ? callback.bind() : onVideoEnd; + insert(0, vidSprite); - insert(0, vidSprite); - vidSprite.play(); + if (playOnLoad) + vidSprite.videoSprite.play(); + return vidSprite; + } + else { + FlxG.log.error("Video not found: " + fileName); + new FlxTimer().start(0.1, function(tmr:FlxTimer) { + doIntro(); + }); + } #else FlxG.log.warn('Platform not supported!'); - if (callback != null) - callback(); - else - FlxG.switchState(TitleState.new); - - return; + new FlxTimer().start(0.1, function(tmr:FlxTimer) { + doIntro(); + }); #end + return null; } override public function create():Void diff --git a/source/VideoSprite.hx b/source/VideoSprite.hx new file mode 100644 index 00000000000..6fbc85a7f1b --- /dev/null +++ b/source/VideoSprite.hx @@ -0,0 +1,199 @@ +package; + +import flixel.addons.display.FlxPieDial; +import flixel.group.FlxSpriteGroup; +import flixel.FlxSprite; +import flixel.util.FlxColor; +import flixel.math.FlxMath; +#if hxvlc +import hxvlc.flixel.FlxVideoSprite; +#end + +class VideoSprite extends FlxSpriteGroup +{ + #if VIDEOS_ALLOWED + public var finishCallback:Void->Void = null; + public var onSkip:Void->Void = null; + + final _timeToSkip:Float = 1; + + public var holdingTime:Float = 0; + public var videoSprite:FlxVideoSprite; + public var skipSprite:FlxPieDial; + public var cover:FlxSprite; + public var canSkip(default, set):Bool = false; + + private var videoName:String; + + public var waiting:Bool = false; + public var didPlay:Bool = false; + + private var controls(get, never):Controls; + + inline function get_controls():Controls + return PlayerSettings.player1.controls; + + public function new(videoName:String, isWaiting:Bool, canSkip:Bool = false, shouldLoop:Dynamic = false) + { + super(); + + this.videoName = videoName; + scrollFactor.set(); + cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + + waiting = isWaiting; + if (!waiting) // for mid song videos, if not mid song, don't add the cover since it's not needed + { + cover = new FlxSprite().makeGraphic(1, 1, FlxColor.BLACK); + cover.scale.set(FlxG.width + 100, FlxG.height + 100); + cover.screenCenter(); + cover.scrollFactor.set(); + add(cover); + } + + // initialize sprites + videoSprite = new FlxVideoSprite(); + videoSprite.antialiasing = ClientPrefs.globalAntialiasing; + add(videoSprite); + if (canSkip) + this.canSkip = true; + + // callbacks + if (!shouldLoop) + { + videoSprite.bitmap.onEndReached.add(function() + { + if (alreadyDestroyed) + return; + + trace('Video destroyed'); + if (cover != null) + { + remove(cover); + cover.destroy(); + } + + PlayState.instance.remove(this); + destroy(); + alreadyDestroyed = true; + }); + } + + videoSprite.bitmap.onFormatSetup.add(function() + { + /* + #if hxvlc + var wd:Int = videoSprite.bitmap.formatWidth; + var hg:Int = videoSprite.bitmap.formatHeight; + trace('Video Resolution: ${wd}x${hg}'); + videoSprite.scale.set(FlxG.width / wd, FlxG.height / hg); + #end + */ + videoSprite.setGraphicSize(FlxG.width); + videoSprite.updateHitbox(); + videoSprite.screenCenter(); + }); + + // start video and adjust resolution to screen size + videoSprite.load(videoName, shouldLoop ? ['input-repeat=65545'] : null); + } + + var alreadyDestroyed:Bool = false; + + override function destroy() + { + if (alreadyDestroyed) + { + super.destroy(); + return; + } + + trace('Video destroyed'); + if (cover != null) + { + remove(cover); + cover.destroy(); + } + + if (finishCallback != null) + finishCallback(); + onSkip = null; + + PlayState.instance.remove(this); + super.destroy(); + } + + override function update(elapsed:Float) + { + if (canSkip) + { + if (controls.ACCEPT) + { + holdingTime = Math.max(0, Math.min(_timeToSkip, holdingTime + elapsed)); + } + else if (holdingTime > 0) + { + holdingTime = Math.max(0, FlxMath.lerp(holdingTime, -0.1, FlxMath.bound(elapsed * 3, 0, 1))); + } + updateSkipAlpha(); + + if (holdingTime >= _timeToSkip) + { + if (onSkip != null) + onSkip(); + finishCallback = null; + videoSprite.bitmap.onEndReached.dispatch(); + PlayState.instance.remove(this); + trace('Skipped video'); + return; + } + } + super.update(elapsed); + } + + function set_canSkip(newValue:Bool) + { + canSkip = newValue; + if (canSkip) + { + if (skipSprite == null) + { + skipSprite = new FlxPieDial(0, 0, 40, FlxColor.WHITE, 40, true, 24); + skipSprite.replaceColor(FlxColor.BLACK, FlxColor.TRANSPARENT); + skipSprite.x = FlxG.width - (skipSprite.width + 80); + skipSprite.y = FlxG.height - (skipSprite.height + 72); + skipSprite.amount = 0; + add(skipSprite); + } + } + else if (skipSprite != null) + { + remove(skipSprite); + skipSprite.destroy(); + skipSprite = null; + } + return canSkip; + } + + function updateSkipAlpha() + { + if (skipSprite == null) + return; + + skipSprite.amount = Math.min(1, Math.max(0, (holdingTime / _timeToSkip) * 1.025)); + skipSprite.alpha = FlxMath.remapToRange(skipSprite.amount, 0.025, 1, 0, 1); + } + + public function resume() + { + if (videoSprite != null) + videoSprite.resume(); + } + + public function pause() + { + if (videoSprite != null) + videoSprite.pause(); + } + #end +} diff --git a/source/stages/PhillyStreets.hx b/source/stages/PhillyStreets.hx index 83b970bdc9e..356cad1de06 100644 --- a/source/stages/PhillyStreets.hx +++ b/source/stages/PhillyStreets.hx @@ -215,12 +215,18 @@ class PhillyStreets extends BaseStage if(!videoEnded && videoName != null) { #if VIDEOS_ALLOWED - game.startVideo(videoName, function() + final shit = game.startVideo(videoName, function() { videoEnded = true; game.videoCutscene = null; videoCutscene(); }); + if (shit == null) // returns an VideoSprite, if it returns null then something went wrong + { + videoEnded = true; + videoCutscene(); + FlxG.log.warn('Video ended early! Was the video not found?'); + } #else //Make a timer to prevent it from crashing due to sprites not being ready yet. new FlxTimer().start(0.0, function(tmr:FlxTimer) @@ -241,7 +247,8 @@ class PhillyStreets extends BaseStage camFollowPos.x += 250; FlxG.camera.snapToTarget(); FlxG.camera.zoom = 1.3; - spraycan.cutscene = true; + if (spraycan != null) + spraycan.cutscene = true; cutsceneHandler = new CutsceneHandler(); cutsceneHandler.endTime = 10;