2023-02-22 01:58:15 +00:00
|
|
|
package funkin.graphics.video;
|
2021-04-18 03:19:33 +00:00
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
import flixel.util.FlxColor;
|
|
|
|
import flixel.util.FlxSignal.FlxTypedSignal;
|
|
|
|
import funkin.audio.FunkinSound;
|
|
|
|
import openfl.display3D.textures.TextureBase;
|
2021-04-18 03:19:33 +00:00
|
|
|
import openfl.events.NetStatusEvent;
|
2024-03-19 19:56:00 +00:00
|
|
|
import openfl.media.SoundTransform;
|
2021-04-18 03:19:33 +00:00
|
|
|
import openfl.media.Video;
|
|
|
|
import openfl.net.NetConnection;
|
|
|
|
import openfl.net.NetStream;
|
|
|
|
|
2023-02-22 01:58:15 +00:00
|
|
|
/**
|
|
|
|
* Plays a video via a NetStream. Only works on HTML5.
|
2024-03-19 19:56:00 +00:00
|
|
|
* This does NOT replace hxCodec, nor does hxCodec replace this.
|
|
|
|
* hxCodec only works on desktop and does not work on HTML5!
|
2023-02-22 01:58:15 +00:00
|
|
|
*/
|
2024-03-19 19:56:00 +00:00
|
|
|
class FlxVideo extends FunkinSprite
|
2021-04-18 03:19:33 +00:00
|
|
|
{
|
2023-01-23 03:25:45 +00:00
|
|
|
var video:Video;
|
|
|
|
var netStream:NetStream;
|
2024-03-19 19:56:00 +00:00
|
|
|
var videoPath:String;
|
2023-01-23 03:25:45 +00:00
|
|
|
|
|
|
|
/**
|
2024-03-19 19:56:00 +00:00
|
|
|
* A callback to execute when the video finishes.
|
2023-01-23 03:25:45 +00:00
|
|
|
*/
|
2024-03-19 19:56:00 +00:00
|
|
|
public var finishCallback:Void->Void;
|
|
|
|
|
2023-06-15 04:30:01 +00:00
|
|
|
public function new(videoPath:String)
|
2023-01-23 03:25:45 +00:00
|
|
|
{
|
|
|
|
super();
|
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
this.videoPath = videoPath;
|
|
|
|
|
|
|
|
makeGraphic(2, 2, FlxColor.TRANSPARENT);
|
|
|
|
|
2023-01-23 03:25:45 +00:00
|
|
|
video = new Video();
|
|
|
|
video.x = 0;
|
|
|
|
video.y = 0;
|
2024-03-19 19:56:00 +00:00
|
|
|
video.alpha = 0;
|
2023-01-23 03:25:45 +00:00
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
FlxG.game.addChild(video);
|
2023-01-23 03:25:45 +00:00
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
var netConnection:NetConnection = new NetConnection();
|
2023-01-23 03:25:45 +00:00
|
|
|
netConnection.connect(null);
|
|
|
|
|
|
|
|
netStream = new NetStream(netConnection);
|
2024-03-19 19:56:00 +00:00
|
|
|
netStream.client = {onMetaData: onClientMetaData};
|
|
|
|
netConnection.addEventListener(NetStatusEvent.NET_STATUS, onNetConnectionNetStatus);
|
2023-06-15 04:30:01 +00:00
|
|
|
netStream.play(videoPath);
|
2023-01-23 03:25:45 +00:00
|
|
|
}
|
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
/**
|
|
|
|
* Tell the FlxVideo to pause playback.
|
|
|
|
*/
|
2024-02-28 08:53:36 +00:00
|
|
|
public function pauseVideo():Void
|
|
|
|
{
|
|
|
|
if (netStream != null)
|
|
|
|
{
|
|
|
|
netStream.pause();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
/**
|
|
|
|
* Tell the FlxVideo to resume if it is paused.
|
|
|
|
*/
|
2024-02-28 08:53:36 +00:00
|
|
|
public function resumeVideo():Void
|
|
|
|
{
|
|
|
|
// Resume playing the video.
|
|
|
|
if (netStream != null)
|
|
|
|
{
|
|
|
|
netStream.resume();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
var videoAvailable:Bool = false;
|
|
|
|
var frameTimer:Float;
|
|
|
|
|
|
|
|
static final FRAME_RATE:Float = 60;
|
|
|
|
|
|
|
|
public override function update(elapsed:Float):Void
|
|
|
|
{
|
|
|
|
super.update(elapsed);
|
|
|
|
|
|
|
|
if (frameTimer >= (1 / FRAME_RATE))
|
|
|
|
{
|
|
|
|
frameTimer = 0;
|
|
|
|
// TODO: We just draw the video buffer to the sprite 60 times a second.
|
|
|
|
// Can we copy the video buffer instead somehow?
|
|
|
|
pixels.draw(video);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (videoAvailable) frameTimer += elapsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tell the FlxVideo to seek to the beginning.
|
|
|
|
*/
|
2024-02-28 05:19:08 +00:00
|
|
|
public function restartVideo():Void
|
|
|
|
{
|
|
|
|
// Seek to the beginning of the video.
|
|
|
|
if (netStream != null)
|
|
|
|
{
|
|
|
|
netStream.seek(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
/**
|
|
|
|
* Tell the FlxVideo to end.
|
|
|
|
*/
|
2023-01-23 03:25:45 +00:00
|
|
|
public function finishVideo():Void
|
|
|
|
{
|
|
|
|
netStream.dispose();
|
|
|
|
FlxG.removeChild(video);
|
|
|
|
|
|
|
|
if (finishCallback != null) finishCallback();
|
|
|
|
}
|
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
public override function destroy():Void
|
|
|
|
{
|
|
|
|
if (netStream != null)
|
|
|
|
{
|
|
|
|
netStream.dispose();
|
|
|
|
|
|
|
|
if (FlxG.game.contains(video)) FlxG.game.removeChild(video);
|
|
|
|
}
|
|
|
|
|
|
|
|
super.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback executed when the video stream loads.
|
|
|
|
* @param metaData The metadata of the video
|
|
|
|
*/
|
|
|
|
public function onClientMetaData(metaData:Dynamic):Void
|
2023-01-23 03:25:45 +00:00
|
|
|
{
|
|
|
|
video.attachNetStream(netStream);
|
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
onVideoReady();
|
|
|
|
}
|
|
|
|
|
|
|
|
function onVideoReady():Void
|
|
|
|
{
|
2023-01-23 03:25:45 +00:00
|
|
|
video.width = FlxG.width;
|
|
|
|
video.height = FlxG.height;
|
2024-03-19 19:56:00 +00:00
|
|
|
|
|
|
|
videoAvailable = true;
|
|
|
|
|
|
|
|
FunkinSound.onVolumeChanged.add(onVolumeChanged);
|
|
|
|
onVolumeChanged(FlxG.sound.muted ? 0 : FlxG.sound.volume);
|
|
|
|
|
|
|
|
makeGraphic(Std.int(video.width), Std.int(video.height), FlxColor.TRANSPARENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
function onVolumeChanged(volume:Float):Void
|
|
|
|
{
|
|
|
|
netStream.soundTransform = new SoundTransform(volume);
|
2023-01-23 03:25:45 +00:00
|
|
|
}
|
|
|
|
|
2024-03-19 19:56:00 +00:00
|
|
|
function onNetConnectionNetStatus(event:NetStatusEvent):Void
|
2023-01-23 03:25:45 +00:00
|
|
|
{
|
|
|
|
if (event.info.code == 'NetStream.Play.Complete') finishVideo();
|
|
|
|
}
|
2021-04-18 03:19:33 +00:00
|
|
|
}
|