Files

189 lines
5.4 KiB
C#

using System.Collections.Generic;
using UnityEngine.Experimental.UIElements;
using UnityEngine;
using UnityEditor.Experimental.UIElements;
using UnityEngine.Video;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI.GraphView
{
public class VideoPlayerElement : VisualContainer
{
private VideoPlayer _player;
private Scene _tempScene;
private Toolbar _toolbar;
private TextElement _header;
private Image _videoProxy;
public VideoPlayerElement()
{
// Constructing Items
_header = new TextElement() {
text = "Using Focused Search",
name = "header",
};
_videoProxy = new Image()
{
name = "video-proxy",
image = Resources.Load<Texture2D>("videoStill"),
scaleMode = ScaleMode.ScaleToFit,
};
_toolbar = new Toolbar
{
// Add buttons by hand in order to set callbacks
new ToolbarButton(Play) { text = "Play", name = "button-play" },
new ToolbarButton(Pause) { text = "Pause", name = "button-pause" }
};
// Adding Items
Add(_header);
Add(_videoProxy);
Add(_toolbar);
}
private void OnEnable()
{
ShowFrame();
RegisterCallback<MouseDownEvent>(OnMouseDown);
}
private void OnDisable()
{
UnregisterCallback<MouseDownEvent>(OnMouseDown);
if (_tempScene != null && _tempScene.IsValid())
{
EditorSceneManager.UnloadSceneAsync(_tempScene);
}
}
private void OnMouseDown(MouseDownEvent evt)
{
PlayPauseToggle();
}
public void PlayPauseToggle()
{
if (GetCurrentPlayer().isPlaying)
{
Pause();
}
else if (GetCurrentPlayer().isPaused)
{
Play();
}
}
public void Play()
{
GetCurrentPlayer().Play();
}
public void Pause()
{
GetCurrentPlayer().Pause();
}
public void LoadVideo(string url)
{
var player = GetCurrentPlayer();
player.url = url;
player.sendFrameReadyEvents = true;
player.frameReady += OnFrameReady;
player.isLooping = true;
ShowFrame();
}
public void ShowFrame()
{
var player = GetCurrentPlayer();
if(player == null || string.IsNullOrEmpty(player.url))
{
return;
}
player.frameReady += PauseOnNextFrame;
player.Play();
}
public void UnloadVideo()
{
var player = GetCurrentPlayer();
player.url = null;
player.sendFrameReadyEvents = false;
player.frameReady -= OnFrameReady;
}
private void OnFrameReady(VideoPlayer source, long frameIdx)
{
_videoProxy.image = source.texture;
MarkDirtyRepaint();
}
private void PauseOnNextFrame(VideoPlayer source, long frameIdx)
{
var player = GetCurrentPlayer();
player.frameReady -= PauseOnNextFrame;
player.Pause();
}
private Scene GetTempScene()
{
if (_tempScene == null)
{
_tempScene = EditorSceneManager.NewPreviewScene();
var root = new GameObject("VideoPlayer");
EditorSceneManager.MoveGameObjectToScene(root, _tempScene);
}
return _tempScene;
}
private VideoPlayer GetCurrentPlayer()
{
// Try to get player from scene if it's not cached
if (_player == null)
{
_player = GetTempScene().GetRootGameObjects()[0].GetComponent<VideoPlayer>();
// Make new player if it doesn't exist in the scene
if (_player == null)
{
_player = GetTempScene().GetRootGameObjects()[0].AddComponent<VideoPlayer>();
_player.renderMode = VideoRenderMode.APIOnly;
_player.source = VideoSource.Url;
_player.audioOutputMode = VideoAudioOutputMode.None;
_player.playOnAwake = false;
_player.Prepare();
}
}
return _player;
}
public new class UxmlFactory : UxmlFactory<VideoPlayerElement, UxmlTraits> { }
public new class UxmlTraits : UnityEngine.Experimental.UIElements.UxmlTraits
{
UxmlStringAttributeDescription m_Url = new UxmlStringAttributeDescription { name = "url-attr", defaultValue = "" };
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription { get; }
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
base.Init(ve, bag, cc);
var ate = ve as VideoPlayerElement;
ate.Clear();
ate.urlAttr = m_Url.GetValueFromBag(bag, cc);
}
}
public string urlAttr { get; set; }
}
}