first commit
This commit is contained in:
448
Assets/AVProVideo/Runtime/Scripts/Components/DisplayIMGUI.cs
Normal file
448
Assets/AVProVideo/Runtime/Scripts/Components/DisplayIMGUI.cs
Normal file
@@ -0,0 +1,448 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2015-2025 RenderHeads Ltd. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define UNITY_PLATFORM_SUPPORTS_LINEAR
|
||||
|
||||
#if UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
|
||||
#define UNITY_PLATFORM_SUPPORTS_VIDEOASPECTRATIO
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace RenderHeads.Media.AVProVideo
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays the video from MediaPlayer component using IMGUI
|
||||
/// </summary>
|
||||
[AddComponentMenu("AVPro Video/Display IMGUI", 200)]
|
||||
[HelpURL("https://www.renderheads.com/products/avpro-video/")]
|
||||
[ExecuteInEditMode]
|
||||
public class DisplayIMGUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
MediaPlayer _mediaPlayer = null;
|
||||
public MediaPlayer Player
|
||||
{
|
||||
get
|
||||
{
|
||||
return _mediaPlayer;
|
||||
}
|
||||
set
|
||||
{
|
||||
_mediaPlayer = value;
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
ScaleMode _scaleMode = ScaleMode.ScaleToFit;
|
||||
public ScaleMode ScaleMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return _scaleMode;
|
||||
}
|
||||
set
|
||||
{
|
||||
_scaleMode = value;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
Color _color = UnityEngine.Color.white;
|
||||
public Color Color
|
||||
{
|
||||
get
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
set
|
||||
{
|
||||
_color = value;
|
||||
}
|
||||
}
|
||||
|
||||
[FormerlySerializedAs("_alphaBlend")]
|
||||
[SerializeField] bool _allowTransparency = false;
|
||||
public bool AllowTransparency
|
||||
{
|
||||
get
|
||||
{
|
||||
return _allowTransparency;
|
||||
}
|
||||
set
|
||||
{
|
||||
_allowTransparency = value;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
bool _useDepth = false;
|
||||
public bool UseDepth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _useDepth;
|
||||
}
|
||||
set
|
||||
{
|
||||
_useDepth = value;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
int _depth = 0;
|
||||
public int Depth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _depth;
|
||||
}
|
||||
set
|
||||
{
|
||||
_depth = value;
|
||||
}
|
||||
}
|
||||
|
||||
[Header("Area")]
|
||||
|
||||
[FormerlySerializedAs("_fullScreen")]
|
||||
[SerializeField]
|
||||
bool _isAreaFullScreen = true;
|
||||
public bool IsAreaFullScreen
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isAreaFullScreen;
|
||||
}
|
||||
set
|
||||
{
|
||||
_isAreaFullScreen = value;
|
||||
}
|
||||
}
|
||||
|
||||
[FormerlySerializedAs("_x")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField]
|
||||
float _areaX = 0f;
|
||||
public float AreaX
|
||||
{
|
||||
get
|
||||
{
|
||||
return _areaX;
|
||||
}
|
||||
set
|
||||
{
|
||||
_areaX = value;
|
||||
}
|
||||
}
|
||||
|
||||
[FormerlySerializedAs("_y")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField]
|
||||
float _areaY = 0f;
|
||||
public float AreaY
|
||||
{
|
||||
get
|
||||
{
|
||||
return _areaY;
|
||||
}
|
||||
set
|
||||
{
|
||||
_areaY = value;
|
||||
}
|
||||
}
|
||||
|
||||
[FormerlySerializedAs("_width")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField] float _areaWidth = 1f;
|
||||
public float AreaWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _areaWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
_areaWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
[FormerlySerializedAs("_height")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField] float _areaHeight = 1f;
|
||||
public float AreaHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return _areaHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
_areaHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
[FormerlySerializedAs("_displayInEditor")]
|
||||
[SerializeField] bool _showAreaInEditor = false;
|
||||
public bool ShowAreaInEditor
|
||||
{
|
||||
get
|
||||
{
|
||||
return _showAreaInEditor;
|
||||
}
|
||||
set
|
||||
{
|
||||
_showAreaInEditor = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static Shader _shaderAlphaPacking;
|
||||
private Material _material;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Disabling useGUILayout lets you skip the GUI layout phase which helps performance, but this also breaks the GUI.depth usage.
|
||||
if (!_useDepth)
|
||||
{
|
||||
this.useGUILayout = false;
|
||||
}
|
||||
|
||||
if (!_shaderAlphaPacking)
|
||||
{
|
||||
_shaderAlphaPacking = Shader.Find("AVProVideo/Internal/IMGUI/Texture Transparent");
|
||||
if (!_shaderAlphaPacking)
|
||||
{
|
||||
Debug.LogError("[AVProVideo] Missing shader 'AVProVideo/Internal/IMGUI/Texture Transparent'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_mediaPlayer != null)
|
||||
{
|
||||
SetupMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
// Destroy existing material
|
||||
if (_material != null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
Material.DestroyImmediate(_material);
|
||||
#else
|
||||
Material.Destroy(_material);
|
||||
#endif
|
||||
_material = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Shader GetRequiredShader()
|
||||
{
|
||||
// [MOZ] Always default to the alpha packed shader for now to force using the material rendering path
|
||||
// in OnGUI. This fixed issues with incorrect colourisation and orientation/cropping for certain videos.
|
||||
Shader result = _shaderAlphaPacking;
|
||||
#if false
|
||||
if (result == null && _mediaPlayer.TextureProducer != null)
|
||||
{
|
||||
switch (_mediaPlayer.TextureProducer.GetTextureAlphaPacking())
|
||||
{
|
||||
case AlphaPacking.None:
|
||||
break;
|
||||
case AlphaPacking.LeftRight:
|
||||
case AlphaPacking.TopBottom:
|
||||
result = _shaderAlphaPacking;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_PLATFORM_SUPPORTS_LINEAR
|
||||
if (result == null && _mediaPlayer.Info != null)
|
||||
{
|
||||
// If the player does support generating sRGB textures then we need to use a shader to convert them for display via IMGUI
|
||||
if (QualitySettings.activeColorSpace == ColorSpace.Linear && !_mediaPlayer.Info.PlayerSupportsLinearColorSpace())
|
||||
{
|
||||
result = _shaderAlphaPacking;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (result == null && _mediaPlayer.TextureProducer != null)
|
||||
{
|
||||
if (_mediaPlayer.TextureProducer.GetTextureCount() == 2)
|
||||
{
|
||||
result = _shaderAlphaPacking;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SetupMaterial()
|
||||
{
|
||||
// Get required shader
|
||||
Shader currentShader = null;
|
||||
if (_material != null)
|
||||
{
|
||||
currentShader = _material.shader;
|
||||
}
|
||||
Shader nextShader = GetRequiredShader();
|
||||
|
||||
// If the shader requirement has changed
|
||||
if (currentShader != nextShader)
|
||||
{
|
||||
// Destroy existing material
|
||||
if (_material != null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
Material.DestroyImmediate(_material);
|
||||
#else
|
||||
Material.Destroy(_material);
|
||||
#endif
|
||||
_material = null;
|
||||
}
|
||||
|
||||
// Create new material
|
||||
if (nextShader != null)
|
||||
{
|
||||
_material = new Material(nextShader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void DrawArea()
|
||||
{
|
||||
Rect rect = GetAreaRect();
|
||||
Rect uv = rect;
|
||||
uv.x /= Screen.width;
|
||||
uv.width /= Screen.width;
|
||||
uv.y /= Screen.height;
|
||||
uv.height /= Screen.height;
|
||||
uv.width *= 16f;
|
||||
uv.height *= 16f;
|
||||
uv.x += 0.5f;
|
||||
uv.y += 0.5f;
|
||||
Texture2D icon = Resources.Load<Texture2D>("AVProVideoIcon");
|
||||
GUI.depth = _depth;
|
||||
GUI.color = _color;
|
||||
GUI.DrawTextureWithTexCoords(rect, icon, uv);
|
||||
}
|
||||
#endif
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (_showAreaInEditor && !Application.isPlaying)
|
||||
{
|
||||
DrawArea();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_mediaPlayer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Texture texture = null;
|
||||
if (_showAreaInEditor)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
texture = Texture2D.whiteTexture;
|
||||
#endif
|
||||
}
|
||||
texture = VideoRender.GetTexture(_mediaPlayer, 0);
|
||||
if (_mediaPlayer.Info != null && !_mediaPlayer.Info.HasVideo())
|
||||
{
|
||||
texture = null;
|
||||
}
|
||||
|
||||
if (texture != null)
|
||||
{
|
||||
bool isTextureVisible = (_color.a > 0f || !_allowTransparency);
|
||||
if (isTextureVisible)
|
||||
{
|
||||
GUI.depth = _depth;
|
||||
GUI.color = _color;
|
||||
|
||||
Rect rect = GetAreaRect();
|
||||
|
||||
// TODO: change this to a material-only path so we only have a single drawing path
|
||||
if (_material != null)
|
||||
{
|
||||
// TODO: Only setup material when needed
|
||||
VideoRender.SetupMaterialForMedia(_material, _mediaPlayer);
|
||||
|
||||
// NOTE: It seems that Graphics.DrawTexture() behaves differently than GUI.DrawTexture() when it comes to sRGB writing
|
||||
// on newer versions of Unity (at least 2018.2.19 and above), so now we have to force the conversion to sRGB on writing
|
||||
bool restoreSRGBWrite = false;
|
||||
#if UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
|
||||
if (QualitySettings.activeColorSpace == ColorSpace.Linear && !GL.sRGBWrite)
|
||||
{
|
||||
restoreSRGBWrite = true;
|
||||
}
|
||||
#endif
|
||||
if (restoreSRGBWrite)
|
||||
{
|
||||
GL.sRGBWrite = true;
|
||||
}
|
||||
|
||||
VideoRender.DrawTexture(rect, texture, _scaleMode, _mediaPlayer.TextureProducer.GetTextureAlphaPacking(), _mediaPlayer.TextureProducer.GetTexturePixelAspectRatio(), _material);
|
||||
|
||||
if (restoreSRGBWrite)
|
||||
{
|
||||
GL.sRGBWrite = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool requiresVerticalFlip = false;
|
||||
if (_mediaPlayer.TextureProducer != null)
|
||||
{
|
||||
requiresVerticalFlip = _mediaPlayer.TextureProducer.RequiresVerticalFlip();
|
||||
}
|
||||
if (requiresVerticalFlip)
|
||||
{
|
||||
GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), new Vector2(0f, rect.y + (rect.height / 2f)));
|
||||
}
|
||||
#if UNITY_PLATFORM_SUPPORTS_VIDEOASPECTRATIO
|
||||
float par = _mediaPlayer.TextureProducer.GetTexturePixelAspectRatio();
|
||||
if (par > 0f)
|
||||
{
|
||||
if (par > 1f)
|
||||
{
|
||||
GUIUtility.ScaleAroundPivot(new Vector2(par, 1f), new Vector2(rect.x + (rect.width / 2f), rect.y + (rect.height / 2f)));
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIUtility.ScaleAroundPivot(new Vector2(1f, 1f/par), new Vector2(rect.x + (rect.width / 2f), rect.y + (rect.height / 2f)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
GUI.DrawTexture(rect, texture, _scaleMode, _allowTransparency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Rect GetAreaRect()
|
||||
{
|
||||
Rect rect;
|
||||
if (_isAreaFullScreen)
|
||||
{
|
||||
rect = new Rect(0.0f, 0.0f, Screen.width, Screen.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect = new Rect(_areaX * (Screen.width - 1), _areaY * (Screen.height - 1), _areaWidth * Screen.width, _areaHeight * Screen.height);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user