first commit

This commit is contained in:
2026-02-09 20:10:14 +08:00
commit 47a5cff08b
2638 changed files with 322636 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2025 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the ApplyToFarPlane component
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(ApplyToFarPlane))]
public class ApplyToFarPlaneEditor : UnityEditor.Editor
{
private SerializedProperty _mainColor;
private SerializedProperty _chroma;
private SerializedProperty _alpha;
private SerializedProperty _aspectRatio;
private SerializedProperty _drawOffset;
private SerializedProperty _customScaling;
private SerializedProperty _propTextureOffset;
private SerializedProperty _propTextureScale;
private SerializedProperty _propMediaPlayer;
private SerializedProperty _propMaterial;
private SerializedProperty _propDefaultTexture;
private SerializedProperty _mat;
private SerializedProperty _cam;
void OnEnable()
{
_mainColor = this.CheckFindProperty("_mainColor");
_chroma = this.CheckFindProperty("_chroma");
_alpha = this.CheckFindProperty("_alpha");
_aspectRatio = this.CheckFindProperty("_aspectRatio");
_drawOffset = this.CheckFindProperty("_drawOffset");
_customScaling = this.CheckFindProperty("_customScaling");
_propTextureOffset = this.CheckFindProperty("_offset");
_propTextureScale = this.CheckFindProperty("_scale");
_propMediaPlayer = this.CheckFindProperty("_media");
_propMaterial = this.CheckFindProperty("_material");
_propDefaultTexture = this.CheckFindProperty("_defaultTexture");
_mat = this.CheckFindProperty("_material");
_cam = this.CheckFindProperty("_camera");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
ApplyToFarPlane tar = (ApplyToFarPlane)target;
// cant change of the material properties if the material does not exist
if (_propMaterial == null)
return;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propMediaPlayer);
// when any of the elements are changed send a call back to the
// target object to update the material
// Color
EditorGUILayout.PropertyField(_mainColor);
if (_mainColor.serializedObject.ApplyModifiedProperties())
tar.UpdateMaterialProperties(0);
// Chroma (texture)
EditorGUILayout.PropertyField(_chroma);
if (_chroma.serializedObject.ApplyModifiedProperties())
tar.UpdateMaterialProperties(4);
// Alpha slider
EditorGUILayout.Slider(_alpha, 0, 1, "Alpha");
if (_alpha.serializedObject.ApplyModifiedProperties())
tar.UpdateMaterialProperties(5);
EditorGUILayout.Space();
// Aspect Ratio (Disabled when custom scaling is set)
var toggle = tar.CustomScaling.x != 0 && tar.CustomScaling.y != 0;
EditorGUI.BeginDisabledGroup(toggle);
EditorGUILayout.PropertyField(_aspectRatio);
if (_aspectRatio.serializedObject.ApplyModifiedProperties())
tar.UpdateMaterialProperties(7);
EditorGUI.EndDisabledGroup();
// custom scaling (Vec2 of the width and height to set)
EditorGUILayout.PropertyField(_customScaling);
if (_customScaling.serializedObject.ApplyModifiedProperties())
tar.UpdateMaterialProperties(9);
// Draw offset to add to the image when rendering with shader so the image can be moved around the screen
EditorGUILayout.PropertyField(_drawOffset);
if (_drawOffset.serializedObject.ApplyModifiedProperties())
tar.UpdateMaterialProperties(8);
// default texture to show
EditorGUILayout.PropertyField(_propDefaultTexture);
// texture offset
EditorGUILayout.PropertyField(_propTextureOffset);
// texture scaling
EditorGUILayout.PropertyField(_propTextureScale);
EditorGUILayout.Space();
// camera to render to
EditorGUILayout.PropertyField(_cam);
// the material that is being used (automaitcally set if not set by user)
EditorGUILayout.PropertyField(_mat);
// when items have been updated update the displayed material
// to ensure that the correct thing is being shown
serializedObject.ApplyModifiedProperties();
bool wasModified = EditorGUI.EndChangeCheck();
if (Application.isPlaying && wasModified)
{
foreach (Object obj in this.targets)
{
((ApplyToFarPlane)obj).ForceUpdate();
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b60bc9fcd12e94c429ac2fbfcbacfd64
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,112 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the ApplyToMaterial component
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(ApplyToMaterial))]
public class ApplyToMaterialEditor : UnityEditor.Editor
{
private static readonly GUIContent _guiTextTextureProperty = new GUIContent("Texture Property");
private SerializedProperty _propTextureOffset;
private SerializedProperty _propTextureScale;
private SerializedProperty _propMediaPlayer;
private SerializedProperty _propMaterial;
private SerializedProperty _propTexturePropertyName;
private SerializedProperty _propDefaultTexture;
private GUIContent[] _materialTextureProperties = new GUIContent[0];
void OnEnable()
{
_propTextureOffset = this.CheckFindProperty("_offset");
_propTextureScale = this.CheckFindProperty("_scale");
_propMediaPlayer = this.CheckFindProperty("_media");
_propMaterial = this.CheckFindProperty("_material");
_propTexturePropertyName = this.CheckFindProperty("_texturePropertyName");
_propDefaultTexture = this.CheckFindProperty("_defaultTexture");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
if (_propMaterial == null)
{
return;
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propMediaPlayer);
EditorGUILayout.PropertyField(_propDefaultTexture);
EditorGUILayout.PropertyField(_propMaterial);
bool hasKeywords = false;
int texturePropertyIndex = 0;
if (_propMaterial.objectReferenceValue != null)
{
Material mat = (Material)(_propMaterial.objectReferenceValue);
if (mat.shaderKeywords.Length > 0)
{
hasKeywords = true;
}
MaterialProperty[] matProps = MaterialEditor.GetMaterialProperties(new UnityEngine.Object[] { mat });
List<GUIContent> items = new List<GUIContent>(16);
foreach (MaterialProperty matProp in matProps)
{
#if UNITY_6000_2_OR_NEWER
if (matProp.propertyType == UnityEngine.Rendering.ShaderPropertyType.Texture)
#else
if (matProp.type == MaterialProperty.PropType.Texture)
#endif
{
if (matProp.name == _propTexturePropertyName.stringValue)
{
texturePropertyIndex = items.Count;
}
items.Add(new GUIContent(matProp.name));
}
}
_materialTextureProperties = items.ToArray();
}
int newTexturePropertyIndex = EditorGUILayout.Popup(_guiTextTextureProperty, texturePropertyIndex, _materialTextureProperties);
if (newTexturePropertyIndex >= 0 && newTexturePropertyIndex < _materialTextureProperties.Length)
{
_propTexturePropertyName.stringValue = _materialTextureProperties[newTexturePropertyIndex].text;
}
if (hasKeywords && _propTexturePropertyName.stringValue != Helper.UnityBaseTextureName)
{
EditorGUILayout.HelpBox("When using an uber shader you may need to enable the keywords on a material for certain texture slots to take effect. You can sometimes achieve this (eg with Standard shader) by putting a dummy texture into the texture slot.", MessageType.Info);
}
EditorGUILayout.PropertyField(_propTextureOffset);
EditorGUILayout.PropertyField(_propTextureScale);
serializedObject.ApplyModifiedProperties();
bool wasModified = EditorGUI.EndChangeCheck();
if (Application.isPlaying && wasModified)
{
foreach (Object obj in this.targets)
{
((ApplyToMaterial)obj).ForceUpdate();
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 60268ddd706f2f1469acb32edab1dea9
timeCreated: 1591790256
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,187 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the ApplyToMesh component
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(ApplyToMesh))]
public class ApplyToMeshEditor : UnityEditor.Editor
{
private static readonly GUIContent _guiTextTextureProperty = new GUIContent("Texture Property");
private SerializedProperty _propTextureOffset;
private SerializedProperty _propTextureScale;
private SerializedProperty _propMediaPlayer;
private SerializedProperty _propRenderer;
private SerializedProperty _propMaterialIndex;
private SerializedProperty _propTexturePropertyName;
private SerializedProperty _propDefaultTexture;
private SerializedProperty _propAutomaticStereoPacking;
private SerializedProperty _propOverrideStereoPacking;
private SerializedProperty _propStereoRedGreenTint;
private GUIContent[] _materialTextureProperties = new GUIContent[0];
void OnEnable()
{
_propTextureOffset = this.CheckFindProperty("_offset");
_propTextureScale = this.CheckFindProperty("_scale");
_propMediaPlayer = this.CheckFindProperty("_media");
_propRenderer = this.CheckFindProperty("_renderer");
_propMaterialIndex = this.CheckFindProperty("_materialIndex");
_propTexturePropertyName = this.CheckFindProperty("_texturePropertyName");
_propDefaultTexture = this.CheckFindProperty("_defaultTexture");
_propAutomaticStereoPacking = this.CheckFindProperty("_automaticStereoPacking");
_propOverrideStereoPacking = this.CheckFindProperty("_overrideStereoPacking");
_propStereoRedGreenTint = this.CheckFindProperty("_stereoRedGreenTint");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
if (_propRenderer == null)
{
return;
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propMediaPlayer);
EditorGUILayout.PropertyField(_propDefaultTexture);
EditorGUILayout.PropertyField(_propRenderer);
bool hasKeywords = false;
int materialCount = 0;
int texturePropertyIndex = 0;
_materialTextureProperties = new GUIContent[0];
if (_propRenderer.objectReferenceValue != null)
{
Renderer r = (Renderer)(_propRenderer.objectReferenceValue);
materialCount = r.sharedMaterials.Length;
List<Material> nonNullMaterials = new List<Material>(r.sharedMaterials);
// Remove any null materials (otherwise MaterialEditor.GetMaterialProperties() errors)
for (int i = 0; i < nonNullMaterials.Count; i++)
{
if (nonNullMaterials[i] == null)
{
nonNullMaterials.RemoveAt(i);
i--;
}
}
if (nonNullMaterials.Count > 0)
{
// Detect if there are any keywords
foreach (Material mat in nonNullMaterials)
{
if (mat.shaderKeywords.Length > 0)
{
hasKeywords = true;
break;
}
}
// Get unique list of texture property names
List<GUIContent> items = new List<GUIContent>(16);
List<string> textureNames = new List<string>(8);
foreach (Material mat in nonNullMaterials)
{
// NOTE: we process each material separately instead of passing them all into MaterialEditor.GetMaterialProperties() as it errors if the materials have different properties
MaterialProperty[] matProps = MaterialEditor.GetMaterialProperties(new Object[] { mat });
foreach (MaterialProperty matProp in matProps)
{
#if UNITY_6000_2_OR_NEWER
if (matProp.propertyType == UnityEngine.Rendering.ShaderPropertyType.Texture)
#else
if (matProp.type == MaterialProperty.PropType.Texture)
#endif
{
if (!textureNames.Contains(matProp.name))
{
if (matProp.name == _propTexturePropertyName.stringValue)
{
texturePropertyIndex = items.Count;
}
textureNames.Add(matProp.name);
items.Add(new GUIContent(matProp.name));
}
}
}
}
_materialTextureProperties = items.ToArray();
}
}
if (materialCount > 0)
{
GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("All Materials");
EditorGUI.BeginChangeCheck();
EditorGUILayout.Toggle(_propMaterialIndex.intValue < 0);
if (EditorGUI.EndChangeCheck())
{
if (_propMaterialIndex.intValue < 0)
{
_propMaterialIndex.intValue = 0;
}
else
{
_propMaterialIndex.intValue = -1;
}
}
GUILayout.EndHorizontal();
if (_propMaterialIndex.intValue >= 0)
{
GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Material Index");
_propMaterialIndex.intValue = EditorGUILayout.IntSlider(_propMaterialIndex.intValue, 0, materialCount - 1);
GUILayout.EndHorizontal();
}
}
int newTexturePropertyIndex = EditorGUILayout.Popup(_guiTextTextureProperty, texturePropertyIndex, _materialTextureProperties);
if (newTexturePropertyIndex >= 0 && newTexturePropertyIndex < _materialTextureProperties.Length)
{
_propTexturePropertyName.stringValue = _materialTextureProperties[newTexturePropertyIndex].text;
}
if (hasKeywords && _propTexturePropertyName.stringValue != Helper.UnityBaseTextureName)
{
EditorGUILayout.HelpBox("When using an uber shader you may need to enable the keywords on a material for certain texture slots to take effect. You can sometimes achieve this (eg with Standard shader) by putting a dummy texture into the texture slot.", MessageType.Info);
}
EditorGUILayout.PropertyField(_propTextureOffset);
EditorGUILayout.PropertyField(_propTextureScale);
EditorGUILayout.PropertyField(_propAutomaticStereoPacking);
if (!_propAutomaticStereoPacking.boolValue)
{
EditorGUILayout.PropertyField(_propOverrideStereoPacking);
}
EditorGUILayout.PropertyField(_propStereoRedGreenTint);
serializedObject.ApplyModifiedProperties();
bool wasModified = EditorGUI.EndChangeCheck();
if (Application.isPlaying && wasModified)
{
foreach (Object obj in this.targets)
{
((ApplyToMesh)obj).ForceUpdate();
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 114ac842bfcaf0745a5e45cb2a7d6559
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,103 @@
using UnityEditor;
using UnityEngine;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the AudioOutput component
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(AudioOutput))]
public class AudioOutputEditor : UnityEditor.Editor
{
private static readonly GUIContent _guiTextChannel = new GUIContent("Channel");
private static readonly GUIContent _guiTextChannels = new GUIContent("Channels");
private static readonly string[] _channelMaskOptions = { "1", "2", "3", "4", "5", "6", "7", "8" };
private SerializedProperty _propMediaPlayer;
private SerializedProperty _propAudioOutputMode;
private SerializedProperty _propSupportPositionalAudio;
private SerializedProperty _propChannelMask;
private int _unityAudioSampleRate;
private int _unityAudioSpeakerCount;
private string _bufferedMs;
void OnEnable()
{
_propMediaPlayer = this.CheckFindProperty("_mediaPlayer");
_propAudioOutputMode = this.CheckFindProperty("_audioOutputMode");
_propSupportPositionalAudio = this.CheckFindProperty("_supportPositionalAudio");
_propChannelMask = this.CheckFindProperty("_channelMask");
_unityAudioSampleRate = Helper.GetUnityAudioSampleRate();
_unityAudioSpeakerCount = Helper.GetUnityAudioSpeakerCount();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
AudioOutput audioOutput = (AudioOutput)this.target;
EditorGUILayout.PropertyField(_propMediaPlayer);
EditorGUILayout.PropertyField(_propAudioOutputMode);
EditorGUILayout.PropertyField(_propSupportPositionalAudio);
// Display the channel mask as either a bitfield or value slider
if ((AudioOutput.AudioOutputMode)_propAudioOutputMode.enumValueIndex == AudioOutput.AudioOutputMode.MultipleChannels)
{
_propChannelMask.intValue = EditorGUILayout.MaskField(_guiTextChannels, _propChannelMask.intValue, _channelMaskOptions);
}
else
{
int prevVal = 0;
for(int i = 0; i < 8; ++i)
{
if((_propChannelMask.intValue & (1 << i)) > 0)
{
prevVal = i;
break;
}
}
int newVal = Mathf.Clamp(EditorGUILayout.IntSlider(_guiTextChannel, prevVal, 0, 7), 0, 7);
_propChannelMask.intValue = 1 << newVal;
}
GUILayout.Label("Unity Audio", EditorStyles.boldLabel);
EditorGUILayout.LabelField("Speakers", _unityAudioSpeakerCount.ToString());
EditorGUILayout.LabelField("Sample Rate", _unityAudioSampleRate.ToString() + "hz");
EditorGUILayout.Space();
if (audioOutput != null)
{
if (audioOutput.Player != null && audioOutput.Player.Control != null)
{
int channelCount = audioOutput.Player.Control.GetAudioChannelCount();
if (channelCount >= 0)
{
GUILayout.Label("Media Audio", EditorStyles.boldLabel);
EditorGUILayout.LabelField("Channels: " + channelCount);
AudioChannelMaskFlags audioChannels = audioOutput.Player.Control.GetAudioChannelMask();
GUILayout.Label(audioChannels.ToString(), EditorHelper.IMGUI.GetWordWrappedTextAreaStyle());
if (Time.frameCount % 4 == 0)
{
int bufferedSampleCount = audioOutput.Player.Control.GetAudioBufferedSampleCount();
float bufferedMs = (bufferedSampleCount * 1000f) / (_unityAudioSampleRate * channelCount);
_bufferedMs = "Buffered: " + bufferedMs.ToString("F2") + "ms";
}
EditorGUILayout.LabelField(_bufferedMs);
EditorGUILayout.Space();
}
}
}
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f7852924144fc064aad785e5985b5402
timeCreated: 1495783665
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the DisplayIMGUI component
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(DisplayIMGUI))]
public class DisplayIMGUIEditor : UnityEditor.Editor
{
private SerializedProperty _propMediaPlayer;
private SerializedProperty _propScaleMode;
private SerializedProperty _propColor;
private SerializedProperty _propAllowTransparency;
private SerializedProperty _propUseDepth;
private SerializedProperty _propDepth;
private SerializedProperty _propAreaFullscreen;
private SerializedProperty _propAreaX;
private SerializedProperty _propAreaY;
private SerializedProperty _propAreaWidth;
private SerializedProperty _propAreaHeight;
private SerializedProperty _propShowAreaInEditor;
void OnEnable()
{
_propMediaPlayer = this.CheckFindProperty("_mediaPlayer");
_propScaleMode = this.CheckFindProperty("_scaleMode");
_propColor = this.CheckFindProperty("_color");
_propAllowTransparency = this.CheckFindProperty("_allowTransparency");
_propUseDepth = this.CheckFindProperty("_useDepth");
_propDepth = this.CheckFindProperty("_depth");
_propAreaFullscreen = this.CheckFindProperty("_isAreaFullScreen");
_propAreaX = this.CheckFindProperty("_areaX");
_propAreaY = this.CheckFindProperty("_areaY");
_propAreaWidth = this.CheckFindProperty("_areaWidth");
_propAreaHeight = this.CheckFindProperty("_areaHeight");
_propShowAreaInEditor = this.CheckFindProperty("_showAreaInEditor");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propMediaPlayer);
EditorGUILayout.PropertyField(_propScaleMode);
EditorGUILayout.PropertyField(_propColor);
EditorGUILayout.PropertyField(_propAllowTransparency);
EditorGUILayout.PropertyField(_propUseDepth);
if (_propUseDepth.boolValue)
{
EditorGUILayout.PropertyField(_propDepth);
}
// Area
EditorGUILayout.PropertyField(_propAreaFullscreen, new GUIContent("Full Screen"));
if (!_propAreaFullscreen.boolValue)
{
EditorGUILayout.PropertyField(_propAreaX, new GUIContent("X"));
EditorGUILayout.PropertyField(_propAreaY, new GUIContent("Y"));
EditorGUILayout.PropertyField(_propAreaWidth, new GUIContent("Width"));
EditorGUILayout.PropertyField(_propAreaHeight, new GUIContent("Height"));
}
EditorGUILayout.PropertyField(_propShowAreaInEditor, new GUIContent("Show in Editor"));
serializedObject.ApplyModifiedProperties();
// Force update
bool unhandledChanges = (EditorGUI.EndChangeCheck() && Application.isPlaying);
if (unhandledChanges)
{
foreach (Object obj in this.targets)
{
((DisplayIMGUI)obj).Update();
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8c822ced482d9444aa15d55b5f9d6e7a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,675 @@
#define AVPROVIDEO_SUPPORT_LIVEEDITMODE
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
//-----------------------------------------------------------------------------
// Copyright 2015-2025 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(MediaPlayer))]
public partial class MediaPlayerEditor : UnityEditor.Editor
{
internal const string SettingsPrefix = "AVProVideo-MediaPlayerEditor-";
private SerializedProperty _propAutoOpen;
private SerializedProperty _propAutoStart;
private SerializedProperty _propLoop;
private SerializedProperty _propRate;
private SerializedProperty _propPersistent;
private SerializedProperty _propFilter;
private SerializedProperty _propWrap;
private SerializedProperty _propAniso;
#if AVPRO_FEATURE_VIDEORESOLVE
private SerializedProperty _propUseVideoResolve;
private SerializedProperty _propVideoResolve;
private SerializedProperty _propVideoResolveOptions;
#endif
private SerializedProperty _propResample;
private SerializedProperty _propResampleMode;
private SerializedProperty _propResampleBufferSize;
private SerializedProperty _propVideoMapping;
private SerializedProperty _propForceFileFormat;
private SerializedProperty _propFallbackMediaHints;
private static Texture2D _icon;
private static bool _isTrialVersion = false;
private static GUIStyle _styleSectionBox = null;
private AnimCollapseSection _sectionMediaInfo;
private AnimCollapseSection _sectionDebug;
private AnimCollapseSection _sectionSettings;
private AnimCollapseSection _sectionAboutHelp;
private List<AnimCollapseSection> _settingSections = new List<AnimCollapseSection>(16);
private List<AnimCollapseSection> _platformSections = new List<AnimCollapseSection>(8);
[MenuItem("GameObject/Video/AVPro Video - Media Player", false, 100)]
public static void CreateMediaPlayerEditor()
{
GameObject go = new GameObject("MediaPlayer");
go.AddComponent<MediaPlayer>();
Selection.activeGameObject = go;
}
[MenuItem("GameObject/Video/AVPro Video - Media Player with Unity Audio", false, 101)]
public static void CreateMediaPlayerWithUnityAudioEditor()
{
GameObject go = new GameObject("MediaPlayer");
go.AddComponent<MediaPlayer>();
go.AddComponent<AudioSource>();
AudioOutput ao = go.AddComponent<AudioOutput>();
// Move the AudioOutput component above the AudioSource so that it acts as the audio generator
UnityEditorInternal.ComponentUtility.MoveComponentUp(ao);
Selection.activeGameObject = go;
}
private static void LoadSettings()
{
_platformIndex = EditorPrefs.GetInt(SettingsPrefix + "PlatformIndex", -1);
_showAlpha = EditorPrefs.GetBool(SettingsPrefix + "ShowAlphaChannel", false);
_showPreview = EditorPrefs.GetBool(SettingsPrefix + "ShowPreview", true);
_allowDeveloperMode = EditorPrefs.GetBool(SettingsPrefix + "AllowDeveloperMode", false);
_HTTPHeadersToggle = EditorPrefs.GetBool(SettingsPrefix + "HTTPHeadersToggle", false);
RecentItems.Load();
}
private void SaveSettings()
{
_sectionMediaInfo.Save();
_sectionDebug.Save();
_sectionSettings.Save();
_sectionAboutHelp.Save();
foreach (AnimCollapseSection section in _settingSections)
{
section.Save();
}
foreach (AnimCollapseSection section in _platformSections)
{
section.Save();
}
_sectionDevModeState.Save();
_sectionDevModeTexture.Save();
_sectionDevModePlaybackQuality.Save();
_sectionDevModeHapNotchLCDecoder.Save();
_sectionDevModeTimedMetadata.Save();
EditorPrefs.SetInt(SettingsPrefix + "PlatformIndex", _platformIndex);
EditorPrefs.SetBool(SettingsPrefix + "ShowAlphaChannel", _showAlpha);
EditorPrefs.SetBool(SettingsPrefix + "ShowPreview", _showPreview);
EditorPrefs.SetBool(SettingsPrefix + "AllowDeveloperMode", _allowDeveloperMode);
EditorPrefs.SetBool(SettingsPrefix + "HTTPHeadersToggle", _HTTPHeadersToggle);
RecentItems.Save();
}
//[MenuItem("RenderHeads/AVPro Video/Reset Settings", false, 101)]
internal static void DeleteSettings()
{
EditorPrefs.DeleteKey(SettingsPrefix + "PlatformIndex");
EditorPrefs.DeleteKey(SettingsPrefix + "ShowAlphaChannel");
EditorPrefs.DeleteKey(SettingsPrefix + "AllowDeveloperMode");
EditorPrefs.DeleteKey(SettingsPrefix + "HTTPHeadersToggle");
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Media"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Debug"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Settings"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("About / Help"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Source"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Main"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Audio"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Visual"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Network"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Media"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Subtitles"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Events"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Platform Specific"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName("Global"));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.Windows).text));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.macOS).text));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.Android).text));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.OpenHarmony).text));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.iOS).text));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.tvOS).text));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.visionOS).text));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.WindowsUWP).text));
EditorPrefs.DeleteKey(AnimCollapseSection.GetPrefName(GetPlatformButtonContent(Platform.WebGL).text));
}
private void CreateSections()
{
const float colorSaturation = 0.66f;
Color mediaInfoColor = Color.HSVToRGB(0.55f, colorSaturation, 1f);
Color sourceColor = Color.HSVToRGB(0.4f, colorSaturation, 1f);
Color platformSpecificColor = Color.HSVToRGB(0.85f, colorSaturation, 1f);
Color platformColor = platformSpecificColor;
if (EditorGUIUtility.isProSkin)
{
platformColor *= 0.66f;
}
_sectionMediaInfo = new AnimCollapseSection("Media Info", false, false, OnInspectorGUI_MediaInfo, this, mediaInfoColor);
_sectionDebug = new AnimCollapseSection("Debug", false, true, OnInspectorGUI_Debug, this, Color.white);
_sectionSettings = new AnimCollapseSection("Settings", false, true, OnInspectorGUI_Settings, this, Color.white);
_sectionAboutHelp = new AnimCollapseSection("About / Help", false, false, OnInspectorGUI_About, this, Color.white);
_settingSections.Clear();
_settingSections.Add(new AnimCollapseSection("Source", false, true, OnInspectorGUI_Source, this, sourceColor));
_settingSections.Add(new AnimCollapseSection("Main", false, false, OnInspectorGUI_Main, this, Color.white));
_settingSections.Add(new AnimCollapseSection("Audio", false, false, OnInspectorGUI_Audio, this, Color.white));
_settingSections.Add(new AnimCollapseSection("Visual", true, false, OnInspectorGUI_Visual, this, Color.white));
//_settingSections.Add(new AnimCollapseSection("Network", true, false, OnInspectorGUI_Network, this, Color.white));
_settingSections.Add(new AnimCollapseSection("Subtitles", true, false, OnInspectorGUI_Subtitles, this, Color.white));
_settingSections.Add(new AnimCollapseSection("Events", true, false, OnInspectorGUI_Events, this, Color.white));
_settingSections.Add(new AnimCollapseSection("Platform Specific", true, false, OnInspectorGUI_PlatformOverrides, this, platformSpecificColor));
_settingSections.Add(new AnimCollapseSection("Global", true, false, OnInspectorGUI_GlobalSettings, this, Color.white));
_platformSections.Clear();
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.Windows), true, false, OnInspectorGUI_Override_Windows, this, platformColor, _platformSections));
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.macOS), true, false, OnInspectorGUI_Override_MacOSX, this, platformColor, _platformSections));
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.Android), true, false, OnInspectorGUI_Override_Android, this, platformColor, _platformSections));
#if UNITY_OPENHARMONY
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.OpenHarmony), true, false, OnInspectorGUI_Override_OpenHarmony, this, platformColor, _platformSections));
#endif
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.iOS), true, false, OnInspectorGUI_Override_iOS, this, platformColor, _platformSections));
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.tvOS), true, false, OnInspectorGUI_Override_tvOS, this, platformColor, _platformSections));
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.visionOS), true, false, OnInspectorGUI_Override_visionOS, this, platformColor, _platformSections));
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.WindowsUWP), true, false, OnInspectorGUI_Override_WindowsUWP, this, platformColor, _platformSections));
_platformSections.Add(new AnimCollapseSection(GetPlatformButtonContent(Platform.WebGL), true, false, OnInspectorGUI_Override_WebGL, this, platformColor, _platformSections));
_sectionDevModeState = new AnimCollapseSection("State", false, false, OnInspectorGUI_DevMode_State, this, Color.white);
_sectionDevModeTexture = new AnimCollapseSection("Texture", false, false, OnInspectorGUI_DevMode_Texture, this, Color.white);
_sectionDevModePlaybackQuality = new AnimCollapseSection("Presentation Quality", false, false, OnInspectorGUI_DevMode_PresentationQuality, this, Color.white);
_sectionDevModeHapNotchLCDecoder = new AnimCollapseSection("Hap/NotchLC Decoder", false, false, OnInspectorGUI_DevMode_HapNotchLCDecoder, this, Color.white);
_sectionDevModeTimedMetadata = new AnimCollapseSection("Timed Metadata", false, false, OnInspectorGUI_DevMode_TimedMetadata, this, Color.white);
}
private void ResolveProperties()
{
_propMediaSource = this.CheckFindProperty("_mediaSource");
_propMediaReference = this.CheckFindProperty("_mediaReference");
_propMediaPath = this.CheckFindProperty("_mediaPath");
_propAutoOpen = this.CheckFindProperty("_autoOpen");
_propAutoStart = this.CheckFindProperty("_autoPlayOnStart");
_propLoop = this.CheckFindProperty("_loop");
_propRate = this.CheckFindProperty("_playbackRate");
_propVolume = this.CheckFindProperty("_audioVolume");
_propBalance = this.CheckFindProperty("_audioBalance");
_propMuted = this.CheckFindProperty("_audioMuted");
_propPersistent = this.CheckFindProperty("_persistent");
_propEvents = this.CheckFindProperty("_events");
_propEventMask = this.CheckFindProperty("_eventMask");
_propPauseMediaOnAppPause = this.CheckFindProperty("_pauseMediaOnAppPause");
_propPlayMediaOnAppUnpause = this.CheckFindProperty("_playMediaOnAppUnpause");
_propFilter = this.CheckFindProperty("_textureFilterMode");
_propWrap = this.CheckFindProperty("_textureWrapMode");
_propAniso = this.CheckFindProperty("_textureAnisoLevel");
#if AVPRO_FEATURE_VIDEORESOLVE
_propUseVideoResolve = this.CheckFindProperty("_useVideoResolve");
_propVideoResolve = this.CheckFindProperty("_videoResolve");
_propVideoResolveOptions = this.CheckFindProperty("_videoResolveOptions");
#endif
_propVideoMapping = this.CheckFindProperty("_videoMapping");
_propForceFileFormat = this.CheckFindProperty("_forceFileFormat");
_propFallbackMediaHints = this.CheckFindProperty("_fallbackMediaHints");
_propSubtitles = this.CheckFindProperty("_sideloadSubtitles");
_propSubtitlePath = this.CheckFindProperty("_subtitlePath");
_propResample = this.CheckFindProperty("_useResampler");
_propResampleMode = this.CheckFindProperty("_resampleMode");
_propResampleBufferSize = this.CheckFindProperty("_resampleBufferSize");
_propAudioHeadTransform = this.CheckFindProperty("_audioHeadTransform");
_propAudioEnableFocus = this.CheckFindProperty("_audioFocusEnabled");
_propAudioFocusOffLevelDB = this.CheckFindProperty("_audioFocusOffLevelDB");
_propAudioFocusWidthDegrees = this.CheckFindProperty("_audioFocusWidthDegrees");
_propAudioFocusTransform = this.CheckFindProperty("_audioFocusTransform");
}
private static Texture GetPlatformIcon(Platform platform)
{
string iconName = string.Empty;
switch (platform)
{
case Platform.Windows:
case Platform.macOS:
iconName = "BuildSettings.Standalone.Small";
break;
case Platform.Android:
iconName = "BuildSettings.Android.Small";
break;
case Platform.OpenHarmony:
iconName = "BuildSettings.OpenHarmony.Small";
break;
case Platform.iOS:
iconName = "BuildSettings.iPhone.Small";
break;
case Platform.tvOS:
iconName = "BuildSettings.tvOS.Small";
break;
case Platform.visionOS:
#if AVPRO_VIDEO_VISIONOS_AVAILABLE
iconName = "BuildSettings.visionOS.Small";
#else
// We'll reuse the iOS icon for visionOS if the specific one isn't available
iconName = "BuildSettings.iPhone.Small";
#endif
break;
case Platform.WindowsUWP:
iconName = "BuildSettings.Metro.Small";
break;
case Platform.WebGL:
iconName = "BuildSettings.WebGL.Small";
break;
}
Texture iconTexture = null;
if (!string.IsNullOrEmpty(iconName))
{
iconTexture = EditorGUIUtility.IconContent(iconName).image;
}
return iconTexture;
}
private static GUIContent GetPlatformButtonContent(Platform platform)
{
return new GUIContent(Helper.GetPlatformName(platform), GetPlatformIcon(platform));
}
private void FixRogueEditorBug()
{
// NOTE: There seems to be a bug in Unity where the editor script will call OnEnable and OnDisable twice.
// This is resolved by setting the Window Layout mode to Default.
// It causes a problem (at least in Unity 2020.1.11) where the System.Action invocations (usd by AnimCollapseSection)
// seem to be in a different 'this' context and so their pointers to serializedObject is not the same, resulting in
// properties modified not marking the serialisedObject as dirty. To get around this issue we use this static bool
// so that OnEnable can only be called once.
// https://answers.unity.com/questions/1216599/custom-editor-gets-created-multiple-times-and-rece.html
#if UNITY_2022_3_OR_NEWER
var remainingBuggedEditors = FindObjectsByType<MediaPlayerEditor>(FindObjectsSortMode.None);
#else
var remainingBuggedEditors = FindObjectsOfType<MediaPlayerEditor>();
#endif
foreach(var editor in remainingBuggedEditors)
{
if (editor == this)
{
continue;
}
DestroyImmediate(editor);
}
}
private void OnEnable()
{
FixRogueEditorBug();
CreateSections();
LoadSettings();
_isTrialVersion = IsTrialVersion();
if (_platformNames == null)
{
_platformNames = new GUIContent[]
{
GetPlatformButtonContent(Platform.Windows),
GetPlatformButtonContent(Platform.macOS),
GetPlatformButtonContent(Platform.iOS),
GetPlatformButtonContent(Platform.tvOS),
GetPlatformButtonContent(Platform.visionOS),
GetPlatformButtonContent(Platform.Android),
GetPlatformButtonContent(Platform.WindowsUWP),
GetPlatformButtonContent(Platform.WebGL)
};
}
ResolveProperties();
}
private void OnDisable()
{
ClosePreview();
SaveSettings();
if (!Application.isPlaying)
{
// NOTE: For some reason when transitioning into Play mode, Dispose() is not called in the MediaPlayer if
// it was playing before the transition because all members are reset to null. So we must force this
// dispose of all resources to handle this case.
// Sadly it means we can't keep persistent playback in the inspector when it loses focus, but
// hopefully we can find a way to achieve this in the future
/*if (EditorApplication.isPlayingOrWillChangePlaymode)
{
// NOTE: This seems to work for the above issue, but
// we'd need to move it to the global event for when the play state changes
MediaPlayer.EditorAllPlayersDispose();
}*/
foreach (MediaPlayer player in this.targets)
{
player.ForceDispose();
}
}
}
private void CreateStyles()
{
if (_styleSectionBox == null)
{
_styleSectionBox = new GUIStyle(GUI.skin.box);
if (!EditorGUIUtility.isProSkin)
{
_styleSectionBox = new GUIStyle(GUI.skin.box);
//_styleSectionBox.normal.background = Texture2D.redTexture;
}
}
_iconPlayButton = EditorGUIUtility.IconContent("d_PlayButton");
_iconPauseButton = EditorGUIUtility.IconContent("d_PauseButton");
_iconSceneViewAudio = EditorGUIUtility.IconContent("d_SceneViewAudio");
_iconProject = EditorGUIUtility.IconContent("d_Project");
_iconRotateTool = EditorGUIUtility.IconContent("d_RotateTool");
AnimCollapseSection.CreateStyles();
}
public override void OnInspectorGUI()
{
MediaPlayer media = (this.target) as MediaPlayer;
// NOTE: It is important that serializedObject.Update() is called before media.EditorUpdate()
// as otherwise the serializedPropertys are not correctly detected as modified
serializedObject.Update();
#if AVPROVIDEO_SUPPORT_LIVEEDITMODE
bool isPlayingInEditor = false;
// Update only during the layout event so that nothing updates for the render event
if (!Application.isPlaying && Event.current.type == EventType.Layout)
{
isPlayingInEditor = media.EditorUpdate();
}
#endif
if (media == null || _propMediaPath == null)
{
return;
}
CreateStyles();
_icon = GetIcon(_icon);
ShowImportantMessages();
if (media != null)
{
OnInspectorGUI_Player(media, media.TextureProducer);
}
AnimCollapseSection.Show(_sectionMediaInfo);
if (_allowDeveloperMode)
{
AnimCollapseSection.Show(_sectionDebug);
}
AnimCollapseSection.Show(_sectionSettings);
if (serializedObject.ApplyModifiedProperties())
{
EditorUtility.SetDirty(target);
}
AnimCollapseSection.Show(_sectionAboutHelp);
#if AVPROVIDEO_SUPPORT_LIVEEDITMODE
if (isPlayingInEditor)
{
GL.InvalidateState();
// NOTE: there seems to be a bug in Unity (2019.3.13) where if you don't have
// GL.sRGBWrite = true and then call RepaintAllViews() it makes the current Inspector
// background turn black. This only happens when using D3D12
// UPDATE: this is happening in Unity 2019.4.15 as well, and in D3D11 mode. It only
// happens when loading a video via the Recent Menu.
bool originalSRGBWrite = GL.sRGBWrite;
GL.sRGBWrite = true;
//this.Repaint();
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
GL.sRGBWrite = originalSRGBWrite;
}
// TODO: OnDisable - stop the video if it's playing (and unload it?)
#endif
}
private void OnInspectorGUI_Settings()
{
foreach (AnimCollapseSection section in _settingSections)
{
AnimCollapseSection.Show(section, indentLevel:1);
}
}
private void ShowSupportWindowButton()
{
//GUI.backgroundColor = new Color(0.96f, 0.25f, 0.47f);
//if (GUILayout.Button("◄ AVPro Video ►\nHelp & Support"))
if (GUILayout.Button("Click here for \nHelp & Support"))
{
SupportWindow.Init();
}
//GUI.backgroundColor = Color.white;
}
private void ShowImportantMessages()
{
// Describe the watermark for trial version
if (_isTrialVersion)
{
string message = string.Empty;
if (Application.isPlaying)
{
#if UNITY_EDITOR_WIN
MediaPlayer media = (this.target) as MediaPlayer;
message = "The watermark is the horizontal bar that moves vertically and the small 'AVPRO TRIAL' text.";
if (media.Info != null && media.Info.GetPlayerDescription().Contains("MF-MediaEngine-Hardware"))
{
message = "The watermark is the RenderHeads logo that moves around the image.";
}
#elif UNITY_EDITOR_OSX
message = "The RenderHeads logo is the watermark.";
#endif
}
EditorHelper.IMGUI.BeginWarningTextBox("AVPRO VIDEO - TRIAL WATERMARK", message, Color.yellow, Color.yellow, Color.white);
if (GUILayout.Button("Purchase"))
{
Application.OpenURL(LinkPurchase);
}
EditorHelper.IMGUI.EndWarningTextBox();
}
#if !UNITY_2019_3_OR_NEWER
if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D12)
{
EditorHelper.IMGUI.WarningTextBox("Compatibility Warning", "Direct3D 12 is not supported until Unity 2019.3", Color.yellow, Color.yellow, Color.white);
}
#endif
}
private void OnInspectorGUI_Main()
{
/////////////////// STARTUP FIELDS
EditorGUILayout.BeginVertical(_styleSectionBox);
GUILayout.Label("Startup", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_propAutoOpen);
EditorGUILayout.PropertyField(_propAutoStart, new GUIContent("Auto Play"));
EditorGUILayout.EndVertical();
/////////////////// PLAYBACK FIELDS
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Playback", EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propLoop);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "Loop");
foreach (MediaPlayer player in this.targets)
{
player.Loop = _propLoop.boolValue;
}
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propRate);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "PlaybackRate");
foreach (MediaPlayer player in this.targets)
{
player.PlaybackRate = _propRate.floatValue;
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Other", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_propPersistent, new GUIContent("Persistent", "Use DontDestroyOnLoad so this object isn't destroyed between level loads"));
if (_propForceFileFormat != null)
{
GUIContent label = new GUIContent("Force File Format", "Override automatic format detection when using non-standard file extensions");
_propForceFileFormat.enumValueIndex = EditorGUILayout.Popup(label, _propForceFileFormat.enumValueIndex, _fileFormatGuiNames);
}
EditorGUILayout.EndVertical();
}
private void OnInspectorGUI_Visual()
{
#if AVPRO_FEATURE_VIDEORESOLVE
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Resolve", EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propUseVideoResolve);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "UseVideoResolve");
foreach (MediaPlayer player in this.targets)
{
player.UseVideoResolve = _propUseVideoResolve.boolValue;
}
}
if (_propUseVideoResolve.boolValue)
{
EditorGUILayout.PropertyField(_propVideoResolve);
/*EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(_propVideoResolveOptions, true);
EditorGUI.indentLevel--;*/
}
GUILayout.EndVertical();
}
#endif
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Texture", EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propFilter, new GUIContent("Filter"));
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "TextureFilterMode");
foreach (MediaPlayer player in this.targets)
{
player.TextureFilterMode = (FilterMode)_propFilter.enumValueIndex;
}
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propWrap, new GUIContent("Wrap"));
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "TextureWrapMode");
foreach (MediaPlayer player in this.targets)
{
player.TextureWrapMode = (TextureWrapMode)_propWrap.enumValueIndex;
}
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propAniso, new GUIContent("Aniso"));
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "TextureAnisoLevel");
foreach (MediaPlayer player in this.targets)
{
player.TextureAnisoLevel = _propAniso.intValue;
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Layout Mapping", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_propVideoMapping);
EditorGUILayout.EndVertical();
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Resampler (BETA)", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_propResample);
EditorGUI.BeginDisabledGroup(!_propResample.boolValue);
EditorGUILayout.PropertyField(_propResampleMode);
EditorGUILayout.PropertyField(_propResampleBufferSize);
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndVertical();
}
}
private static bool IsTrialVersion()
{
string version = GetPluginVersion();
return version.Contains("-trial");
}
//private int _updateFrameCount = -1;
public override bool RequiresConstantRepaint()
{
MediaPlayer media = (this.target) as MediaPlayer;
if (media != null && media.Control != null && media.isActiveAndEnabled && media.Info.GetDuration() > 0.0)
{
if (!media.Info.HasVideo())
{
if (media.Info.HasAudio())
{
return true;
}
}
else if (media.TextureProducer.GetTexture() != null)
{
//int frameCount = media.TextureProducer.GetTextureFrameCount();
//if (_updateFrameCount != frameCount)
{
//_updateFrameCount = frameCount;
return true;
}
}
}
return false;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8fdcfef6a9f4f724486d3374e03f4864
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,164 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// About/Help section of the editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
public const string LinkPluginWebsite = "https://renderheads.com/products/avpro-video/";
public const string LinkForumPage = "https://forum.unity.com/threads/released-avpro-video-complete-video-playback-solution.385611/";
public const string LinkForumLastPage = "https://discussions.unity.com/t/released-avpro-video-complete-video-playback-solution/616470/5259";
public const string LinkGithubIssues = "https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues";
public const string LinkGithubIssuesNew = "https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues/new/choose";
public const string LinkAssetStorePage = "https://assetstore.unity.com/packages/tools/video/avpro-video-v3-core-edition-278893";
public const string LinkUserManual = "https://www.renderheads.com/content/docs/AVProVideo-v3/articles/intro.html";
public const string LinkScriptingClassReference = "https://www.renderheads.com/content/docs/AVProVideo-v3/api/RenderHeads.Media.AVProVideo.html";
public const string LinkPurchase = "https://www.renderheads.com/content/docs/AVProVideo-v3/articles/download.html";
private struct Native
{
#if UNITY_EDITOR_WIN
[System.Runtime.InteropServices.DllImport("AVProVideo")]
public static extern System.IntPtr GetPluginVersion();
#elif UNITY_EDITOR_OSX
[System.Runtime.InteropServices.DllImport("AVProVideo")]
public static extern System.IntPtr AVPPluginGetVersionStringPointer();
#endif
}
private static string GetPluginVersion()
{
string version = "Unknown";
try
{
#if UNITY_EDITOR_WIN
version = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Native.GetPluginVersion());
#elif UNITY_EDITOR_OSX
version = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Native.AVPPluginGetVersionStringPointer());
#endif
}
catch (System.DllNotFoundException e)
{
#if UNITY_EDITOR_OSX
Debug.LogError("[AVProVideo] Failed to load Bundle. " + e.Message);
#else
Debug.LogError("[AVProVideo] Failed to load DLL. " + e.Message);
#endif
}
return version;
}
private static Texture2D GetIcon(Texture2D icon)
{
if (icon == null)
{
icon = Resources.Load<Texture2D>("AVProVideoIcon");
}
return icon;
}
private void OnInspectorGUI_About()
{
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
_icon = GetIcon(_icon);
if (_icon != null)
{
GUILayout.Label(new GUIContent(_icon));
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
GUI.color = Color.yellow;
EditorHelper.IMGUI.CentreLabel("AVPro Video by RenderHeads Ltd", EditorStyles.boldLabel);
EditorHelper.IMGUI.CentreLabel("version " + Helper.AVProVideoVersion + " (plugin v" + GetPluginVersion() + ")");
GUI.color = Color.white;
GUI.backgroundColor = Color.white;
if (_icon != null)
{
GUILayout.Space(8f);
ShowSupportWindowButton();
GUILayout.Space(8f);
}
EditorGUILayout.LabelField("Links", EditorStyles.boldLabel);
GUILayout.Space(8f);
EditorGUILayout.LabelField("Documentation");
if (GUILayout.Button("User Manual, FAQ, Release Notes", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkUserManual);
}
if (GUILayout.Button("Scripting Class Reference", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkScriptingClassReference);
}
GUILayout.Space(16f);
GUILayout.Label("Bugs and Support");
if (GUILayout.Button("Open Help & Support", GUILayout.ExpandWidth(false)))
{
SupportWindow.Init();
}
GUILayout.Space(16f);
GUILayout.Label("Rate and Review (★★★★☆)", GUILayout.ExpandWidth(false));
if (GUILayout.Button("Asset Store Page", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkAssetStorePage);
}
GUILayout.Space(16f);
GUILayout.Label("Community");
if (GUILayout.Button("Forum Thread", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkForumPage);
}
GUILayout.Space(16f);
GUILayout.Label("Homepage", GUILayout.ExpandWidth(false));
if (GUILayout.Button("Official Website", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkPluginWebsite);
}
GUILayout.Space(32f);
EditorGUILayout.LabelField("Credits", EditorStyles.boldLabel);
GUILayout.Space(8f);
EditorHelper.IMGUI.CentreLabel("Programming", EditorStyles.boldLabel);
EditorHelper.IMGUI.CentreLabel("Andrew Griffiths");
EditorHelper.IMGUI.CentreLabel("Morris Butler");
EditorHelper.IMGUI.CentreLabel("Ste Butcher");
EditorHelper.IMGUI.CentreLabel("Richard Turnbull");
EditorHelper.IMGUI.CentreLabel("Sunrise Wang");
EditorHelper.IMGUI.CentreLabel("Muano Mainganye");
EditorHelper.IMGUI.CentreLabel("Shane Marks");
EditorHelper.IMGUI.CentreLabel("Reuben Miller");
GUILayout.Space(8f);
EditorHelper.IMGUI.CentreLabel("Graphics", EditorStyles.boldLabel);
GUILayout.Space(8f);
EditorHelper.IMGUI.CentreLabel("Jeff Rusch");
EditorHelper.IMGUI.CentreLabel("Luke Godward");
EditorHelper.IMGUI.CentreLabel( "QA/Support", EditorStyles.boldLabel );
GUILayout.Space( 8f );
EditorHelper.IMGUI.CentreLabel( "Chris Clarkson" );
GUILayout.Space(32f);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2463176874e32294998504d6b1f2f21c
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,218 @@
//-----------------------------------------------------------------------------
// Copyright 2015-2025 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.Rendering;
using UnityEditor;
// using System.Collections.Generic;
// using System.Linq;
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private readonly static GUIContent[] _audioModesAndroid =
{
new GUIContent("System Direct"),
new GUIContent("Unity"),
new GUIContent("Facebook Audio 360", "Initialises player with Facebook Audio 360 support"),
};
private readonly static GUIContent[] _blitTextureFilteringAndroid =
{
new GUIContent("Point"),
new GUIContent("Bilinear"),
new GUIContent("Trilinear"),
};
private readonly static FieldDescription _optionFileOffset = new FieldDescription(".fileOffset", GUIContent.none);
private readonly static FieldDescription _optionGenerateMipmaps = new FieldDescription("._generateMipmaps", new GUIContent("Generate Mipmaps", "Generate a complete mipmap chain for the output texture. Not supported when the texture format is set to OES"));
// private readonly static FieldDescription _optionBlitTextureFiltering = new FieldDescription(".blitTextureFiltering", new GUIContent("Blit Texture Filtering", "The texture filtering used for the final internal blit."));
// private readonly static FieldDescription _optionShowPosterFrames = new FieldDescription(".showPosterFrame", new GUIContent("Show Poster Frame", "Allows a paused loaded video to display the initial frame. This uses up decoder resources."));
private readonly static FieldDescription _optionPreferSoftwareDecoder = new FieldDescription(".preferSoftwareDecoder", GUIContent.none);
private readonly static FieldDescription _optionForceRtpTCP = new FieldDescription(".forceRtpTCP", GUIContent.none);
private readonly static FieldDescription _optionForceEnableMediaCodecAsynchronousQueueing = new FieldDescription(".forceEnableMediaCodecAsynchronousQueueing", GUIContent.none);
private readonly static FieldDescription _optionAllowUnsupportedVideoTrackVariants = new FieldDescription(".allowUnsupportedVideoTrackVariants", GUIContent.none);
private readonly static FieldDescription _optionPreferredMaximumResolution = new FieldDescription("._preferredMaximumResolution", new GUIContent("Preferred Maximum Resolution", "The desired maximum resolution of the video."));
#if UNITY_2017_2_OR_NEWER
private readonly static FieldDescription _optionCustomPreferredMaxResolution = new FieldDescription("._customPreferredMaximumResolution", new GUIContent(" "));
#endif
private readonly static FieldDescription _optionCustomPreferredPeakBitRate = new FieldDescription("._preferredPeakBitRate", new GUIContent("Preferred Peak BitRate", "The desired limit of network bandwidth consumption for playback, set to 0 for no preference."));
private readonly static FieldDescription _optionCustomPreferredPeakBitRateUnits = new FieldDescription("._preferredPeakBitRateUnits", new GUIContent());
private readonly static FieldDescription _optionMinBufferMs = new FieldDescription(".minBufferMs", new GUIContent("Minimum Buffer Ms"));
private readonly static FieldDescription _optionMaxBufferMs = new FieldDescription(".maxBufferMs", new GUIContent("Maximum Buffer Ms"));
private readonly static FieldDescription _optionBufferForPlaybackMs = new FieldDescription(".bufferForPlaybackMs", new GUIContent("Buffer For Playback Ms"));
private readonly static FieldDescription _optionBufferForPlaybackAfterRebufferMs = new FieldDescription(".bufferForPlaybackAfterRebufferMs", new GUIContent("Buffer For Playback After Rebuffer Ms"));
private readonly static FieldDescription _optionPrioritiseTimeOverSize = new FieldDescription(".prioritiseTimeOverSize", new GUIContent("Prioritise Time Over Size", "Enable to prioritise buffering time constraints over size constraints"));
private void OnInspectorGUI_Override_Android()
{
//MediaPlayer media = (this.target) as MediaPlayer;
//MediaPlayer.OptionsAndroid options = media._optionsAndroid;
GUILayout.Space(8f);
string optionsVarName = MediaPlayer.GetPlatformOptionsVariable(Platform.Android);
{
EditorGUILayout.BeginVertical(GUI.skin.box);
DisplayPlatformOption(optionsVarName, _optionVideoAPI);
SerializedProperty propVideoOutputMode = DisplayPlatformOption(optionsVarName, _optionVideoOutputMode);
if (propVideoOutputMode.enumValueIndex == (int)MediaPlayer.OptionsAndroid.VideoOutputMode.Texture)
{
SerializedProperty propTextureFormat = DisplayPlatformOption(optionsVarName, _optionTextureFormat);
bool isOES = propTextureFormat.enumValueIndex == (int)MediaPlayer.PlatformOptions.TextureFormat.YCbCr420_OES;
if (isOES)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "The OES texture format is only supported when using the OpenGL ES3 renderer, and requires special shaders. Make sure to assign an AVPro Video OES shader type to the meshes or materials that need to display video.");
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "The OES texture format is not supported when using the Vulkan renderer or with the trial version of the plugin.");
}
// Generate mipmaps - only non-OES
if (!isOES)
{
SerializedProperty propGenerateMipmaps = DisplayPlatformOption(optionsVarName, _optionGenerateMipmaps);
}
}
#if AVPRO_VIDEO_XR_COMPOSITION_LAYERS
else if (propVideoOutputMode.enumValueIndex == (int)MediaPlayer.OptionsAndroid.VideoOutputMode.XRCompositionLayer)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "XR Composition Layer requires the AVPro Video XR Composition Layers package, available here: https://u3d.as/3zoT");
GraphicsDeviceType[] graphicsApis = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android);
if (graphicsApis[0] != GraphicsDeviceType.Vulkan || graphicsApis.Length > 1)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "XR Composition Layer is only supported when using the Vulkan graphics API.");
}
SerializedProperty propTextureFormat = DisplayPlatformOption(optionsVarName, _optionTextureFormat);
bool isOES = propTextureFormat.enumValueIndex == (int)MediaPlayer.PlatformOptions.TextureFormat.YCbCr420_OES;
if (isOES)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "The video is output directly to the XR composition layer. This is the most performant mode and should be your preferred choice.");
}
else
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "The video is rendered to the XR composition layer by the plugin. This is the most compatible mode.");
}
}
#endif
{
SerializedProperty propFileOffset = DisplayPlatformOption(optionsVarName, _optionFileOffset);
propFileOffset.intValue = Mathf.Max(0, propFileOffset.intValue);
}
EditorGUILayout.EndVertical();
}
if (_showUltraOptions)
{
SerializedProperty httpHeadersProp = serializedObject.FindProperty(optionsVarName + ".httpHeaders.httpHeaders");
if (httpHeadersProp != null)
{
OnInspectorGUI_HttpHeaders(httpHeadersProp);
}
SerializedProperty keyAuthProp = serializedObject.FindProperty(optionsVarName + ".keyAuth");
if (keyAuthProp != null)
{
OnInspectorGUI_HlsDecryption(keyAuthProp);
}
}
#if false
// MediaPlayer API options
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("MediaPlayer API Options", EditorStyles.boldLabel);
DisplayPlatformOption(optionsVarName, _optionShowPosterFrames);
EditorGUILayout.EndVertical();
}
#endif
// ExoPlayer API options
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("ExoPlayer API Options", EditorStyles.boldLabel);
DisplayPlatformOption(optionsVarName, _optionPreferSoftwareDecoder);
DisplayPlatformOption(optionsVarName, _optionForceRtpTCP);
DisplayPlatformOption(optionsVarName, _optionForceEnableMediaCodecAsynchronousQueueing);
DisplayPlatformOption(optionsVarName, _optionAllowUnsupportedVideoTrackVariants);
// Audio
{
SerializedProperty propAudioOutput = DisplayPlatformOptionEnum(optionsVarName, _optionAudioOutput, _audioModesAndroid);
if ((Android.AudioOutput)propAudioOutput.enumValueIndex == Android.AudioOutput.FacebookAudio360)
{
if (_showUltraOptions)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Facebook Audio 360", EditorStyles.boldLabel);
DisplayPlatformOptionEnum(optionsVarName, _optionAudio360ChannelMode, _audio360ChannelMapGuiNames);
DisplayPlatformOption(optionsVarName, _optionAudio360LatencyMS);
}
}
}
GUILayout.Space(8f);
// EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Adaptive Stream", EditorStyles.boldLabel);
DisplayPlatformOption(optionsVarName, _optionStartMaxBitrate);
{
SerializedProperty preferredMaximumResolutionProp = DisplayPlatformOption(optionsVarName, _optionPreferredMaximumResolution);
if ((MediaPlayer.OptionsAndroid.Resolution)preferredMaximumResolutionProp.intValue == MediaPlayer.OptionsAndroid.Resolution.Custom)
{
#if UNITY_2017_2_OR_NEWER
DisplayPlatformOption(optionsVarName, _optionCustomPreferredMaxResolution);
#endif
}
}
{
EditorGUILayout.BeginHorizontal();
DisplayPlatformOption(optionsVarName, _optionCustomPreferredPeakBitRate);
DisplayPlatformOption(optionsVarName, _optionCustomPreferredPeakBitRateUnits);
EditorGUILayout.EndHorizontal();
}
DisplayPlatformOption(optionsVarName, _optionMinBufferMs);
DisplayPlatformOption(optionsVarName, _optionMaxBufferMs);
DisplayPlatformOption(optionsVarName, _optionBufferForPlaybackMs);
DisplayPlatformOption(optionsVarName, _optionBufferForPlaybackAfterRebufferMs);
var propPrioritiseTimeOverSize = DisplayPlatformOption(optionsVarName, _optionPrioritiseTimeOverSize);
if (propPrioritiseTimeOverSize.boolValue)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "Only enable this if you're exclusively playing streamed media types (HLS, or MPEG-Dash)");
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "May lead to OOM crashes if 'Min Buffer Ms' and 'Max Buffer Ms' are too large.");
}
EditorGUILayout.EndVertical();
}
GUI.enabled = true;
/*
SerializedProperty propFileOffsetLow = serializedObject.FindProperty(optionsVarName + ".fileOffsetLow");
SerializedProperty propFileOffsetHigh = serializedObject.FindProperty(optionsVarName + ".fileOffsetHigh");
if (propFileOffsetLow != null && propFileOffsetHigh != null)
{
propFileOffsetLow.intValue = ;
EditorGUILayout.PropertyField(propFileOFfset);
}*/
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0516948b5fec81a4eb1566ebd6d4027a
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,145 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private readonly static FieldDescription _optionAudioMode = new FieldDescription("._audioMode", new GUIContent("Audio Mode", "Unity mode does not work with HLS video"));
private readonly static FieldDescription _optionTextureFormat = new FieldDescription(".textureFormat", new GUIContent("Texture Format", "BGRA32 is the most compatible.\nYCbCr420_OES requires less memory and processing however it does require shader support."));
private readonly static FieldDescription _optionPreferredForwardBufferDuration = new FieldDescription("._preferredForwardBufferDuration", new GUIContent("Preferred Forward Buffer Duration", "The duration in seconds the player should buffer ahead of the playhead to prevent stalling. Set to 0 to let the system decide."));
private readonly static FieldDescription _optionCustomPreferredPeakBitRateApple = new FieldDescription("._preferredPeakBitRate", new GUIContent("Preferred Peak BitRate", "The desired limit of network bandwidth consumption for playback, set to 0 for no preference."));
private readonly static FieldDescription _optionCustomPreferredPeakBitRateUnitsApple = new FieldDescription("._preferredPeakBitRateUnits", new GUIContent());
private void OnInspectorGUI_Override_Apple(Platform platform)
{
GUILayout.Space(8f);
string optionsVarName = MediaPlayer.GetPlatformOptionsVariable(platform);
EditorGUILayout.BeginVertical(GUI.skin.box);
DisplayPlatformOption(optionsVarName, _optionTextureFormat);
SerializedProperty flagsProp = serializedObject.FindProperty(optionsVarName + "._flags");
MediaPlayer.OptionsApple.Flags flags = flagsProp != null ? (MediaPlayer.OptionsApple.Flags)flagsProp.intValue : 0;
// Texture flags
if (flagsProp != null)
{
bool generateMipmaps = flags.GenerateMipmaps();
generateMipmaps = EditorGUILayout.Toggle(new GUIContent("Generate Mipmaps"), generateMipmaps);
flags = flags.SetGenerateMipMaps(generateMipmaps);
}
// Audio
DisplayPlatformOption(optionsVarName, _optionAudioMode);
// Platform specific flags
if (flagsProp != null)
{
if (platform == Platform.macOS || platform == Platform.iOS)
{
bool b = flags.AllowExternalPlayback();
b = EditorGUILayout.Toggle(new GUIContent("Allow External Playback", "Enables support for playback on external devices via AirPlay."), b);
flags = flags.SetAllowExternalPlayback(b);
}
if (platform == Platform.iOS)
{
bool b = flags.ResumePlaybackAfterAudioSessionRouteChange();
b = EditorGUILayout.Toggle(new GUIContent("Resume playback after audio route change", "The default behaviour is for playback to pause when the audio route changes, for instance when disconnecting headphones."), b);
flags = flags.SetResumePlaybackAfterAudioSessionRouteChange(b);
}
bool playWithoutBuffering = flags.PlayWithoutBuffering();
playWithoutBuffering = EditorGUILayout.Toggle(new GUIContent("Play without buffering"), playWithoutBuffering);
flags = flags.SetPlayWithoutBuffering(playWithoutBuffering);
bool useSinglePlayerItem = flags.UseSinglePlayerItem();
useSinglePlayerItem = EditorGUILayout.Toggle(new GUIContent("Use single player item", "Restricts the media player to using only one player item. This can help reduce network usage for remote videos but will cause a stall when looping."), useSinglePlayerItem);
flags = flags.SetUseSinglePlayerItem(useSinglePlayerItem);
}
SerializedProperty maximumPlaybackRateProp = serializedObject.FindProperty(optionsVarName + ".maximumPlaybackRate");
if (maximumPlaybackRateProp != null)
{
EditorGUILayout.Slider(maximumPlaybackRateProp, 2.0f, 10.0f, new GUIContent("Max Playback Rate", "Increase the maximum playback rate before which playback switches to key-frames only."));
}
GUILayout.Space(8f);
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Network", EditorStyles.boldLabel);
SerializedProperty preferredMaximumResolutionProp = DisplayPlatformOption(optionsVarName, _optionPreferredMaximumResolution);
if ((MediaPlayer.OptionsApple.Resolution)preferredMaximumResolutionProp.intValue == MediaPlayer.OptionsApple.Resolution.Custom)
{
#if UNITY_2017_2_OR_NEWER
DisplayPlatformOption(optionsVarName, _optionCustomPreferredMaxResolution);
#endif
}
EditorGUILayout.BeginHorizontal();
DisplayPlatformOption(optionsVarName, _optionCustomPreferredPeakBitRateApple);
DisplayPlatformOption(optionsVarName, _optionCustomPreferredPeakBitRateUnitsApple);
EditorGUILayout.EndHorizontal();
DisplayPlatformOption(optionsVarName, _optionPreferredForwardBufferDuration);
EditorGUILayout.EndVertical();
EditorGUILayout.EndVertical();
// Set the flags
if (flagsProp != null)
{
flagsProp.intValue = (int)flags;
}
if (_showUltraOptions)
{
SerializedProperty keyAuthProp = serializedObject.FindProperty(optionsVarName + ".keyAuth");
if (keyAuthProp != null)
{
OnInspectorGUI_HlsDecryption(keyAuthProp);
}
SerializedProperty httpHeadersProp = serializedObject.FindProperty(optionsVarName + ".httpHeaders.httpHeaders");
if (httpHeadersProp != null)
{
OnInspectorGUI_HttpHeaders(httpHeadersProp);
}
}
}
private void OnInspectorGUI_Override_MacOSX()
{
OnInspectorGUI_Override_Apple(Platform.macOS);
}
private void OnInspectorGUI_Override_iOS()
{
OnInspectorGUI_Override_Apple(Platform.iOS);
}
private void OnInspectorGUI_Override_tvOS()
{
OnInspectorGUI_Override_Apple(Platform.tvOS);
}
private void OnInspectorGUI_Override_visionOS()
{
OnInspectorGUI_Override_Apple(Platform.visionOS);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 38bbbff2994464c48b6d633a311b63f6
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,87 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2022 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private SerializedProperty _propVolume;
private SerializedProperty _propBalance;
private SerializedProperty _propMuted;
private SerializedProperty _propAudioHeadTransform;
private SerializedProperty _propAudioEnableFocus;
private SerializedProperty _propAudioFocusOffLevelDB;
private SerializedProperty _propAudioFocusWidthDegrees;
private SerializedProperty _propAudioFocusTransform;
private void OnInspectorGUI_Audio()
{
if (EditorUtility.audioMasterMute)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.HelpBox("Audio is currently muted in Editor", MessageType.Warning, true);
if (GUILayout.Button("Unmute", GUILayout.ExpandHeight(true)))
{
EditorUtility.audioMasterMute = false;
UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); // To force the GameView audio mute toggle display state to update
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.BeginVertical(GUI.skin.box);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propVolume, new GUIContent("Volume"));
if (EditorGUI.EndChangeCheck())
{
foreach (MediaPlayer player in this.targets)
{
player.AudioVolume = _propVolume.floatValue;
}
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propBalance, new GUIContent("Balance"));
if (EditorGUI.EndChangeCheck())
{
foreach (MediaPlayer player in this.targets)
{
player.AudioBalance = _propBalance.floatValue;
}
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propMuted, new GUIContent("Muted"));
if (EditorGUI.EndChangeCheck())
{
foreach (MediaPlayer player in this.targets)
{
player.AudioMuted = _propMuted.boolValue;
}
}
EditorGUILayout.EndVertical();
if (_showUltraOptions)
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Audio 360", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_propAudioHeadTransform, new GUIContent("Head Transform", "Set this to your head camera transform. Only currently used for Facebook Audio360"));
EditorGUILayout.PropertyField(_propAudioEnableFocus, new GUIContent("Enable Focus", "Enables focus control. Only currently used for Facebook Audio360"));
if (_propAudioEnableFocus.boolValue)
{
EditorGUILayout.PropertyField(_propAudioFocusOffLevelDB, new GUIContent("Off Focus Level DB", "Sets the off-focus level in DB, with the range being between -24 to 0 DB. Only currently used for Facebook Audio360"));
EditorGUILayout.PropertyField(_propAudioFocusWidthDegrees, new GUIContent("Focus Width Degrees", "Set the focus width in degrees, with the range being between 40 and 120 degrees. Only currently used for Facebook Audio360"));
EditorGUILayout.PropertyField(_propAudioFocusTransform, new GUIContent("Focus Transform", "Set this to where you wish to focus on the video. Only currently used for Facebook Audio360"));
}
EditorGUILayout.EndVertical();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 37646bf6e83e0f5429dc604d9f8b86fc
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,255 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private static bool _allowDeveloperMode = false;
private static bool _showUltraOptions = true;
private AnimCollapseSection _sectionDevModeState;
private AnimCollapseSection _sectionDevModeTexture;
private AnimCollapseSection _sectionDevModeHapNotchLCDecoder;
private AnimCollapseSection _sectionDevModePlaybackQuality;
private AnimCollapseSection _sectionDevModeTimedMetadata;
private static readonly GUIContent _guiTextMetaData = new GUIContent("MetaData");
private static readonly GUIContent _guiTextPaused = new GUIContent("Paused");
private static readonly GUIContent _guiTextPlaying = new GUIContent("Playing");
private static readonly GUIContent _guiTextSeeking = new GUIContent("Seeking");
private static readonly GUIContent _guiTextBuffering = new GUIContent("Buffering");
private static readonly GUIContent _guiTextStalled = new GUIContent("Stalled");
private static readonly GUIContent _guiTextFinished = new GUIContent("Finished");
private static readonly GUIContent _guiTextTimeColon= new GUIContent("Time: ");
private static readonly GUIContent _guiTextFrameColon = new GUIContent("Frame: ");
private static readonly GUIContent _guiTextFrameDec = new GUIContent("<");
private static readonly GUIContent _guiTextFrameInc = new GUIContent(">");
private static readonly GUIContent _guiTextSelectTexture = new GUIContent("Select Texture");
private static readonly GUIContent _guiTextSaveFramePNG = new GUIContent("Save Frame PNG");
private static readonly GUIContent _guiTextSaveFrameEXR = new GUIContent("Save Frame EXR");
private static readonly GUIContent _guiTextDecodeStats = new GUIContent("Decode Stats");
private static readonly GUIContent _guiTextParallelFrames = new GUIContent("Parallel Frames");
private static readonly GUIContent _guiTextDecodedFrames = new GUIContent("Decoded Frames");
private static readonly GUIContent _guiTextDroppedFrames = new GUIContent("Dropped Frames");
private static readonly GUIContent _guiTextBufferedFrames = new GUIContent("Buffered Frames");
private static readonly GUIContent _guiTextFreeFrames = new GUIContent("Free Frames");
//private static readonly GUIContent _guiTextDisplayTimestamp = new GUIContent("Display Timstamp");
//private static readonly GUIContent _guiTextMinTimestamp = new GUIContent("Min Timstamp");
//private static readonly GUIContent _guiTextMaxTimestamp = new GUIContent("Max Timstamp");
private static readonly GUIContent _guiTextFlush = new GUIContent("Flush");
private static readonly GUIContent _guiTextReset = new GUIContent("Reset");
private void OnInspectorGUI_DevMode_State()
{
MediaPlayer mediaPlayer = (this.target) as MediaPlayer;
if (mediaPlayer.Control != null)
{
// State
GUIStyle style = GUI.skin.button;
using (HorizontalFlowScope flow = new HorizontalFlowScope(Screen.width))
{
flow.AddItem(_guiTextMetaData, style);
GUI.color = mediaPlayer.Control.HasMetaData() ? Color.green : Color.white;
GUILayout.Toggle(true, _guiTextMetaData, style);
flow.AddItem(_guiTextPaused, style);
GUI.color = mediaPlayer.Control.IsPaused() ? Color.green : Color.white;
GUILayout.Toggle(true, _guiTextPaused, style);
flow.AddItem(_guiTextPlaying, style);
GUI.color = mediaPlayer.Control.IsPlaying() ? Color.green : Color.white;
GUILayout.Toggle(true, _guiTextPlaying, style);
flow.AddItem(_guiTextSeeking, style);
GUI.color = mediaPlayer.Control.IsSeeking() ? Color.green : Color.white;
GUILayout.Toggle(true, _guiTextSeeking, style);
flow.AddItem(_guiTextBuffering, style);
GUI.color = mediaPlayer.Control.IsBuffering() ? Color.green : Color.white;
GUILayout.Toggle(true, _guiTextBuffering, style);
flow.AddItem(_guiTextStalled, style);
GUI.color = mediaPlayer.Info.IsPlaybackStalled() ? Color.green : Color.white;
GUILayout.Toggle(true, _guiTextStalled, style);
flow.AddItem(_guiTextFinished, style);
GUI.color = mediaPlayer.Control.IsFinished() ? Color.green : Color.white;
GUILayout.Toggle(true, _guiTextFinished, style);
}
GUI.color = Color.white;
// Time, FPS, Frame stepping
GUILayout.BeginHorizontal();
GUILayout.Label(_guiTextTimeColon);
GUILayout.Label(mediaPlayer.Control.GetCurrentTime().ToString());
GUILayout.FlexibleSpace();
GUILayout.Label(_guiTextFrameColon);
GUILayout.Label(mediaPlayer.Control.GetCurrentTimeFrames().ToString());
EditorGUI.BeginDisabledGroup(mediaPlayer.Info.GetVideoFrameRate() <= 0f);
if (GUILayout.Button(_guiTextFrameDec))
{
mediaPlayer.Control.SeekToFrameRelative(-1);
}
if (GUILayout.Button(_guiTextFrameInc))
{
mediaPlayer.Control.SeekToFrameRelative(1);
}
EditorGUI.EndDisabledGroup();
GUILayout.EndHorizontal();
}
}
private void OnInspectorGUI_DevMode_Texture()
{
MediaPlayer mediaPlayer = (this.target) as MediaPlayer;
if (mediaPlayer.Control != null)
{
// Raw texture preview
if (mediaPlayer.TextureProducer != null)
{
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace();
for (int i = 0; i < mediaPlayer.TextureProducer.GetTextureCount(); i++)
{
Texture texture = mediaPlayer.TextureProducer.GetTexture(i);
if (texture != null)
{
GUILayout.BeginVertical();
Rect textureRect = GUILayoutUtility.GetRect(128f, 128f);
if (Event.current.type == EventType.Repaint)
{
GUI.color = Color.gray;
EditorGUI.DrawTextureTransparent(textureRect, Texture2D.blackTexture, ScaleMode.StretchToFill);
GUI.color = Color.white;
}
GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit, false);
GUILayout.Label(texture.width + "x" + texture.height + " ");
if (GUILayout.Button(_guiTextSelectTexture, GUILayout.ExpandWidth(false)))
{
Selection.activeObject = texture;
}
GUILayout.EndVertical();
}
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.Label("Updates: " + mediaPlayer.TextureProducer.GetTextureFrameCount());
GUILayout.Label("TimeStamp: " + mediaPlayer.TextureProducer.GetTextureTimeStamp());
GUILayout.BeginHorizontal();
if (GUILayout.Button(_guiTextSaveFramePNG, GUILayout.ExpandWidth(true)))
{
mediaPlayer.SaveFrameToPng();
}
if (GUILayout.Button(_guiTextSaveFrameEXR, GUILayout.ExpandWidth(true)))
{
mediaPlayer.SaveFrameToExr();
}
GUILayout.EndHorizontal();
}
}
}
private void OnInspectorGUI_DevMode_HapNotchLCDecoder()
{
MediaPlayer mediaPlayer = (this.target) as MediaPlayer;
if (mediaPlayer.Info != null)
{
int activeDecodeThreadCount = 0;
int decodedFrameCount = 0;
int droppedFrameCount = 0;
if (mediaPlayer.Info.GetDecoderPerformance(ref activeDecodeThreadCount, ref decodedFrameCount, ref droppedFrameCount))
{
GUILayout.Label(_guiTextDecodeStats);
EditorGUI.indentLevel++;
EditorGUILayout.Slider(_guiTextParallelFrames, activeDecodeThreadCount, 0f, mediaPlayer.PlatformOptionsWindows.parallelFrameCount);
EditorGUILayout.Slider(_guiTextDecodedFrames, decodedFrameCount, 0f, mediaPlayer.PlatformOptionsWindows.prerollFrameCount * 2);
EditorGUILayout.IntField(_guiTextDroppedFrames, droppedFrameCount);
EditorGUI.indentLevel--;
}
}
}
private void OnInspectorGUI_DevMode_PresentationQuality()
{
MediaPlayer mediaPlayer = (this.target) as MediaPlayer;
if (mediaPlayer.Info != null)
{
PlaybackQualityStats stats = mediaPlayer.Info.GetPlaybackQualityStats();
//stats.LogIssues = true;
stats.LogIssues = EditorGUILayout.Toggle("Log Issues", stats.LogIssues);
GUILayout.Label("Video", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUILayout.LabelField("Skipped Frames", stats.SkippedFrames.ToString());
GUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Duplicate Frames", stats.DuplicateFrames.ToString());
GUILayout.Label(stats.VSyncStatus);
GUILayout.EndHorizontal();
EditorGUILayout.LabelField("Perfect Frames", (stats.PerfectFramesT * 100f).ToString("F2") + "%");
EditorGUI.indentLevel--;
GUILayout.Label("Unity", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUILayout.LabelField("Dropped Frames", stats.UnityDroppedFrames.ToString());
EditorGUI.indentLevel--;
if (GUILayout.Button(_guiTextReset))
{
stats.Reset();
}
}
}
private void OnInspectorGUI_DevMode_TimedMetadata()
{
ITimedMetadata timedMetadata = (this.target as MediaPlayer).TimedMetadata;
TimedMetadataItem item = timedMetadata.GetTimedMetadataItem();
if (item != null)
{
GUILayout.Label($"{item.PresentationTime} - {item.Text}");
}
else
{
GUILayout.Label("None");
}
}
private void OnInspectorGUI_Debug()
{
MediaPlayer mediaPlayer = (this.target) as MediaPlayer;
IMediaInfo info = mediaPlayer.Info;
if (info != null)
{
AnimCollapseSection.Show(_sectionDevModeState);
AnimCollapseSection.Show(_sectionDevModeTexture);
AnimCollapseSection.Show(_sectionDevModePlaybackQuality);
AnimCollapseSection.Show(_sectionDevModeTimedMetadata);
}
if (info != null)
{
#if UNITY_EDITOR_WIN
if (mediaPlayer.PlatformOptionsWindows.useHapNotchLC)
{
AnimCollapseSection.Show(_sectionDevModeHapNotchLCDecoder);
}
#endif
}
else
{
GUILayout.Label("No media loaded");
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8c5649aed6704fa4199ad212f4562fdb
timeCreated: 1594038897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private SerializedProperty _propEvents;
private SerializedProperty _propEventMask;
private SerializedProperty _propPauseMediaOnAppPause;
private SerializedProperty _propPlayMediaOnAppUnpause;
private void OnInspectorGUI_Events()
{
EditorGUILayout.BeginVertical(GUI.skin.box);
EditorGUILayout.PropertyField(_propEvents);
_propEventMask.intValue = EditorGUILayout.MaskField("Triggered Events", _propEventMask.intValue, System.Enum.GetNames(typeof(MediaPlayerEvent.EventType)));
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Pause Media On App Pause");
_propPauseMediaOnAppPause.boolValue = EditorGUILayout.Toggle(_propPauseMediaOnAppPause.boolValue);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Play Media On App Unpause");
_propPlayMediaOnAppUnpause.boolValue = EditorGUILayout.Toggle(_propPlayMediaOnAppUnpause.boolValue);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 191b4e7b3d732b44381d348e9e0dc7ea
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private void OnInspectorGUI_GlobalSettings()
{
EditorGUI.BeginDisabledGroup(Application.isPlaying);
EditorGUILayout.LabelField("Target Platform", EditorUserBuildSettings.selectedBuildTargetGroup.ToString());
if (EditorUserBuildSettings.selectedBuildTargetGroup != BuildTargetGroup.Standalone)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "These global options only affect the current target platform so will not apply in-editor unless you change your Build Target and reapply them.");
}
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Video Capture", EditorStyles.boldLabel);
// TimeScale
{
const string TimeScaleDefine = "AVPROVIDEO_BETA_SUPPORT_TIMESCALE";
if (EditorHelper.IMGUI.ToggleScriptDefine("TimeScale Support", TimeScaleDefine))
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "This will affect performance if you change Time.timeScale or Time.captureFramerate. This feature is useful for supporting video capture system that adjust time scale during capturing.");
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Other", EditorStyles.boldLabel);
// Disable Logging
{
const string DisableLogging = "AVPROVIDEO_DISABLE_LOGGING";
EditorHelper.IMGUI.ToggleScriptDefine("Disable Logging", DisableLogging);
}
// Show Ultra Options
{
const string ShowUltraOptions = "AVPROVIDEO_SHOW_ULTRA_OPTIONS";
EditorHelper.IMGUI.ToggleScriptDefine("Show Ultra Options", ShowUltraOptions);
}
_allowDeveloperMode = EditorGUILayout.Toggle(new GUIContent("Developer Mode", "Enables some additional information useful for debugging"), _allowDeveloperMode);
EditorGUILayout.EndVertical();
EditorGUI.EndDisabledGroup();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 43f33634e709c224aa295751513f8f63
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,130 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private void OnInspectorGUI_Network()
{
if (_showUltraOptions)
{
SerializedProperty httpHeadersProp = serializedObject.FindProperty("_httpHeaders.httpHeaders");
OnInspectorGUI_HttpHeaders(httpHeadersProp);
SerializedProperty keyAuthProp = serializedObject.FindProperty("_keyAuth");
OnInspectorGUI_HlsDecryption(keyAuthProp);
}
}
private void OnInspectorGUI_HlsDecryption(SerializedProperty keyAuthProp)
{
if (keyAuthProp == null) return;
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("HLS Decryption", EditorStyles.boldLabel);
// Key server auth token
SerializedProperty prop = keyAuthProp.FindPropertyRelative("keyServerToken");
if (prop != null)
{
EditorGUILayout.PropertyField(prop, new GUIContent("Auth Token", "Token to pass to the key server in the 'Authorization' HTTP header field"));
}
//GUILayout.Label("Overrides");
//EditorGUI.indentLevel++;
// Key server override
/*prop = serializedObject.FindProperty(optionsVarName + ".keyServerURLOverride");
if (prop != null)
{
EditorGUILayout.PropertyField(prop, new GUIContent("Key Server URL", "Overrides the key server URL if present in a HLS manifest."));
}*/
// Key data blob override
prop = keyAuthProp.FindPropertyRelative("overrideDecryptionKeyBase64");
if (prop != null)
{
EditorGUILayout.PropertyField(prop, new GUIContent("Key Override (Base64)", "Override key to use for decoding encrypted HLS streams (in Base64 format)."));
}
//EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
}
private void OnInspectorGUI_HttpHeaders(SerializedProperty httpHeadersProp)
{
if (httpHeadersProp == null) return;
//GUILayout.Space(8f);
bool isExpanded = _HTTPHeadersToggle;
if (isExpanded)
{
EditorGUILayout.BeginVertical(GUI.skin.box);
}
bool hasHeaders = (httpHeadersProp.arraySize > 0);
Color tintColor = hasHeaders?Color.yellow:Color.white;
if (AnimCollapseSection.BeginShow("Custom HTTP Headers", ref _HTTPHeadersToggle, tintColor))
{
{
if (httpHeadersProp.arraySize > 0)
{
int deleteIndex = -1;
for (int i = 0; i < httpHeadersProp.arraySize; ++i)
{
SerializedProperty httpHeaderProp = httpHeadersProp.GetArrayElementAtIndex(i);
SerializedProperty headerProp = httpHeaderProp.FindPropertyRelative("name");
GUILayout.BeginVertical(GUI.skin.box);
GUILayout.BeginHorizontal();
GUI.color = HttpHeader.IsValid(headerProp.stringValue)?Color.white:Color.red;
EditorGUILayout.PropertyField(headerProp, GUIContent.none);
headerProp.stringValue = headerProp.stringValue.Trim();
GUI.color = Color.white;
if (GUILayout.Button("-", GUILayout.ExpandWidth(false)))
{
deleteIndex = i;
}
GUILayout.EndHorizontal();
SerializedProperty valueProp = httpHeaderProp.FindPropertyRelative("value");
GUI.color = HttpHeader.IsValid(valueProp.stringValue)?Color.white:Color.red;
valueProp.stringValue = EditorGUILayout.TextArea(valueProp.stringValue, EditorHelper.IMGUI.GetWordWrappedTextAreaStyle());
GUI.color = Color.white;
valueProp.stringValue = valueProp.stringValue.Trim();
GUILayout.EndVertical();
GUILayout.Space(4f);
}
if (deleteIndex >= 0)
{
httpHeadersProp.DeleteArrayElementAtIndex(deleteIndex);
}
}
if (GUILayout.Button("+"))
{
httpHeadersProp.InsertArrayElementAtIndex(httpHeadersProp.arraySize);
}
}
}
AnimCollapseSection.EndShow();
if (isExpanded)
{
EditorGUILayout.EndVertical();
}
//GUILayout.Space(8f);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e21d984efff21a1498d41745548e8f14
timeCreated: 1592503568
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,161 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
// private readonly static FieldDescription _optionFileOffset = new FieldDescription(".fileOffset", GUIContent.none);
private readonly static FieldDescription _optionGenerateMipmapsOpenHarmony = new FieldDescription("._generateMipmapsOH", new GUIContent("Generate Mipmaps", "Generate a complete mipmap chain for the output texture"));
private readonly static FieldDescription _optionUseNormalizedOHMUrl = new FieldDescription("._useNormalizedOHMUrl", new GUIContent("useNormalizedOHMUrl", "Set whether to use the plugin built with _useNormalizedOHMUrl"));
/*
private readonly static FieldDescription _optionPreferredMaximumResolution = new FieldDescription("._preferredMaximumResolution", new GUIContent("Preferred Maximum Resolution", "The desired maximum resolution of the video."));
#if UNITY_2017_2_OR_NEWER
private readonly static FieldDescription _optionCustomPreferredMaxResolution = new FieldDescription("._customPreferredMaximumResolution", new GUIContent(" "));
#endif
private readonly static FieldDescription _optionCustomPreferredPeakBitRate = new FieldDescription("._preferredPeakBitRate", new GUIContent("Preferred Peak BitRate", "The desired limit of network bandwidth consumption for playback, set to 0 for no preference."));
private readonly static FieldDescription _optionCustomPreferredPeakBitRateUnits = new FieldDescription("._preferredPeakBitRateUnits", new GUIContent());
private readonly static FieldDescription _optionMinBufferMs = new FieldDescription(".minBufferMs", new GUIContent("Minimum Buffer Ms"));
private readonly static FieldDescription _optionMaxBufferMs = new FieldDescription(".maxBufferMs", new GUIContent("Maximum Buffer Ms"));
private readonly static FieldDescription _optionBufferForPlaybackMs = new FieldDescription(".bufferForPlaybackMs", new GUIContent("Buffer For Playback Ms"));
private readonly static FieldDescription _optionBufferForPlaybackAfterRebufferMs = new FieldDescription(".bufferForPlaybackAfterRebufferMs", new GUIContent("Buffer For Playback After Rebuffer Ms"));
*/
private void OnInspectorGUI_Override_OpenHarmony()
{
//MediaPlayer media = (this.target) as MediaPlayer;
//MediaPlayer.OptionsOpenHarmony options = media._optionsOpenHarmony;
GUILayout.Space(8f);
string optionsVarName = MediaPlayer.GetPlatformOptionsVariable(Platform.OpenHarmony);
{
EditorGUILayout.BeginVertical(GUI.skin.box);
/*
DisplayPlatformOption(optionsVarName, _optionVideoAPI);
{
SerializedProperty propFileOffset = DisplayPlatformOption(optionsVarName, _optionFileOffset);
propFileOffset.intValue = Mathf.Max(0, propFileOffset.intValue);
}
*/
SerializedProperty propTextureFormat = DisplayPlatformOption(optionsVarName, _optionTextureFormat);
// Generate mipmaps
SerializedProperty propGenerateMipmaps = DisplayPlatformOption(optionsVarName, _optionGenerateMipmapsOpenHarmony);
// useNormalizedOHMUrl
EditorGUI.BeginChangeCheck();
SerializedProperty propUseNormalizedOHMUrl = DisplayPlatformOption(optionsVarName, _optionUseNormalizedOHMUrl);
if ( EditorGUI.EndChangeCheck() )
{
// Ensure the correct har is used
// string folderHAR = Path.Combine(Application.dataPath, "AVProVideo/Runtime/Plugins/OpenHarmony");
string folderLIB = Path.Combine(Application.dataPath, "AVProVideo/Runtime/Plugins/OpenHarmony/libs/arm64-v8a");
string[] aSourcePath = { /*Path.Combine( folderHAR, ( ( propUseNormalizedOHMUrl.boolValue ) ? "AVProVideoLib.hrt" : "AVProVideoLib.hrf" ) ), */
Path.Combine( folderLIB, ( ( propUseNormalizedOHMUrl.boolValue ) ? "libavprovideolib.sot" : "libavprovideolib.sof" ) ) };
string[] aTargetPath = { /*Path.Combine( folderHAR, "AVProVideoLib.har"), */
Path.Combine( folderLIB, "libavprovideolib.so" ) };
for( int i = 0; i < aSourcePath.Length; ++i )
{
if ( File.Exists( aSourcePath[ i ] ) )
{
File.Copy( aSourcePath[ i ], aTargetPath[ i ], overwrite: true );
// Debug.Log( $"Copied {aSourcePath[ i ]} → {aTargetPath[ i ]}" );
}
}
AssetDatabase.Refresh();
}
EditorGUILayout.EndVertical();
}
/*
if (_showUltraOptions)
{
SerializedProperty httpHeadersProp = serializedObject.FindProperty(optionsVarName + ".httpHeaders.httpHeaders");
if (httpHeadersProp != null)
{
OnInspectorGUI_HttpHeaders(httpHeadersProp);
}
SerializedProperty keyAuthProp = serializedObject.FindProperty(optionsVarName + ".keyAuth");
if (keyAuthProp != null)
{
OnInspectorGUI_HlsDecryption(keyAuthProp);
}
}
*/
#if false
// MediaPlayer API options
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("MediaPlayer API Options", EditorStyles.boldLabel);
DisplayPlatformOption(optionsVarName, _optionShowPosterFrames);
EditorGUILayout.EndVertical();
}
#endif
/*
{
EditorGUILayout.BeginVertical(GUI.skin.box);
DisplayPlatformOption(optionsVarName, _optionStartMaxBitrate);
{
SerializedProperty preferredMaximumResolutionProp = DisplayPlatformOption(optionsVarName, _optionPreferredMaximumResolution);
if ((MediaPlayer.OptionsAndroid.Resolution)preferredMaximumResolutionProp.intValue == MediaPlayer.OptionsAndroid.Resolution.Custom)
{
#if UNITY_2017_2_OR_NEWER
DisplayPlatformOption(optionsVarName, _optionCustomPreferredMaxResolution);
#endif
}
}
{
EditorGUILayout.BeginHorizontal();
DisplayPlatformOption(optionsVarName, _optionCustomPreferredPeakBitRate);
DisplayPlatformOption(optionsVarName, _optionCustomPreferredPeakBitRateUnits);
EditorGUILayout.EndHorizontal();
}
DisplayPlatformOption(optionsVarName, _optionMinBufferMs);
DisplayPlatformOption(optionsVarName, _optionMaxBufferMs);
DisplayPlatformOption(optionsVarName, _optionBufferForPlaybackMs);
DisplayPlatformOption(optionsVarName, _optionBufferForPlaybackAfterRebufferMs);
EditorGUILayout.EndVertical();
}
*/
GUI.enabled = true;
/*
SerializedProperty propFileOffsetLow = serializedObject.FindProperty(optionsVarName + ".fileOffsetLow");
SerializedProperty propFileOffsetHigh = serializedObject.FindProperty(optionsVarName + ".fileOffsetHigh");
if (propFileOffsetLow != null && propFileOffsetHigh != null)
{
propFileOffsetLow.intValue = ;
EditorGUILayout.PropertyField(propFileOFfset);
}
*/
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 002670de62a202345a6623240ce1b36e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,368 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private static int _platformIndex = -1;
private static bool _HTTPHeadersToggle = false;
private static GUIContent[] _platformNames = null;
private void OnInspectorGUI_SelectPlatform()
{
// TODO: support multiple targets?
MediaPlayer media = (this.target) as MediaPlayer;
int i = 0;
int platformIndex = _platformIndex;
foreach (GUIContent platformText in _platformNames)
{
MediaPlayer.PlatformOptions options = media.GetPlatformOptions((Platform)i);
Color hilight = Color.yellow;
if (i == _platformIndex)
{
// Selected, unmodified
if (!options.IsModified())
{
GUI.contentColor = Color.white;
}
else
{
// Selected, modified
GUI.color = hilight;
GUI.contentColor = Color.white;
}
}
else if (options.IsModified())
{
// Unselected, modified
GUI.backgroundColor = Color.grey* hilight;
GUI.contentColor = hilight;
}
else
{
// Unselected, unmodified
if (EditorGUIUtility.isProSkin)
{
GUI.backgroundColor = Color.grey;
GUI.color = new Color(0.65f, 0.66f, 0.65f);// Color.grey;
}
}
if (i == _platformIndex)
{
if (!GUILayout.Toggle(true, _platformNames[i], GUI.skin.button))
{
platformIndex = -1;
}
}
else
{
GUI.skin.button.imagePosition = ImagePosition.ImageOnly;
if (GUILayout.Toggle(false, _platformNames[i], GUI.skin.button))
{
platformIndex = i;
}
GUI.skin.button.imagePosition = ImagePosition.ImageLeft;
}
GUI.backgroundColor = Color.white;
GUI.contentColor = Color.white;
GUI.color = Color.white;
i++;
}
//_platformIndex = GUILayout.SelectionGrid(_platformIndex, _platformNames, 3);
//return;
#if false
int rowCount = 0;
int platformIndex = _platformIndex;
const int itemsPerLine = 4;
for (int i = 0; i < _platformNames.Length; i++)
{
if (i % itemsPerLine == 0)
{
GUILayout.BeginHorizontal();
rowCount++;
}
MediaPlayer.PlatformOptions options = media.GetPlatformOptions((Platform)i);
Color hilight = Color.yellow;
if (i == _platformIndex)
{
// Selected, unmodified
if (!options.IsModified())
{
GUI.contentColor = Color.white;
}
else
{
// Selected, modified
GUI.color = hilight;
GUI.contentColor = Color.white;
}
}
else if (options.IsModified())
{
// Unselected, modified
GUI.backgroundColor = Color.grey* hilight;
GUI.contentColor = hilight;
}
else
{
// Unselected, unmodified
if (EditorGUIUtility.isProSkin)
{
GUI.backgroundColor = Color.grey;
GUI.color = new Color(0.65f, 0.66f, 0.65f);// Color.grey;
}
}
if (i == _platformIndex)
{
if (!GUILayout.Toggle(true, _platformNames[i], GUI.skin.button))
{
platformIndex = -1;
}
}
else
{
GUI.skin.button.imagePosition = ImagePosition.ImageOnly;
if (GUILayout.Toggle(false, _platformNames[i], GUI.skin.button))
{
platformIndex = i;
}
GUI.skin.button.imagePosition = ImagePosition.ImageLeft;
}
if ((i+1) % itemsPerLine == 0)
{
rowCount--;
GUILayout.EndHorizontal();
}
GUI.backgroundColor = Color.white;
GUI.contentColor = Color.white;
GUI.color = Color.white;
}
if (rowCount > 0)
{
GUILayout.EndHorizontal();
}
#endif
//platformIndex = GUILayout.SelectionGrid(_platformIndex, Helper.GetPlatformNames(), 3);
//int platformIndex = GUILayout.Toolbar(_platformIndex, Helper.GetPlatformNames());
if (platformIndex != _platformIndex)
{
_platformIndex = platformIndex;
// We do this to clear the focus, otherwise a focused text field will not change when the Toolbar index changes
EditorGUI.FocusTextInControl("ClearFocus");
}
}
private void OnInspectorGUI_PlatformOverrides()
{
foreach (AnimCollapseSection section in _platformSections)
{
AnimCollapseSection.Show(section, indentLevel:2);
}
}
private readonly static GUIContent[] _audio360ChannelMapGuiNames =
{
new GUIContent("(TBE_8_2) 8 channels of hybrid TBE ambisonics and 2 channels of head-locked stereo audio"),
new GUIContent("(TBE_8) 8 channels of hybrid TBE ambisonics. NO head-locked stereo audio"),
new GUIContent("(TBE_6_2) 6 channels of hybrid TBE ambisonics and 2 channels of head-locked stereo audio"),
new GUIContent("(TBE_6) 6 channels of hybrid TBE ambisonics. NO head-locked stereo audio"),
new GUIContent("(TBE_4_2) 4 channels of hybrid TBE ambisonics and 2 channels of head-locked stereo audio"),
new GUIContent("(TBE_4) 4 channels of hybrid TBE ambisonics. NO head-locked stereo audio"),
new GUIContent("(TBE_8_PAIR0) Channels 1 and 2 of TBE hybrid ambisonics"),
new GUIContent("(TBE_8_PAIR1) Channels 3 and 4 of TBE hybrid ambisonics"),
new GUIContent("(TBE_8_PAIR2) Channels 5 and 6 of TBE hybrid ambisonics"),
new GUIContent("(TBE_8_PAIR3) Channels 7 and 8 of TBE hybrid ambisonics"),
new GUIContent("(TBE_CHANNEL0) Channels 1 of TBE hybrid ambisonics"),
new GUIContent("(TBE_CHANNEL1) Channels 2 of TBE hybrid ambisonics"),
new GUIContent("(TBE_CHANNEL2) Channels 3 of TBE hybrid ambisonics"),
new GUIContent("(TBE_CHANNEL3) Channels 4 of TBE hybrid ambisonics"),
new GUIContent("(TBE_CHANNEL4) Channels 5 of TBE hybrid ambisonics"),
new GUIContent("(TBE_CHANNEL5) Channels 6 of TBE hybrid ambisonics"),
new GUIContent("(TBE_CHANNEL6) Channels 7 of TBE hybrid ambisonics"),
new GUIContent("(TBE_CHANNEL7) Channels 8 of TBE hybrid ambisonics"),
new GUIContent("(HEADLOCKED_STEREO) Head-locked stereo audio"),
new GUIContent("(HEADLOCKED_CHANNEL0) Channels 1 or left of head-locked stereo audio"),
new GUIContent("(HEADLOCKED_CHANNEL1) Channels 2 or right of head-locked stereo audio"),
new GUIContent("(AMBIX_4) 4 channels of first order ambiX"),
new GUIContent("(AMBIX_4_2) 4 channels of first order ambiX with 2 channels of head-locked audio"),
new GUIContent("(AMBIX_9) 9 channels of second order ambiX"),
new GUIContent("(AMBIX_9_2) 9 channels of second order ambiX with 2 channels of head-locked audio"),
new GUIContent("(AMBIX_16) 16 channels of third order ambiX"),
new GUIContent("(AMBIX_16_2) 16 channels of third order ambiX with 2 channels of head-locked audio"),
new GUIContent("(MONO) Mono audio"),
new GUIContent("(STEREO) Stereo audio"),
};
private struct FieldDescription
{
public FieldDescription(string fieldName, GUIContent description)
{
this.fieldName = fieldName;
this.description = description;
}
public string fieldName;
public GUIContent description;
}
private SerializedProperty DisplayPlatformOption(string platformOptionsFieldName, FieldDescription option)
{
return DisplayPlatformOption(this.serializedObject, platformOptionsFieldName + option.fieldName, option.description);
}
private static SerializedProperty DisplayPlatformOption(SerializedObject so, string fieldName, GUIContent description)
{
SerializedProperty prop = so.FindProperty(fieldName);
if (prop != null)
{
if (description == GUIContent.none)
{
EditorGUILayout.PropertyField(prop, true);
}
else
{
EditorGUILayout.PropertyField(prop, description, true);
}
}
else
{
Debug.LogWarning("Can't find property `" + fieldName + "`");
}
return prop;
}
private SerializedProperty DisplayPlatformOptionEnum(string platformOptionsFieldName, FieldDescription option, GUIContent[] enumNames)
{
return DisplayPlatformOptionEnum(this.serializedObject, platformOptionsFieldName + option.fieldName, option.description, enumNames);
}
private static SerializedProperty DisplayPlatformOptionEnum(SerializedObject so, string fieldName, GUIContent description, GUIContent[] enumNames)
{
SerializedProperty prop = so.FindProperty(fieldName);
if (prop != null)
{
prop.enumValueIndex = EditorGUILayout.Popup(description, prop.enumValueIndex, enumNames);
}
else
{
Debug.LogWarning("Can't find property `" + fieldName + "`");
}
return prop;
}
#if false
private void OnInspectorGUI_HlsDecryption(string optionsVarName)
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("HLS Decryption", EditorStyles.boldLabel);
// Key server auth token
SerializedProperty prop = serializedObject.FindProperty(optionsVarName + ".keyAuth.keyServerToken");
if (prop != null)
{
EditorGUILayout.PropertyField(prop, new GUIContent("Key Server Auth Token", "Token to pass to the key server in the 'Authorization' HTTP header field"));
}
GUILayout.Label("Overrides");
EditorGUI.indentLevel++;
// Key server override
/*prop = serializedObject.FindProperty(optionsVarName + ".keyServerURLOverride");
if (prop != null)
{
EditorGUILayout.PropertyField(prop, new GUIContent("Key Server URL", "Overrides the key server URL if present in a HLS manifest."));
}*/
// Key data blob override
prop = serializedObject.FindProperty(optionsVarName + ".keyAuth.overrideDecryptionKeyBase64");
if (prop != null)
{
EditorGUILayout.PropertyField(prop, new GUIContent("Key (Base64)", "Override key to use for decoding encrypted HLS streams (in Base64 format)."));
}
EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
}
private void OnInspectorGUI_HttpHeaders(string platformOptionsVarName)
{
SerializedProperty httpHeadersProp = serializedObject.FindProperty(platformOptionsVarName + ".httpHeaders.httpHeaders");
if (httpHeadersProp != null)
{
if (BeginCollapsableSection("Custom HTTP Headers", ref _HTTPHeadersToggle))
{
{
if (httpHeadersProp.arraySize > 0)
{
int deleteIndex = -1;
for (int i = 0; i < httpHeadersProp.arraySize; ++i)
{
SerializedProperty httpHeaderProp = httpHeadersProp.GetArrayElementAtIndex(i);
SerializedProperty headerProp = httpHeaderProp.FindPropertyRelative("name");
GUILayout.BeginVertical(GUI.skin.box);
GUILayout.BeginHorizontal();
GUI.color = HttpHeader.IsValid(headerProp.stringValue)?Color.white:Color.red;
EditorGUILayout.PropertyField(headerProp, GUIContent.none);
headerProp.stringValue = headerProp.stringValue.Trim();
GUI.color = Color.white;
if (GUILayout.Button("-", GUILayout.ExpandWidth(false)))
{
deleteIndex = i;
}
GUILayout.EndHorizontal();
SerializedProperty valueProp = httpHeaderProp.FindPropertyRelative("value");
GUI.color = HttpHeader.IsValid(valueProp.stringValue)?Color.white:Color.red;
valueProp.stringValue = EditorGUILayout.TextArea(valueProp.stringValue, EditorHelper.IMGUI.GetWordWrappedTextAreaStyle());
GUI.color = Color.white;
valueProp.stringValue = valueProp.stringValue.Trim();
GUILayout.EndVertical();
GUILayout.Space(4f);
}
if (deleteIndex >= 0)
{
httpHeadersProp.DeleteArrayElementAtIndex(deleteIndex);
}
}
if (GUILayout.Button("+"))
{
httpHeadersProp.InsertArrayElementAtIndex(httpHeadersProp.arraySize);
}
}
}
EndCollapsableSection();
}
}
#endif
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 02b6040b5ca06424e8ca01ecad239291
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,882 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private static GUIContent FilePathSplitEllipses = new GUIContent("-");
private static GUIContent _iconPlayButton;
private static GUIContent _iconPauseButton;
private static GUIContent _iconSceneViewAudio;
private static GUIContent _iconProject;
private static GUIContent _iconRotateTool;
private static bool _showAlpha = false;
private static bool _showPreview = false;
private static Material _materialResolve;
private static Material _materialIMGUI;
private static RenderTexture _previewTexture;
private static float _lastTextureRatio = -1f;
private static int _previewTextureFrameCount = -1;
private MediaReference _queuedLoadMediaRef = null;
private bool _queuedToggleShowPreview = false;
private void OnInspectorGUI_MediaInfo()
{
MediaPlayer media = (this.target) as MediaPlayer;
IMediaInfo info = media.Info;
IMediaControl control = media.Control;
ITextTracks textTracks = media.TextTracks;
IAudioTracks audioTracks = media.AudioTracks;
IVideoTracks videoTracks = media.VideoTracks;
ITimedMetadata timedMetadata = media.TimedMetadata;
if (info != null)
{
if (!info.HasVideo() && !info.HasAudio())// && !info.HasText())
{
GUILayout.Label("No media loaded");
}
else
{
if (info.HasVideo())
{
GUILayout.BeginHorizontal();
{
string dimensionText = string.Format("{0}x{1}@{2:0.##}", info.GetVideoWidth(), info.GetVideoHeight(), info.GetVideoFrameRate());
GUILayout.Label(dimensionText);
GUILayout.FlexibleSpace();
string rateText = "0.00";
if (media.Info != null)
{
rateText = media.Info.GetVideoDisplayRate().ToString("F2");
}
GUILayout.Label(rateText + "FPS");
}
GUILayout.EndHorizontal();
EditorGUILayout.Space();
}
if (info.HasVideo())
{
VideoTracks tracks = videoTracks.GetVideoTracks();
if (tracks.Count > 0)
{
GUILayout.Label("Video Tracks: " + tracks.Count);
foreach (VideoTrack track in tracks)
{
bool isActiveTrack = (track == videoTracks.GetActiveVideoTrack());
GUI.color = isActiveTrack ? Color.green : Color.white;
{
if (GUILayout.Button(track.DisplayName))
{
if (isActiveTrack)
{
videoTracks.SetActiveVideoTrack(null);
}
else
{
videoTracks.SetActiveVideoTrack(track);
}
}
}
}
GUI.color = Color.white;
EditorGUILayout.Space();
}
}
if (info.HasAudio())
{
AudioTracks tracks = audioTracks.GetAudioTracks();
if (tracks.Count > 0)
{
GUILayout.Label("Audio Tracks: " + tracks.Count);
foreach (AudioTrack track in tracks)
{
bool isActiveTrack = (track == audioTracks.GetActiveAudioTrack());
GUI.color = isActiveTrack ? Color.green : Color.white;
{
if (GUILayout.Button(track.DisplayName))
{
if (isActiveTrack)
{
audioTracks.SetActiveAudioTrack(null);
}
else
{
audioTracks.SetActiveAudioTrack(track);
}
}
}
}
GUI.color = Color.white;
/*int channelCount = control.GetAudioChannelCount();
if (channelCount > 0)
{
GUILayout.Label("Audio Channels: " + channelCount);
AudioChannelMaskFlags audioChannels = control.GetAudioChannelMask();
GUILayout.Label("(" + audioChannels + ")", EditorHelper.IMGUI.GetWordWrappedTextAreaStyle());
}*/
EditorGUILayout.Space();
}
}
{
TextTracks tracks = textTracks.GetTextTracks();
if (tracks.Count > 0)
{
GUILayout.Label("Text Tracks: " + tracks.Count);
foreach (TextTrack track in tracks)
{
bool isActiveTrack = (track == textTracks.GetActiveTextTrack());
GUI.color = isActiveTrack ? Color.green : Color.white;
{
if (GUILayout.Button(track.DisplayName))
{
if (isActiveTrack)
{
textTracks.SetActiveTextTrack(null);
}
else
{
textTracks.SetActiveTextTrack(track);
}
}
}
}
GUI.color = Color.white;
if (textTracks.GetActiveTextTrack() != null)
{
string text = string.Empty;
if (textTracks.GetCurrentTextCue() != null)
{
text = textTracks.GetCurrentTextCue().Text;
// Clip the text if it is too long
if (text.Length >= 96)
{
text = string.Format("{0}...({1} chars)", text.Substring(0, 96), text.Length);
}
}
GUILayout.Label(text, EditorHelper.IMGUI.GetWordWrappedTextAreaStyle(), GUILayout.Height(48f));
}
EditorGUILayout.Space();
}
}
}
}
else
{
GUILayout.Label("No media loaded");
}
}
private void ClosePreview()
{
if (_materialResolve)
{
DestroyImmediate(_materialResolve); _materialResolve = null;
}
if (_materialIMGUI)
{
DestroyImmediate(_materialIMGUI); _materialIMGUI = null;
}
if (_previewTexture)
{
RenderTexture.ReleaseTemporary(_previewTexture); _previewTexture = null;
}
}
private void RenderPreview(MediaPlayer media)
{
int textureFrameCount = media.TextureProducer.GetTextureFrameCount();
if (textureFrameCount != _previewTextureFrameCount)
{
_previewTextureFrameCount = textureFrameCount;
if (!_materialResolve)
{
_materialResolve = VideoRender.CreateResolveMaterial( false );
VideoRender.SetupResolveMaterial(_materialResolve, VideoResolveOptions.Create());
}
if (!_materialIMGUI)
{
_materialIMGUI = VideoRender.CreateIMGUIMaterial();
}
VideoRender.SetupMaterialForMedia(_materialResolve, media, -1);
VideoRender.ResolveFlags resolveFlags = (VideoRender.ResolveFlags.ColorspaceSRGB | VideoRender.ResolveFlags.Mipmaps | VideoRender.ResolveFlags.PackedAlpha | VideoRender.ResolveFlags.StereoLeft);
_previewTexture = VideoRender.ResolveVideoToRenderTexture(_materialResolve, _previewTexture, media.TextureProducer, resolveFlags);
}
}
private void DrawCenterCroppedLabel(Rect rect, string text)
{
if (Event.current.type != EventType.Repaint) return;
GUIContent textContent = new GUIContent(text);
Vector2 textSize = GUI.skin.label.CalcSize(textContent);
if (textSize.x > rect.width)
{
float ellipseWidth = GUI.skin.label.CalcSize(FilePathSplitEllipses).x;
// Left
Rect rleft = rect;
rleft.xMax -= (rleft.width / 2f);
rleft.xMax -= (ellipseWidth / 2f);
GUI.Label(rleft, textContent);
// Right
Rect rRight = rect;
rRight.xMin += (rRight.width / 2f);
rRight.xMin += (ellipseWidth / 2f);
GUI.Label(rRight, textContent, EditorHelper.IMGUI.GetRightAlignedLabelStyle());
// Center
Rect rCenter = rect;
rCenter.xMin += (rect.width / 2f) - (ellipseWidth / 2f);
rCenter.xMax -= (rect.width / 2f) - (ellipseWidth / 2f);
GUI.Label(rCenter, FilePathSplitEllipses, EditorHelper.IMGUI.GetCenterAlignedLabelStyle());
}
else
{
GUI.Label(rect, textContent, EditorHelper.IMGUI.GetCenterAlignedLabelStyle());
}
}
private void OnInspectorGUI_Player(MediaPlayer mediaPlayer, ITextureProducer textureSource)
{
EditorGUILayout.BeginVertical(GUI.skin.box);
Rect titleRect = Rect.zero;
// Display filename as title of preview
{
string mediaFileName = string.Empty;
if ((MediaSource)_propMediaSource.enumValueIndex == MediaSource.Path)
{
mediaFileName = mediaPlayer.MediaPath.Path;
}
else if ((MediaSource)_propMediaSource.enumValueIndex == MediaSource.Reference)
{
if (_propMediaReference.objectReferenceValue != null)
{
mediaFileName = ((MediaReference)_propMediaReference.objectReferenceValue).GetCurrentPlatformMediaReference().MediaPath.Path;
}
}
// Display the file name, cropping if necessary
if (!string.IsNullOrEmpty(mediaFileName) &&
(0 > mediaFileName.IndexOfAny(System.IO.Path.GetInvalidPathChars())))
{
string text = System.IO.Path.GetFileName(mediaFileName);
titleRect = GUILayoutUtility.GetRect(GUIContent.none, GUI.skin.label);
// Draw background
GUI.Box(titleRect, GUIContent.none, EditorStyles.toolbarButton);
DrawCenterCroppedLabel(titleRect, text);
}
}
// Toggle preview
if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && Event.current.isMouse)
{
if (titleRect.Contains(Event.current.mousePosition))
{
_queuedToggleShowPreview = true;
}
}
if (_showPreview)
{
Texture texture = EditorGUIUtility.whiteTexture;
float textureRatio = 16f / 9f;
if (_lastTextureRatio > 0f)
{
textureRatio = _lastTextureRatio;
}
if (textureSource != null && textureSource.GetTexture() != null)
{
texture = textureSource.GetTexture();
if (_previewTexture)
{
texture = _previewTexture;
}
_lastTextureRatio = textureRatio = (((float)texture.width / (float)texture.height) * textureSource.GetTexturePixelAspectRatio());
}
// Reserve rectangle for texture
//GUILayout.BeginHorizontal(GUILayout.MaxHeight(Screen.height / 2f), GUILayout.ExpandHeight(true));
//GUILayout.FlexibleSpace();
Rect textureRect;
//textureRect = GUILayoutUtility.GetRect(256f, 256f);
if (texture != EditorGUIUtility.whiteTexture)
{
if (_showAlpha)
{
float rectRatio = textureRatio * 2f;
rectRatio = Mathf.Max(1f, rectRatio);
textureRect = GUILayoutUtility.GetAspectRect(rectRatio, GUILayout.ExpandWidth(true));
}
else
{
//textureRatio *= 2f;
float rectRatio = Mathf.Max(1f, textureRatio);
textureRect = GUILayoutUtility.GetAspectRect(rectRatio, GUILayout.ExpandWidth(true), GUILayout.Height(256f));
/*GUIStyle style = new GUIStyle(GUI.skin.box);
style.stretchHeight = true;
style.stretchWidth = true;
style.fixedWidth = 0;
style.fixedHeight = 0;
textureRect = GUILayoutUtility.GetRect(Screen.width, Screen.width, 128f, Screen.height / 1.2f, style);*/
}
}
else
{
float rectRatio = Mathf.Max(1f, textureRatio);
textureRect = GUILayoutUtility.GetAspectRect(rectRatio, GUILayout.ExpandWidth(true), GUILayout.Height(256f));
}
if (textureRect.height > (Screen.height / 2f))
{
//textureRect.height = Screen.height / 2f;
}
//Debug.Log(textureRect.height + " " + Screen.height);
//GUILayout.FlexibleSpace();
//GUILayout.EndHorizontal();
// Pause / Play toggle on mouse click
if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && Event.current.isMouse)
{
if (textureRect.Contains(Event.current.mousePosition))
{
if (mediaPlayer.Control != null)
{
if (mediaPlayer.Control.IsPaused())
{
mediaPlayer.Play();
}
else
{
mediaPlayer.Pause();
}
}
}
}
if (Event.current.type == EventType.Repaint)
{
GUI.color = Color.gray;
EditorGUI.DrawTextureTransparent(textureRect, Texture2D.blackTexture, ScaleMode.StretchToFill);
GUI.color = Color.white;
//EditorGUI.DrawTextureAlpha(textureRect, Texture2D.whiteTexture, ScaleMode.ScaleToFit);
//GUI.color = Color.black;
//GUI.DrawTexture(textureRect, texture, ScaleMode.StretchToFill, false);
//GUI.color = Color.white;
// Draw the texture
if (textureSource != null && textureSource.RequiresVerticalFlip())
{
// GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), new Vector2(0f, textureRect.y + (textureRect.height / 2f)));
}
if (!GUI.enabled)
{
//GUI.color = Color.black;
//GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit, false);
//GUI.color = Color.white;
}
else
{
if (_showPreview && texture != EditorGUIUtility.whiteTexture)
{
RenderPreview(mediaPlayer);
}
if (!_showAlpha)
{
if (texture != EditorGUIUtility.whiteTexture)
{
// TODO: In Linear mode, this displays the texture too bright, but GUI.DrawTexture displays it correctly
//GL.sRGBWrite = true;
//GUI.DrawTexture(textureRect, rt, ScaleMode.ScaleToFit, false);
if (_previewTexture)
{
EditorGUI.DrawPreviewTexture(textureRect, _previewTexture, _materialIMGUI, ScaleMode.ScaleToFit, textureRatio);
}
//EditorGUI.DrawTextureTransparent(textureRect, rt, ScaleMode.ScaleToFit);
//VideoRender.DrawTexture(textureRect, rt, ScaleMode.ScaleToFit, AlphaPacking.None, _materialPreview);
//GL.sRGBWrite = false;
}
else
{
// Fill with black
//GUI.color = Color.black;
//GUI.DrawTexture(textureRect, texture, ScaleMode.StretchToFill, false);
//GUI.color = Color.white;
}
}
else
{
textureRect.width /= 2f;
//GUI.DrawTexture(textureRect, rt, ScaleMode.ScaleToFit, false);
//GL.sRGBWrite = true;
//VideoRender.DrawTexture(textureRect, rt, ScaleMode.ScaleToFit, AlphaPacking.None, _materialIMGUI);
//GL.sRGBWrite = false;
textureRect.x += textureRect.width;
//EditorGUI.DrawTextureAlpha(textureRect, texture, ScaleMode.ScaleToFit);
}
}
}
}
IMediaInfo info = mediaPlayer.Info;
IMediaControl control = mediaPlayer.Control;
bool showBrowseMenu = false;
if (true)
{
bool isPlaying = false;
if (control != null)
{
isPlaying = control.IsPlaying();
}
// Slider layout
EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight/2f));
Rect sliderRect = GUILayoutUtility.GetRect(GUIContent.none, GUI.skin.horizontalSlider, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
EditorGUILayout.EndHorizontal();
float currentTime = 0f;
float durationTime = 0.001f;
if (control != null)
{
currentTime = (float)control.GetCurrentTime();
durationTime = (float)info.GetDuration();
if (float.IsNaN(durationTime))
{
durationTime = 0f;
}
// RJT NOTE: Sometimes current time can exceed duration temporarily before a finished event occurs so clamp for display purposes
if (currentTime > durationTime)
{
currentTime = durationTime;
}
}
TimeRange timelineRange = new TimeRange(0.0, 0.001); // A tiny default duration to prevent divide by zero's
if (info != null)
{
timelineRange = Helper.GetTimelineRange(info.GetDuration(), control.GetSeekableTimes());
}
// Slider
{
// Draw buffering
if (control != null && timelineRange.Duration > 0.0 && Event.current.type == EventType.Repaint)
{
GUI.color = new Color(0f, 1f, 0f, 0.25f);
TimeRanges times = control.GetBufferedTimes();
if (timelineRange.Duration > 0.0)
{
for (int i = 0; i < times.Count; i++)
{
Rect bufferedRect = sliderRect;
float startT = Mathf.Clamp01((float)((times[i].StartTime - timelineRange.StartTime) / timelineRange.Duration));
float endT = Mathf.Clamp01((float)((times[i].EndTime - timelineRange.StartTime) / timelineRange.Duration));
bufferedRect.xMin = sliderRect.xMin + sliderRect.width * startT;
bufferedRect.xMax = sliderRect.xMin + sliderRect.width * endT;
bufferedRect.yMin += sliderRect.height * 0.5f;
GUI.DrawTexture(bufferedRect, Texture2D.whiteTexture);
}
}
GUI.color = Color.white;
}
// Timeline slider
{
float newTime = GUI.HorizontalSlider(sliderRect, currentTime, (float)timelineRange.StartTime, (float)timelineRange.EndTime);
if (newTime != currentTime)
{
if (control != null)
{
// NOTE: For unknown reasons the seeks here behave differently to the MediaPlayerUI demo
// When scrubbing (especially with NotchLC) while the video is playing, the frames will not update and a Stalled state will be shown,
// but using the MediaPlayerUI the same scrubbing will updates the frames. Perhaps it's just an execution order issue
control.Seek(newTime);
}
}
}
}
EditorGUILayout.BeginHorizontal();
string timeTotal = "∞";
if (!float.IsInfinity(durationTime))
{
timeTotal = Helper.GetTimeString(durationTime, false);
}
string timeUsed = Helper.GetTimeString(currentTime - (float)timelineRange.StartTime, false);
GUILayout.Label(timeUsed, GUILayout.ExpandWidth(false));
//GUILayout.Label("/", GUILayout.ExpandWidth(false));
GUILayout.FlexibleSpace();
GUILayout.Label(timeTotal, GUILayout.ExpandWidth(false));
EditorGUILayout.EndHorizontal();
// In non-pro we need to make these 3 icon content black as the buttons are light
// and the icons are white by default
if (!EditorGUIUtility.isProSkin)
{
GUI.contentColor = Color.black;
}
EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
// Play/Pause
{
float maxHeight = GUI.skin.button.CalcHeight(_iconSceneViewAudio, 0f);
if (!isPlaying)
{
GUI.color = Color.green;
if (GUILayout.Button(_iconPlayButton, GUILayout.ExpandWidth(false), GUILayout.Height(maxHeight)))
{
if (control != null)
{
control.Play();
}
else
{
if (mediaPlayer.MediaSource == MediaSource.Path)
{
mediaPlayer.OpenMedia(mediaPlayer.MediaPath.PathType, mediaPlayer.MediaPath.Path, true);
}
else if (mediaPlayer.MediaSource == MediaSource.Reference)
{
mediaPlayer.OpenMedia(mediaPlayer.MediaReference, true);
}
}
}
}
else
{
GUI.color = Color.yellow;
if (GUILayout.Button(_iconPauseButton, GUILayout.ExpandWidth(false), GUILayout.Height(maxHeight)))
{
if (control != null)
{
control.Pause();
}
}
}
GUI.color = Color.white;
}
// Looping
{
if (!_propLoop.boolValue)
{
GUI.color = Color.grey;
}
float maxHeight = GUI.skin.button.CalcHeight(_iconSceneViewAudio, 0f);
//GUIContent icon = new GUIContent("∞");
if (GUILayout.Button(_iconRotateTool, GUILayout.Height(maxHeight)))
{
if (control != null)
{
control.SetLooping(!_propLoop.boolValue);
}
_propLoop.boolValue = !_propLoop.boolValue;
}
GUI.color = Color.white;
}
// Mute & Volume
EditorGUI.BeginDisabledGroup(UnityEditor.EditorUtility.audioMasterMute);
{
if (_propMuted.boolValue)
{
GUI.color = Color.gray;
}
float maxWidth = _iconPlayButton.image.width;
//if (GUILayout.Button("Muted", GUILayout.ExpandWidth(false), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
//string iconName = "d_AudioListener Icon"; // Unity 2019+
if (GUILayout.Button(_iconSceneViewAudio))//, GUILayout.Width(maxWidth), GUILayout.Height(EditorGUIUtility.singleLineHeight), GUILayout.ExpandHeight(false)))
{
if (control != null)
{
control.MuteAudio(!_propMuted.boolValue);
}
_propMuted.boolValue = !_propMuted.boolValue;
}
GUI.color = Color.white;
}
if (!_propMuted.boolValue)
{
EditorGUI.BeginChangeCheck();
float newVolume = GUILayout.HorizontalSlider(_propVolume.floatValue, 0f, 1f, GUILayout.ExpandWidth(true), GUILayout.MinWidth(64f));
if (EditorGUI.EndChangeCheck())
{
if (control != null)
{
control.SetVolume(newVolume);
}
_propVolume.floatValue = newVolume;
}
}
EditorGUI.EndDisabledGroup();
GUI.contentColor = Color.white;
GUILayout.FlexibleSpace();
if (Event.current.commandName == "ObjectSelectorClosed" &&
EditorGUIUtility.GetObjectPickerControlID() == 200)
{
_queuedLoadMediaRef = (MediaReference)EditorGUIUtility.GetObjectPickerObject();
}
if (GUILayout.Button(_iconProject, GUILayout.ExpandWidth(false)))
{
showBrowseMenu = true;
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
if (showBrowseMenu)
{
RecentMenu.Create(_propMediaPath, _propMediaSource, MediaFileExtensions, true, 200);
}
if (_queuedLoadMediaRef && Event.current.type == EventType.Repaint)
{
//MediaPlayer mediaPlayer = (MediaPlayer)_propMediaPath.serializedObject.targetObject;
if (mediaPlayer)
{
mediaPlayer.OpenMedia(_queuedLoadMediaRef, true);
_queuedLoadMediaRef = null;
}
}
if (_queuedToggleShowPreview)
{
_showPreview = !_showPreview;
_queuedToggleShowPreview = false;
this.Repaint();
}
}
private void OnInspectorGUI_VideoPreview(MediaPlayer media, ITextureProducer textureSource)
{
EditorGUILayout.LabelField("* Inspector preview affects playback performance");
Texture texture = null;
if (textureSource != null)
{
texture = textureSource.GetTexture();
}
if (texture == null)
{
texture = EditorGUIUtility.whiteTexture;
}
float ratio = (float)texture.width / (float)texture.height;
// Reserve rectangle for texture
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
Rect textureRect;
if (texture != EditorGUIUtility.whiteTexture)
{
if (_showAlpha)
{
ratio *= 2f;
textureRect = GUILayoutUtility.GetRect(Screen.width / 2, Screen.width / 2, (Screen.width / 2) / ratio, (Screen.width / 2) / ratio);
}
else
{
textureRect = GUILayoutUtility.GetRect(Screen.width / 2, Screen.width / 2, (Screen.width / 2) / ratio, (Screen.width / 2) / ratio);
}
}
else
{
textureRect = GUILayoutUtility.GetRect(1920f / 40f, 1080f / 40f, GUILayout.ExpandWidth(true));
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
// Dimensions
string dimensionText = string.Format("{0}x{1}@{2:0.##}", 0, 0, 0.0f);
if (texture != EditorGUIUtility.whiteTexture && media.Info != null)
{
dimensionText = string.Format("{0}x{1}@{2:0.##}", texture.width, texture.height, media.Info.GetVideoFrameRate());
}
EditorHelper.IMGUI.CentreLabel(dimensionText);
string rateText = "0";
string playerText = string.Empty;
if (media.Info != null)
{
rateText = media.Info.GetVideoDisplayRate().ToString("F2");
playerText = media.Info.GetPlayerDescription();
}
EditorGUILayout.LabelField("Display Rate", rateText);
EditorGUILayout.LabelField("Using", playerText);
_showAlpha = EditorGUILayout.Toggle("Show Alpha", _showAlpha);
// Draw the texture
Matrix4x4 prevMatrix = GUI.matrix;
if (textureSource != null && textureSource.RequiresVerticalFlip())
{
GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), new Vector2(0, textureRect.y + (textureRect.height / 2)));
}
if (!GUI.enabled)
{
GUI.color = Color.grey;
GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit, false);
GUI.color = Color.white;
}
else
{
if (!_showAlpha)
{
// TODO: In Linear mode, this displays the texture too bright, but GUI.DrawTexture displays it correctly
EditorGUI.DrawTextureTransparent(textureRect, texture, ScaleMode.ScaleToFit);
}
else
{
textureRect.width /= 2f;
GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit, false);
textureRect.x += textureRect.width;
EditorGUI.DrawTextureAlpha(textureRect, texture, ScaleMode.ScaleToFit);
}
}
GUI.matrix = prevMatrix;
// Select texture button
/*if (texture != null && texture != EditorGUIUtility.whiteTexture)
{
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace();
for (int i = 0; i < textureSource.GetTextureCount(); i++)
{
Texture textures = textureSource.GetTexture(i);
if (GUILayout.Button("Select Texture", GUILayout.ExpandWidth(false)))
{
Selection.activeObject = textures;
}
}
if (GUILayout.Button("Save PNG", GUILayout.ExpandWidth(true)))
{
media.SaveFrameToPng();
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}*/
}
private void OnInspectorGUI_PlayControls(IMediaControl control, IMediaInfo info)
{
GUILayout.Space(8.0f);
// Slider
EditorGUILayout.BeginHorizontal();
bool isPlaying = false;
if (control != null)
{
isPlaying = control.IsPlaying();
}
float currentTime = 0f;
if (control != null)
{
currentTime = (float)control.GetCurrentTime();
}
float durationTime = 0f;
if (info != null)
{
durationTime = (float)info.GetDuration();
if (float.IsNaN(durationTime))
{
durationTime = 0f;
}
}
string timeUsed = Helper.GetTimeString(currentTime, true);
GUILayout.Label(timeUsed, GUILayout.ExpandWidth(false));
float newTime = GUILayout.HorizontalSlider(currentTime, 0f, durationTime, GUILayout.ExpandWidth(true));
if (newTime != currentTime)
{
control.Seek(newTime);
}
string timeTotal = "Infinity";
if (!float.IsInfinity(durationTime))
{
timeTotal = Helper.GetTimeString(durationTime, true);
}
GUILayout.Label(timeTotal, GUILayout.ExpandWidth(false));
EditorGUILayout.EndHorizontal();
// Buttons
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Rewind", GUILayout.ExpandWidth(false)))
{
control.Rewind();
}
if (!isPlaying)
{
GUI.color = Color.green;
if (GUILayout.Button("Play", GUILayout.ExpandWidth(true)))
{
control.Play();
}
}
else
{
GUI.color = Color.yellow;
if (GUILayout.Button("Pause", GUILayout.ExpandWidth(true)))
{
control.Pause();
}
}
GUI.color = Color.white;
EditorGUILayout.EndHorizontal();
}
void OnInspectorGUI_Preview()
{
MediaPlayer media = (this.target) as MediaPlayer;
EditorGUI.BeginDisabledGroup(!(media.TextureProducer != null && media.Info.HasVideo()));
OnInspectorGUI_VideoPreview(media, media.TextureProducer);
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(!(media.Control != null && media.Control.CanPlay() && media.isActiveAndEnabled && !EditorApplication.isPaused));
OnInspectorGUI_PlayControls(media.Control, media.Info);
EditorGUI.EndDisabledGroup();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 09461ea66270ee847aceeb2a5fa2fb81
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,419 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
#if UNITY_EDITOR_OSX
internal const string MediaFileExtensions = "mp4,m4v,mov,mpg,avi,mp3,m4a,aac,ac3,au,aiff,caf,wav,m3u8";
#else
internal const string MediaFileExtensions = "Media Files;*.mp4;*.mov;*.m4v;*.avi;*.mkv;*.ts;*.webm;*.flv;*.vob;*.ogg;*.ogv;*.mpg;*.wmv;*.3gp;*.mxf;Audio Files;*wav;*.mp3;*.mp2;*.m4a;*.wma;*.aac;*.au;*.flac;*.m3u8;*.mpd;*.ism;";
#endif
private readonly static GUIContent[] _fileFormatGuiNames =
{
new GUIContent("Automatic (by extension)"),
new GUIContent("Apple HLS (.m3u8)"),
new GUIContent("MPEG-DASH (.mdp)"),
new GUIContent("MS Smooth Streaming (.ism)"),
};
private SerializedProperty _propMediaSource;
private SerializedProperty _propMediaReference;
private SerializedProperty _propMediaPath;
private void OnInspectorGUI_Source()
{
// Display the file name and buttons to load new files
MediaPlayer mediaPlayer = (this.target) as MediaPlayer;
EditorGUILayout.PropertyField(_propMediaSource);
if (MediaSource.Reference == (MediaSource)_propMediaSource.enumValueIndex)
{
EditorGUILayout.PropertyField(_propMediaReference);
}
EditorGUILayout.BeginVertical(GUI.skin.box);
if (MediaSource.Reference != (MediaSource)_propMediaSource.enumValueIndex)
{
OnInspectorGUI_CopyableFilename(mediaPlayer.MediaPath.Path);
EditorGUILayout.PropertyField(_propMediaPath);
}
//if (!Application.isPlaying)
{
GUI.color = Color.white;
GUILayout.BeginHorizontal();
if (_allowDeveloperMode)
{
if (GUILayout.Button("Rewind"))
{
mediaPlayer.Rewind(true);
}
if (GUILayout.Button("End"))
{
mediaPlayer.Control.Seek(mediaPlayer.Info.GetDuration());
}
}
if (GUILayout.Button("Close"))
{
mediaPlayer.CloseMedia();
}
if (GUILayout.Button("Load"))
{
if (mediaPlayer.MediaSource == MediaSource.Path)
{
mediaPlayer.OpenMedia(mediaPlayer.MediaPath.PathType, mediaPlayer.MediaPath.Path, mediaPlayer.AutoStart);
}
else if (mediaPlayer.MediaSource == MediaSource.Reference)
{
mediaPlayer.OpenMedia(mediaPlayer.MediaReference, mediaPlayer.AutoStart);
}
}
/*if (media.Control != null)
{
if (GUILayout.Button("Unload"))
{
media.CloseVideo();
}
}*/
if (EditorGUIUtility.GetObjectPickerControlID() == 100 &&
Event.current.commandName == "ObjectSelectorClosed")
{
MediaReference mediaRef = (MediaReference)EditorGUIUtility.GetObjectPickerObject();
if (mediaRef)
{
_propMediaSource.enumValueIndex = (int)MediaSource.Reference;
_propMediaReference.objectReferenceValue = mediaRef;
}
}
GUI.color = Color.green;
MediaPathDrawer.ShowBrowseButtonIcon(_propMediaPath, _propMediaSource);
GUI.color = Color.white;
GUILayout.EndHorizontal();
//MediaPath mediaPath = new MediaPath(_propMediaPath.FindPropertyRelative("_path").stringValue, (MediaPathType)_propMediaPath.FindPropertyRelative("_pathType").enumValueIndex);
//ShowFileWarningMessages((MediaSource)_propMediaSource.enumValueIndex, mediaPath, (MediaReference)_propMediaReference.objectReferenceValue, mediaPlayer.AutoOpen, Platform.Unknown);
GUI.color = Color.white;
}
if (MediaSource.Reference != (MediaSource)_propMediaSource.enumValueIndex)
{
GUILayout.Label("Fallback Media Hints", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_propFallbackMediaHints);
}
EditorGUILayout.EndVertical();
}
internal static void OnInspectorGUI_CopyableFilename(string path)
{
if (EditorGUIUtility.isProSkin)
{
GUI.backgroundColor = Color.black;
GUI.color = Color.cyan;
}
EditorHelper.IMGUI.CopyableFilename(path);
GUI.color = Color.white;
GUI.backgroundColor = Color.white;
}
internal static void ShowFileWarningMessages(MediaSource mediaSource, MediaPath mediaPath, MediaReference mediaReference, bool isAutoOpen, Platform platform)
{
MediaPath result = null;
if (mediaSource == MediaSource.Path)
{
if (mediaPath != null)
{
result = mediaPath;
}
}
else if (mediaSource == MediaSource.Reference)
{
if (mediaReference != null)
{
result = mediaReference.GetCurrentPlatformMediaReference().MediaPath;
}
}
ShowFileWarningMessages(result, isAutoOpen, platform);
}
internal static void ShowFileWarningMessages(string filePath, MediaPathType fileLocation, MediaReference mediaReference, MediaSource mediaSource, bool isAutoOpen, Platform platform)
{
MediaPath mediaPath = null;
if (mediaSource == MediaSource.Path)
{
mediaPath = new MediaPath(filePath, fileLocation);
}
else if (mediaSource == MediaSource.Reference)
{
if (mediaReference != null)
{
mediaPath = mediaReference.GetCurrentPlatformMediaReference().MediaPath;
}
}
ShowFileWarningMessages(mediaPath, isAutoOpen, platform);
}
internal static void ShowFileWarningMessages(MediaPath mediaPath, bool isAutoOpen, Platform platform)
{
string fullPath = string.Empty;
if (mediaPath != null)
{
fullPath = mediaPath.GetResolvedFullPath();
}
if (string.IsNullOrEmpty(fullPath))
{
if (isAutoOpen)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Error, "No media specified");
}
else
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "No media specified");
}
}
else
{
bool isPlatformAndroid = platform == Platform.Android;
isPlatformAndroid |= (platform == Platform.Unknown && BuildTargetGroup.Android == UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup);
bool isPlatformIOS = (platform == Platform.iOS);
isPlatformIOS |= (platform == Platform.Unknown && BuildTargetGroup.iOS == UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup);
bool isPlatformTVOS = (platform == Platform.tvOS);
isPlatformTVOS |= (platform == Platform.Unknown && BuildTargetGroup.tvOS == UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup);
// Test file extensions
{
bool isExtensionAVI = fullPath.ToLower().EndsWith(".avi");
bool isExtensionMOV = fullPath.ToLower().EndsWith(".mov");
bool isExtensionMKV = fullPath.ToLower().EndsWith(".mkv");
#if false
// [MOZ] 250311 .mov files seem to be working fine on android
if (isPlatformAndroid && isExtensionMOV)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "MOV file detected. Android doesn't support MOV files, you should change the container file.");
}
// [MOZ] 250311 Android 8.0 is the minimum now so we can skip this
if (isPlatformAndroid && isExtensionMKV)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "MKV file detected. Android doesn't support MKV files until Android 5.0.");
}
#endif
if (isPlatformAndroid && isExtensionAVI)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "AVI file detected. Android doesn't support AVI files, you should change the container file.");
}
if (isPlatformIOS && isExtensionAVI)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "AVI file detected. iOS doesn't support AVI files, you should change the container file.");
}
}
if (fullPath.Contains("://"))
{
if (fullPath.ToLower().Contains("rtsp://"))
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "RTMP protocol is not supported by AVPro Video, except when Windows DirectShow is used with an external codec library (eg LAV Filters) and Android (limited functionality when using the MediaPlayer API)");
}
if (fullPath.ToLower().Contains("rtmp://"))
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "RTMP protocol is not supported by AVPro Video, except when Windows DirectShow is used with an external codec library (eg LAV Filters) and Android when ExoPlayer is used");
}
if (fullPath.ToLower().Contains("youtube.com/watch"))
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "YouTube URL detected. YouTube website URL contains no media, a direct media file URL (eg MP4 or M3U8) is required. See the documentation FAQ for YouTube support.");
}
if (mediaPath.PathType != MediaPathType.AbsolutePathOrURL)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "URL detected, change location type to URL?");
}
else
{
// Display warning to iOS users if they're trying to use HTTP url without setting the permission
if ((isPlatformIOS || isPlatformTVOS) && fullPath.StartsWith("http://"))
{
#if UNITY_2022_1_OR_NEWER
if (PlayerSettings.insecureHttpOption != InsecureHttpOption.AlwaysAllowed)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "PlayerSettings.insecureHttpOption must be enabled for HTTP connections (see Player Settings)");
}
#else
if (!PlayerSettings.iOS.allowHTTPDownload)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "PlayerSettings.iOS.allowHTTPDownload must be enabled for HTTP connections (see Player Settings)");
}
#endif
}
#if UNITY_ANDROID
if (fullPath.StartsWith("http://"))
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "Starting with Android 8 unsecure HTTP is not allowed by default and HTTPS must be used, unless a custom cleartext security policy is assigned");
}
#endif
// Display warning for Android users if they're trying to use a URL without setting permission
if (isPlatformAndroid && !PlayerSettings.Android.forceInternetPermission)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "You need to set 'Internet Access' to 'require' in your Player Settings for Android builds when using URLs");
}
// Display warning for UWP users if they're trying to use a URL without setting permission
if (platform == Platform.WindowsUWP || (platform == Platform.Unknown && (
BuildTargetGroup.WSA == UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup
)))
{
if (!PlayerSettings.WSA.GetCapability(PlayerSettings.WSACapability.InternetClient))
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "You need to set 'InternetClient' capability in your Player Settings when using URLs");
}
}
}
}
else
{
// [MOZ] All paths on (i|mac|tv)OS are absolute so this check just results in an incorrect warning being shown
#if !UNITY_EDITOR_OSX
if (mediaPath.PathType != MediaPathType.AbsolutePathOrURL && fullPath.StartsWith("/"))
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "Absolute path detected, change location to Absolute path?");
}
#endif
// Display warning for Android users if they're trying to use absolute file path without permission
if (isPlatformAndroid && !PlayerSettings.Android.forceSDCardPermission)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "You may need to access the local file system you may need to set 'Write Access' to 'External(SDCard)' in your Player Settings for Android");
}
if (platform == Platform.Unknown || platform == MediaPlayer.GetPlatform())
{
bool fileExists = System.IO.File.Exists(fullPath);
if (!fileExists)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Error, "File not found");
}
else
{
// Check the case
// This approach is very slow, so we only run it when the app isn't playing
if (!Application.isPlaying)
{
string folderPath = System.IO.Path.GetDirectoryName(fullPath);
// Skip empty paths and network shares
if (!string.IsNullOrEmpty(folderPath) && !folderPath.StartsWith("\\\\"))
{
string[] files;
bool caseMatch = false;
try
{
string ext = System.IO.Path.GetExtension(fullPath);
files = System.IO.Directory.GetFiles(folderPath, $"*{ext}", System.IO.SearchOption.TopDirectoryOnly);
}
catch
{
// Directory.GetFiles can fail if the folder path cannot be resolved such as if it is a network share
files = null;
caseMatch = true;
}
if (files != null && files.Length > 0)
{
string modifiedFullPath = fullPath;
#if UNITY_EDITOR_WIN
// Ensure fullPath is not using \ for the comparison
modifiedFullPath = modifiedFullPath.Replace('\\', '/');
#endif
for (int i = 0; i < files.Length; i++)
{
string filePath = System.IO.Path.Combine(folderPath, files[i]);
filePath = filePath.Replace('\\', '/');
if (filePath == modifiedFullPath)
{
caseMatch = true;
break;
}
}
}
if (!caseMatch)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "File found but case doesn't match");
}
}
}
}
}
}
}
if (mediaPath != null && mediaPath.PathType == MediaPathType.RelativeToStreamingAssetsFolder)
{
if (!System.IO.Directory.Exists(Application.streamingAssetsPath))
{
GUILayout.BeginHorizontal();
GUI.color = Color.yellow;
GUILayout.TextArea("Warning: No StreamingAssets folder found");
if (GUILayout.Button("Create Folder"))
{
System.IO.Directory.CreateDirectory(Application.streamingAssetsPath);
AssetDatabase.Refresh();
}
GUILayout.EndHorizontal();
}
else
{
bool checkAndroidFileSize = false;
#if UNITY_ANDROID
if (platform == Platform.Unknown)
{
checkAndroidFileSize = true;
}
#endif
if (platform == Platform.Android)
{
checkAndroidFileSize = true;
}
if (checkAndroidFileSize)
{
try
{
System.IO.FileInfo info = new System.IO.FileInfo(fullPath);
if (info != null && info.Length > (1024 * 1024 * 512))
{
EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "Using this very large file inside StreamingAssets folder on Android isn't recommended. Deployments will be slow and mapping the file from the StreamingAssets JAR may cause storage and memory issues. We recommend loading from another folder on the device.");
}
}
catch (System.Exception)
{
}
}
}
}
GUI.color = Color.white;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d48dbd69cf9694e439fa465103879d35
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
#if UNITY_EDITOR_OSX
internal const string SubtitleFileExtensions = "srt";
#else
internal const string SubtitleFileExtensions = "Subtitle Files;*.srt";
#endif
private SerializedProperty _propSubtitles;
private SerializedProperty _propSubtitlePath;
private void OnInspectorGUI_Subtitles()
{
// TODO: add support for multiple targets?
MediaPlayer media = (this.target) as MediaPlayer;
//EditorGUILayout.BeginVertical();
EditorGUILayout.PropertyField(_propSubtitles, new GUIContent("Sideload Subtitles"));
EditorGUI.BeginDisabledGroup(!_propSubtitles.boolValue);
EditorGUILayout.BeginVertical(GUI.skin.box);
EditorGUILayout.PropertyField(_propSubtitlePath);
//if (!Application.isPlaying)
{
GUI.color = Color.white;
GUILayout.BeginHorizontal();
if (Application.isPlaying)
{
if (GUILayout.Button("Load"))
{
MediaPath mediaPath = new MediaPath(_propSubtitlePath.FindPropertyRelative("_path").stringValue, (MediaPathType)_propSubtitlePath.FindPropertyRelative("_pathType").enumValueIndex);
media.EnableSubtitles(mediaPath);
}
if (GUILayout.Button("Clear"))
{
media.DisableSubtitles();
}
}
else
{
GUILayout.FlexibleSpace();
}
MediaPathDrawer.ShowBrowseSubtitlesButtonIcon(_propSubtitlePath);
GUILayout.EndHorizontal();
if (_propSubtitles.boolValue)
{
///MediaPath mediaPath = new MediaPath(_propSubtitlePath.FindPropertyRelative("_path").stringValue, (MediaPathType)_propSubtitlePath.FindPropertyRelative("_pathType").enumValueIndex);
//ShowFileWarningMessages(mediaPath, media.AutoOpen, Platform.Unknown);
//GUI.color = Color.white;
}
}
//EditorGUILayout.EndVertical();
EditorGUILayout.EndVertical();
EditorGUI.EndDisabledGroup();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a04b089da8164054e9997d11d2b2f9a4
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private readonly static FieldDescription _optionExternalLibrary = new FieldDescription(".externalLibrary", GUIContent.none);
private void OnInspectorGUI_Override_WebGL()
{
GUILayout.Space(8f);
string optionsVarName = MediaPlayer.GetPlatformOptionsVariable(Platform.WebGL);
EditorGUILayout.BeginVertical(GUI.skin.box);
DisplayPlatformOption(optionsVarName, _optionExternalLibrary);
SerializedProperty propUseTextureMips = DisplayPlatformOption(optionsVarName, _optionTextureMips);
if (propUseTextureMips.boolValue && ((FilterMode)_propFilter.enumValueIndex) != FilterMode.Trilinear)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "Recommend changing the texture filtering mode to Trilinear when using mip-maps.");
}
EditorGUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 204fbdf92f39c6847ac3e270ca56dc09
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,308 @@
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2015-2025 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlayer component
/// </summary>
public partial class MediaPlayerEditor : UnityEditor.Editor
{
private SerializedProperty _propSourceAudioSampleRate;
private SerializedProperty _propSourceAudioChannels;
private SerializedProperty _propManualSetAudioProps;
private readonly static GUIContent[] _audioModesWindows =
{
new GUIContent("System Direct"),
new GUIContent("Unity", "Allows the AudioOutput component to grab audio from the video and play it through Unity to the AudioListener"),
new GUIContent("Facebook Audio 360", "Initialises player with Facebook Audio 360 support"),
new GUIContent("None", "No audio"),
};
private readonly static GUIContent[] _audioModesUWP =
{
new GUIContent("System Direct"),
new GUIContent("Unity", "Allows the AudioOutput component to grab audio from the video and play it through Unity to the AudioListener"),
new GUIContent("Facebook Audio 360", "Initialises player with Facebook Audio 360 support"),
new GUIContent("None", "No audio"),
};
private readonly static FieldDescription _optionLowLatency = new FieldDescription(".useLowLatency", new GUIContent("Use Low Latency", "Provides a hint to the decoder to use less buffering - may degrade performance and quality"));
private readonly static FieldDescription _optionVideoAPI = new FieldDescription(".videoApi", new GUIContent("Video API", "The preferred video API to use"));
private readonly static FieldDescription _optionVideoOutputMode = new FieldDescription(".videoOutputMode", new GUIContent("Video Output Mode"));
private readonly static FieldDescription _optionTextureMips = new FieldDescription(".useTextureMips", new GUIContent("Generate Mipmaps", "Automatically create mip-maps for the texture to reducing aliasing when texture is scaled down"));
private readonly static FieldDescription _option10BitTextures = new FieldDescription(".use10BitTextures", new GUIContent("Use 10-Bit Textures", "Provides a hint to the decoder to use 10-bit textures - allowing more quality for videos encoded with a 10-bit profile"));
private readonly static FieldDescription _optionUseHardwareDecoding = new FieldDescription(".useHardwareDecoding", new GUIContent("Hardware Decoding"));
private readonly static FieldDescription _optionUseRendererSync = new FieldDescription(".useRendererSync", new GUIContent("Renderer Sync", "Ensure synchronisation between video textures and Unity rendering - alleviates potential playback artifacts"));
private readonly static FieldDescription _optionUseStereoDetection = new FieldDescription(".useStereoDetection", new GUIContent("Use Stereo Detection", "Disable if no stereo detection is required"));
private readonly static FieldDescription _optionUseTextTrackSupport = new FieldDescription(".useTextTrackSupport", new GUIContent("Use Text Tracks", "Disable if no text tracks are required"));
private readonly static FieldDescription _optionUseAudioDelay = new FieldDescription(".useAudioDelay", new GUIContent("Use Audio Delay", "Allows audio to be offset"));
private readonly static FieldDescription _optionUseFacebookAudio360Support = new FieldDescription(".useFacebookAudio360Support", new GUIContent("Use Facebook Audio 360", "Disable if no Facebook Audio 360 support is required for"));
private readonly static FieldDescription _optionUseHapNotchLC = new FieldDescription(".useHapNotchLC", new GUIContent("Use Hap/NotchLC", "Disable if no Hap/NotchLC playback is required"));
private readonly static FieldDescription _optionCustomMovParser = new FieldDescription(".useCustomMovParser", new GUIContent("Use Custom MOV Parser", "For playback of Hap and NotchLC media to handle high bit-rates"));
private readonly static FieldDescription _optionParallelFrameCount = new FieldDescription(".parallelFrameCount", new GUIContent("Parallel Frame Count", "Number of frames to decode in parallel via multi-threading. Higher values increase latency but can improve performance for demanding videos."));
private readonly static FieldDescription _optionPrerollFrameCount = new FieldDescription(".prerollFrameCount", new GUIContent("Preroll Frame Count", "Number of frames to pre-decode before playback starts. Higher values increase latency but can improve performance for demanding videos."));
private readonly static FieldDescription _optionAudioOutput = new FieldDescription("._audioMode", new GUIContent("Audio Output"));
private readonly static FieldDescription _optionAudio360ChannelMode = new FieldDescription(".audio360ChannelMode", new GUIContent("Channel Mode", "Specifies what channel mode Facebook Audio 360 needs to be initialised with"));
private readonly static FieldDescription _optionAudio360LatencyMS = new FieldDescription(".audio360LatencyMS", new GUIContent("Audio Latency (ms)", "Specifies audio latency, in milliseconds, that Facebook Audio 360 needs to be initialised with. -ve will play audio sooner, +ve later."));
private readonly static FieldDescription _optionStartMaxBitrate = new FieldDescription(".startWithHighestBitrate", new GUIContent("Start Max Bitrate"));
private readonly static FieldDescription _optionUseLowLiveLatency = new FieldDescription(".useLowLiveLatency", new GUIContent("Low Live Latency"));
private readonly static FieldDescription _optionHintAlphaChannel = new FieldDescription(".hintAlphaChannel", new GUIContent("Alpha Channel Hint", "If a video is detected as 32-bit, use or ignore the alpha channel"));
private readonly static FieldDescription _optionForceAudioOutputDeviceName = new FieldDescription(".forceAudioOutputDeviceName", new GUIContent("Force Audio Output Device Name", "Useful for VR when you need to output to the VR audio device"));
private readonly static FieldDescription _optionPreferredFilters = new FieldDescription(".preferredFilters", new GUIContent("Preferred Filters", "Priority list for preferred filters to be used instead of default"));
private void OnInspectorGUI_Override_Windows()
{
//MediaPlayer media = (this.target) as MediaPlayer;
//MediaPlayer.OptionsWindows options = media._optionsWindows;
GUILayout.Space(8f);
EditorGUILayout.BeginVertical(GUI.skin.box);
string optionsVarName = MediaPlayer.GetPlatformOptionsVariable(Platform.Windows);
{
SerializedProperty propVideoApi = DisplayPlatformOption(optionsVarName, _optionVideoAPI);
{
SerializedProperty propUseTextureMips = DisplayPlatformOption(optionsVarName, _optionTextureMips);
if (propUseTextureMips.boolValue && ((FilterMode)_propFilter.enumValueIndex) != FilterMode.Trilinear)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "Recommend changing the texture filtering mode to Trilinear when using mip-maps.");
}
}
{
SerializedProperty propUseHardwareDecoding = serializedObject.FindProperty(optionsVarName + _optionUseHardwareDecoding.fieldName);
EditorGUI.BeginDisabledGroup(!propUseHardwareDecoding.boolValue && propVideoApi.enumValueIndex == (int)Windows.VideoApi.MediaFoundation);
{
DisplayPlatformOption(optionsVarName, _option10BitTextures);
}
EditorGUI.EndDisabledGroup();
}
}
EditorGUILayout.EndVertical();
// Media Foundation Options
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Media Foundation API Options", EditorStyles.boldLabel);
{
DisplayPlatformOption(optionsVarName, _optionUseHardwareDecoding);
DisplayPlatformOption(optionsVarName, _optionUseRendererSync);
}
{
DisplayPlatformOption(optionsVarName, _optionLowLatency);
DisplayPlatformOption(optionsVarName, _optionUseStereoDetection);
DisplayPlatformOption(optionsVarName, _optionUseTextTrackSupport);
if (_showUltraOptions)
{
SerializedProperty useHapNotchLC = DisplayPlatformOption(optionsVarName, _optionUseHapNotchLC);
if (useHapNotchLC.boolValue)
{
EditorGUI.indentLevel++;
DisplayPlatformOption(optionsVarName, _optionCustomMovParser);
DisplayPlatformOption(optionsVarName, _optionParallelFrameCount);
DisplayPlatformOption(optionsVarName, _optionPrerollFrameCount);
EditorGUI.indentLevel--;
}
}
}
// Audio Output
{
SerializedProperty propAudioDelay = DisplayPlatformOption(optionsVarName, _optionUseAudioDelay);
if (propAudioDelay.boolValue)
{
//EditorGUI.indentLevel++;
//EditorGUI.indentLevel--;
}
DisplayPlatformOption(optionsVarName, _optionUseFacebookAudio360Support);
SerializedProperty propAudioOutput = DisplayPlatformOptionEnum(optionsVarName, _optionAudioOutput, _audioModesWindows);
if (_showUltraOptions && (Windows.AudioOutput)propAudioOutput.enumValueIndex == Windows.AudioOutput.FacebookAudio360)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Facebook Audio 360", EditorStyles.boldLabel);
DisplayPlatformOptionEnum(optionsVarName, _optionAudio360ChannelMode, _audio360ChannelMapGuiNames);
{
SerializedProperty propForceAudioOutputDeviceName = serializedObject.FindProperty(optionsVarName + ".forceAudioOutputDeviceName");
if (propForceAudioOutputDeviceName != null)
{
string[] deviceNames = { "Default", Windows.AudioDeviceOutputName_Rift, Windows.AudioDeviceOutputName_Vive, "Custom" };
int index = 0;
if (!string.IsNullOrEmpty(propForceAudioOutputDeviceName.stringValue))
{
switch (propForceAudioOutputDeviceName.stringValue)
{
case Windows.AudioDeviceOutputName_Rift:
index = 1;
break;
case Windows.AudioDeviceOutputName_Vive:
index = 2;
break;
default:
index = 3;
break;
}
}
int newIndex = EditorGUILayout.Popup("Audio Device Name", index, deviceNames);
if (newIndex == 0)
{
propForceAudioOutputDeviceName.stringValue = string.Empty;
}
else if (newIndex == 3)
{
if (index != newIndex)
{
if (string.IsNullOrEmpty(propForceAudioOutputDeviceName.stringValue) ||
propForceAudioOutputDeviceName.stringValue == Windows.AudioDeviceOutputName_Rift ||
propForceAudioOutputDeviceName.stringValue == Windows.AudioDeviceOutputName_Vive)
{
propForceAudioOutputDeviceName.stringValue = "?";
}
}
EditorGUILayout.PropertyField(propForceAudioOutputDeviceName, new GUIContent("Audio Device Name", "Useful for VR when you need to output to the VR audio device"));
}
else
{
propForceAudioOutputDeviceName.stringValue = deviceNames[newIndex];
}
}
}
}
}
EditorGUILayout.EndVertical();
}
// WinRT Options
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("WinRT API Options", EditorStyles.boldLabel);
DisplayPlatformOption(optionsVarName, _optionStartMaxBitrate);
DisplayPlatformOption(optionsVarName, _optionUseLowLiveLatency);
if (_showUltraOptions)
{
SerializedProperty httpHeadersProp = serializedObject.FindProperty(optionsVarName + ".httpHeaders.httpHeaders");
if (httpHeadersProp != null)
{
OnInspectorGUI_HttpHeaders(httpHeadersProp);
}
GUILayout.Space(8f);
SerializedProperty keyAuthProp = serializedObject.FindProperty(optionsVarName + ".keyAuth");
if (keyAuthProp != null)
{
OnInspectorGUI_HlsDecryption(keyAuthProp);
}
}
EditorGUILayout.EndVertical();
}
// DirectShow Options
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("DirectShow API Options", EditorStyles.boldLabel);
DisplayPlatformOption(optionsVarName, _optionHintAlphaChannel);
DisplayPlatformOption(optionsVarName, _optionForceAudioOutputDeviceName);
{
int prevIndentLevel = EditorGUI.indentLevel;
EditorGUI.indentLevel = 1;
SerializedProperty propPreferredFilter = DisplayPlatformOption(optionsVarName, _optionPreferredFilters);
if (propPreferredFilter.arraySize > 0)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "Command filter names are:\n1) \"Microsoft DTV-DVD Video Decoder\" (best for compatibility when playing H.264 videos)\n2) \"LAV Video Decoder\"\n3) \"LAV Audio Decoder\"");
}
EditorGUI.indentLevel = prevIndentLevel;
}
EditorGUILayout.EndVertical();
}
}
private void OnInspectorGUI_Override_WindowsUWP()
{
//MediaPlayer media = (this.target) as MediaPlayer;
//MediaPlayer.OptionsWindowsUWP options = media._optionsWindowsUWP;
GUILayout.Space(8f);
string optionsVarName = MediaPlayer.GetPlatformOptionsVariable(Platform.WindowsUWP);
EditorGUILayout.BeginVertical(GUI.skin.box);
if (_showUltraOptions)
{
SerializedProperty propVideoApi = DisplayPlatformOption(optionsVarName, _optionVideoAPI);
{
SerializedProperty propUseHardwareDecoding = serializedObject.FindProperty(optionsVarName + _optionUseHardwareDecoding.fieldName);
EditorGUI.BeginDisabledGroup(!propUseHardwareDecoding.boolValue && propVideoApi.enumValueIndex == (int)Windows.VideoApi.MediaFoundation);
{
DisplayPlatformOption(optionsVarName, _option10BitTextures);
}
EditorGUI.EndDisabledGroup();
}
}
EditorGUILayout.EndVertical();
// Media Foundation Options
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Media Foundation API Options", EditorStyles.boldLabel);
DisplayPlatformOption(optionsVarName, _optionUseHardwareDecoding);
DisplayPlatformOption(optionsVarName, _optionUseRendererSync);
{
SerializedProperty propUseTextureMips = DisplayPlatformOption(optionsVarName, _optionTextureMips);
if (propUseTextureMips.boolValue && ((FilterMode)_propFilter.enumValueIndex) != FilterMode.Trilinear)
{
EditorHelper.IMGUI.NoticeBox(MessageType.Info, "Recommend changing the texture filtering mode to Trilinear when using mip-maps.");
}
}
DisplayPlatformOption(optionsVarName, _optionLowLatency);
DisplayPlatformOptionEnum(optionsVarName, _optionAudioOutput, _audioModesUWP);
EditorGUILayout.EndVertical();
}
// WinRT Options
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("WinRT API Options", EditorStyles.boldLabel);
DisplayPlatformOption(optionsVarName, _optionStartMaxBitrate);
DisplayPlatformOption(optionsVarName, _optionUseLowLiveLatency);
if (_showUltraOptions)
{
{
SerializedProperty httpHeadersProp = serializedObject.FindProperty(optionsVarName + ".httpHeaders.httpHeaders");
if (httpHeadersProp != null)
{
OnInspectorGUI_HttpHeaders(httpHeadersProp);
}
}
{
SerializedProperty keyAuthProp = serializedObject.FindProperty(optionsVarName + ".keyAuth");
if (keyAuthProp != null)
{
OnInspectorGUI_HlsDecryption(keyAuthProp);
}
}
}
EditorGUILayout.EndVertical();
}
GUI.enabled = true;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f96124fabf3e8cb46a512e3ecdbd6a3c
timeCreated: 1448902492
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,517 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
//-----------------------------------------------------------------------------
// Copyright 2015-2022 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the MediaPlaylist class
/// </summary>
[CustomPropertyDrawer(typeof(MediaPlaylist))]
public class MediaPlaylistDrawer : PropertyDrawer
{
private static readonly GUIContent _guiTextInsert = new GUIContent("Clone");
private static readonly GUIContent _guiTextDelete = new GUIContent("Delete");
private static readonly GUIContent _guiTextUp = new GUIContent("↑");
private static readonly GUIContent _guiTextDown = new GUIContent("↓");
private static GUIStyle _styleButtonFoldout = null;
private static GUIStyle _styleHelpBoxNoPad = null;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (_styleButtonFoldout == null)
{
_styleButtonFoldout = new GUIStyle(EditorStyles.foldout);
_styleButtonFoldout.margin = new RectOffset();
_styleButtonFoldout.fontStyle = FontStyle.Bold;
_styleButtonFoldout.alignment = TextAnchor.MiddleLeft;
}
if (_styleHelpBoxNoPad == null)
{
_styleHelpBoxNoPad = new GUIStyle(EditorStyles.helpBox);
_styleHelpBoxNoPad.padding = new RectOffset();
_styleHelpBoxNoPad.overflow = new RectOffset();
_styleHelpBoxNoPad.margin = new RectOffset();
_styleHelpBoxNoPad.margin = new RectOffset(0, 0, 0, 0);
_styleHelpBoxNoPad.stretchWidth = false;
_styleHelpBoxNoPad.stretchHeight = false;
}
// Using BeginProperty / EndProperty on the parent property means that
// prefab override logic works on the entire property.
EditorGUI.BeginProperty(position, label, property);
SerializedProperty propItems = property.FindPropertyRelative("_items");
if (propItems.arraySize == 0)
{
if (GUILayout.Button("Insert Item"))
{
propItems.InsertArrayElementAtIndex(0);
}
}
int insertIndex = -1;
int deleteIndex = -1;
for (int i = 0; i < propItems.arraySize; i++)
{
SerializedProperty propItem = propItems.GetArrayElementAtIndex(i);
GUILayout.BeginVertical(_styleHelpBoxNoPad);
GUI.backgroundColor = propItem.isExpanded ? Color.yellow : Color.white;
GUILayout.Box(GUIContent.none, EditorStyles.miniButton, GUILayout.ExpandWidth(true));
Rect buttonRect = GUILayoutUtility.GetLastRect();
GUI.backgroundColor = Color.white;
if (Event.current.type != EventType.Layout)
{
EditorGUI.indentLevel++;
SerializedProperty propName = propItem.FindPropertyRelative("name");
propItem.isExpanded = EditorGUI.Foldout(buttonRect, propItem.isExpanded, "#" + i + ": " + propName.stringValue, true, _styleButtonFoldout);
EditorGUI.indentLevel--;
}
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(_guiTextInsert, GUILayout.ExpandWidth(false)))
{
insertIndex = i;
}
if (GUILayout.Button(_guiTextDelete, GUILayout.ExpandWidth(false)))
{
deleteIndex = i;
}
EditorGUI.BeginDisabledGroup((i - 1) < 0);
if (GUILayout.Button(_guiTextUp, GUILayout.ExpandWidth(false)))
{
propItems.MoveArrayElement(i, i - 1);
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup((i + 1) >= propItems.arraySize);
if (GUILayout.Button(_guiTextDown, GUILayout.ExpandWidth(false)))
{
propItems.MoveArrayElement(i, i + 1);
}
EditorGUI.EndDisabledGroup();
GUILayout.EndHorizontal();
if (propItem.isExpanded)
{
EditorGUILayout.PropertyField(propItem);
}
GUILayout.EndVertical();
GUILayout.Space(8f);
}
if (insertIndex >= 0)
{
propItems.InsertArrayElementAtIndex(insertIndex);
}
else if (deleteIndex >= 0)
{
propItems.DeleteArrayElementAtIndex(deleteIndex);
}
EditorGUI.EndProperty();
}
}
/// <summary>
/// Editor for the MediaPlaylist.MediaItem class
/// </summary>
[CustomPropertyDrawer(typeof(MediaPlaylist.MediaItem))]
public class MediaPlaylistItemDrawer : PropertyDrawer
{
private static readonly GUIContent _guiTextTransition = new GUIContent("Transition");
private static readonly GUIContent _guiTextOverrideTransition = new GUIContent("Override Transition");
private static readonly GUIContent _guiTextDuration = new GUIContent("Duration");
private static readonly GUIContent _guiTextEasing = new GUIContent("Easing");
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUILayout.PropertyField(property.FindPropertyRelative("name"));
SerializedProperty propSourceType = property.FindPropertyRelative("sourceType");
EditorGUILayout.PropertyField(propSourceType);
if (propSourceType.enumValueIndex == 0)
{
EditorGUILayout.PropertyField(property.FindPropertyRelative("mediaPath"));
MediaPathDrawer.ShowBrowseButton(property.FindPropertyRelative("mediaPath"));
}
else
{
//EditorGUILayout.PropertyField(property.FindPropertyRelative("texture"));
//EditorGUILayout.PropertyField(property.FindPropertyRelative("textureDuration"));
}
EditorGUILayout.Space();
//EditorGUILayout.PropertyField(property.FindPropertyRelative("stereoPacking"));
//EditorGUILayout.PropertyField(property.FindPropertyRelative("alphaPacking"));
EditorGUILayout.Space();
EditorGUILayout.PropertyField(property.FindPropertyRelative("loop"));
EditorGUILayout.PropertyField(property.FindPropertyRelative("startMode"));
SerializedProperty propProgressMode = property.FindPropertyRelative("progressMode");
EditorGUILayout.PropertyField(propProgressMode);
if (propProgressMode.enumValueIndex == (int)PlaylistMediaPlayer.ProgressMode.BeforeFinish)
{
EditorGUILayout.PropertyField(property.FindPropertyRelative("progressTimeSeconds"));
}
EditorGUILayout.Space();
SerializedProperty propIsOverrideTransition = property.FindPropertyRelative("isOverrideTransition");
EditorGUILayout.PropertyField(propIsOverrideTransition, _guiTextOverrideTransition);
if (propIsOverrideTransition.boolValue)
{
EditorGUI.indentLevel++;
SerializedProperty propTransitionMode = property.FindPropertyRelative("overrideTransition");
EditorGUILayout.PropertyField(propTransitionMode, _guiTextTransition);
if (propTransitionMode.enumValueIndex != (int)PlaylistMediaPlayer.Transition.None)
{
EditorGUILayout.PropertyField(property.FindPropertyRelative("overrideTransitionDuration"), _guiTextDuration);
EditorGUILayout.PropertyField(property.FindPropertyRelative("overrideTransitionEasing"), _guiTextEasing);
}
EditorGUI.indentLevel--;
}
}
}
/// <summary>
/// Editor for the PlaylistMediaPlayer component
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(PlaylistMediaPlayer))]
public class PlaylistMediaPlayerEditor : UnityEditor.Editor
{
private SerializedProperty _propPlayerA;
private SerializedProperty _propPlayerB;
private SerializedProperty _propPlaylist;
private SerializedProperty _propPlaylistAutoProgress;
private SerializedProperty _propAutoCloseVideo;
private SerializedProperty _propPlaylistLoopMode;
private SerializedProperty _propPausePreviousOnTransition;
private SerializedProperty _propDefaultTransition;
private SerializedProperty _propDefaultTransitionDuration;
private SerializedProperty _propDefaultTransitionEasing;
private SerializedProperty _propAudioVolume;
private SerializedProperty _propAudioMuted;
private static bool _expandPlaylistItems = false;
private static Material _materialIMGUI = null;
private static GUIStyle _sectionBoxStyle = null;
private const string SettingsPrefix = "AVProVideo-PlaylistMediaPlayerEditor-";
private void OnEnable()
{
_propPlayerA = this.CheckFindProperty("_playerA");
_propPlayerB = this.CheckFindProperty("_playerB");
_propDefaultTransition = this.CheckFindProperty("_defaultTransition");
_propDefaultTransitionDuration = this.CheckFindProperty("_defaultTransitionDuration");
_propDefaultTransitionEasing = this.CheckFindProperty("_defaultTransitionEasing");
_propPausePreviousOnTransition = this.CheckFindProperty("_pausePreviousOnTransition");
_propPlaylist = this.CheckFindProperty("_playlist");
_propPlaylistAutoProgress = this.CheckFindProperty("_playlistAutoProgress");
_propAutoCloseVideo = this.CheckFindProperty("_autoCloseVideo");
_propPlaylistLoopMode = this.CheckFindProperty("_playlistLoopMode");
_propAudioVolume = this.CheckFindProperty("_playlistAudioVolume");
_propAudioMuted = this.CheckFindProperty("_playlistAudioMuted");
_expandPlaylistItems = EditorPrefs.GetBool(SettingsPrefix + "ExpandPlaylistItems", false);
}
private void OnDisable()
{
EditorPrefs.SetBool(SettingsPrefix + "ExpandPlaylistItems", _expandPlaylistItems);
if (_materialIMGUI)
{
DestroyImmediate(_materialIMGUI); _materialIMGUI = null;
}
}
public override bool RequiresConstantRepaint()
{
PlaylistMediaPlayer media = (this.target) as PlaylistMediaPlayer;
return (media.Control != null && media.isActiveAndEnabled);
}
public override void OnInspectorGUI()
{
PlaylistMediaPlayer media = (this.target) as PlaylistMediaPlayer;
serializedObject.Update();
if (media == null || _propPlayerA == null)
{
return;
}
if (_sectionBoxStyle == null)
{
_sectionBoxStyle = new GUIStyle(GUI.skin.box);
_sectionBoxStyle.padding.top = 0;
_sectionBoxStyle.padding.bottom = 0;
}
EditorGUILayout.PropertyField(_propPlayerA);
EditorGUILayout.PropertyField(_propPlayerB);
EditorGUILayout.Space();
EditorGUILayout.Space();
GUILayout.Label("Audio", EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propAudioVolume, new GUIContent("Volume"));
if (EditorGUI.EndChangeCheck())
{
foreach (PlaylistMediaPlayer player in this.targets)
{
player.AudioVolume = _propAudioVolume.floatValue;
}
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_propAudioMuted, new GUIContent("Muted"));
if (EditorGUI.EndChangeCheck())
{
foreach (PlaylistMediaPlayer player in this.targets)
{
player.AudioMuted = _propAudioMuted.boolValue;
}
}
EditorGUILayout.Space();
EditorGUILayout.Space();
GUILayout.Label("Playlist", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_propPlaylistAutoProgress, new GUIContent("Auto Progress"));
EditorGUILayout.PropertyField(_propPlaylistLoopMode, new GUIContent("Loop Mode"));
EditorGUILayout.PropertyField(_propAutoCloseVideo);
{
EditorGUILayout.Space();
EditorGUILayout.Space();
GUI.color = Color.white;
GUI.backgroundColor = Color.clear;
if (_expandPlaylistItems)
{
GUI.color = Color.white;
GUI.backgroundColor = new Color(0.8f, 0.8f, 0.8f, 0.1f);
if (EditorGUIUtility.isProSkin)
{
GUI.backgroundColor = Color.black;
}
}
GUILayout.BeginVertical(_sectionBoxStyle);
GUI.backgroundColor = Color.white;
if (GUILayout.Button("Playlist Items", EditorStyles.toolbarButton))
{
_expandPlaylistItems = !_expandPlaylistItems;
}
GUI.color = Color.white;
if (_expandPlaylistItems)
{
EditorGUILayout.PropertyField(_propPlaylist);
}
GUILayout.EndVertical();
}
EditorGUILayout.Space();
EditorGUILayout.Space();
GUILayout.Label("Default Transition", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_propDefaultTransition, new GUIContent("Transition"));
EditorGUILayout.PropertyField(_propDefaultTransitionEasing, new GUIContent("Easing"));
EditorGUILayout.PropertyField(_propDefaultTransitionDuration, new GUIContent("Duration"));
EditorGUILayout.PropertyField(_propPausePreviousOnTransition, new GUIContent("Pause Previous"));
EditorGUILayout.Space();
EditorGUILayout.Space();
if (Application.isPlaying)
{
ITextureProducer textureSource = media.TextureProducer;
Texture texture = null;
if (textureSource != null)
{
texture = textureSource.GetTexture();
}
if (texture == null)
{
texture = EditorGUIUtility.whiteTexture;
}
float ratio = 1f;// (float)texture.width / (float)texture.height;
// Reserve rectangle for texture
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
Rect textureRect;
if (texture != EditorGUIUtility.whiteTexture)
{
textureRect = GUILayoutUtility.GetRect(Screen.width / 2, Screen.width / 2, (Screen.width / 2) / ratio, (Screen.width / 2) / ratio);
}
else
{
textureRect = GUILayoutUtility.GetRect(1920f / 40f, 1080f / 40f);
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
string rateText = "0";
string playerText = string.Empty;
if (media.Info != null)
{
rateText = media.Info.GetVideoDisplayRate().ToString("F2");
playerText = media.Info.GetPlayerDescription();
}
EditorGUILayout.LabelField("Display Rate", rateText);
EditorGUILayout.LabelField("Using", playerText);
// Draw the texture
if (Event.current.type == EventType.Repaint)
{
Matrix4x4 prevMatrix = GUI.matrix;
if (textureSource != null && textureSource.RequiresVerticalFlip())
{
GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), new Vector2(0f, textureRect.y + (textureRect.height / 2f)));
}
GUI.color = Color.gray;
EditorGUI.DrawTextureTransparent(textureRect, Texture2D.blackTexture, ScaleMode.StretchToFill);
GUI.color = Color.white;
if (!GUI.enabled)
{
GUI.color = Color.grey;
GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit, false);
GUI.color = Color.white;
}
else
{
if (!_materialIMGUI)
{
_materialIMGUI = VideoRender.CreateResolveMaterial( false );
VideoRender.SetupGammaMaterial(_materialIMGUI, true);
}
{
EditorGUI.DrawPreviewTexture(textureRect, texture, _materialIMGUI, ScaleMode.ScaleToFit);
}
}
GUI.matrix = prevMatrix;
}
}
EditorGUI.BeginDisabledGroup(!(media.Control != null && media.Control.CanPlay() && media.isActiveAndEnabled && !EditorApplication.isPaused));
OnInspectorGUI_PlayControls(media);
EditorGUI.EndDisabledGroup();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(!Application.isPlaying);
GUILayout.Label("Current Item: " + media.PlaylistIndex + " / " + Mathf.Max(0, media.Playlist.Items.Count - 1) );
GUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(!media.CanJumpToItem(media.PlaylistIndex - 1));
if (GUILayout.Button("Prev"))
{
media.PrevItem();
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(!media.CanJumpToItem(media.PlaylistIndex + 1));
if (GUILayout.Button("Next"))
{
media.NextItem();
}
EditorGUI.EndDisabledGroup();
GUILayout.EndHorizontal();
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
}
private void OnInspectorGUI_PlayControls(PlaylistMediaPlayer player)
{
GUILayout.Space(8.0f);
// Slider
EditorGUILayout.BeginHorizontal();
bool isPlaying = false;
if (player.Control != null)
{
isPlaying = player.Control.IsPlaying();
}
float currentTime = 0f;
if (player.Control != null)
{
currentTime = (float)player.Control.GetCurrentTime();
}
float durationTime = 0f;
if (player.Info != null)
{
durationTime = (float)player.Info.GetDuration();
if (float.IsNaN(durationTime))
{
durationTime = 0f;
}
}
string timeUsed = Helper.GetTimeString(currentTime, true);
GUILayout.Label(timeUsed, GUILayout.ExpandWidth(false));
float newTime = GUILayout.HorizontalSlider(currentTime, 0f, durationTime, GUILayout.ExpandWidth(true));
if (newTime != currentTime && player.Control != null)
{
player.Control.Seek(newTime);
}
string timeTotal = "Infinity";
if (!float.IsInfinity(durationTime))
{
timeTotal = Helper.GetTimeString(durationTime, true);
}
GUILayout.Label(timeTotal, GUILayout.ExpandWidth(false));
EditorGUILayout.EndHorizontal();
// Buttons
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Rewind", GUILayout.ExpandWidth(false)))
{
if (player.Control != null)
{
player.Control.Rewind();
}
}
if (!isPlaying)
{
GUI.color = Color.green;
if (GUILayout.Button("Play", GUILayout.ExpandWidth(true)))
{
player.Play();
}
}
else
{
GUI.color = Color.yellow;
if (GUILayout.Button("Pause", GUILayout.ExpandWidth(true)))
{
player.Pause();
}
}
GUI.color = Color.white;
EditorGUILayout.EndHorizontal();
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c9328411ef862884f97a993c4daa9b68
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,123 @@
using UnityEditor;
using UnityEngine;
//-----------------------------------------------------------------------------
// Copyright 2015-2022 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo.Editor
{
/// <summary>
/// Editor for the ResolveToRenderTexture component
/// </summary>
[CanEditMultipleObjects]
[CustomEditor(typeof(ResolveToRenderTexture))]
public class ResolveToRenderTextureEditor : UnityEditor.Editor
{
private SerializedProperty _propMediaPlayer;
private SerializedProperty _propExternalTexture;
private SerializedProperty _propResolveFlags;
private SerializedProperty _propOptionsApplyHSBC;
private SerializedProperty _propOptionsHue;
private SerializedProperty _propOptionsSaturation;
private SerializedProperty _propOptionsBrightness;
private SerializedProperty _propOptionsContrast;
private SerializedProperty _propOptionsGamma;
private SerializedProperty _propOptionsTint;
private SerializedProperty _propOptionsAspectRatio;
void OnEnable()
{
_propMediaPlayer = this.CheckFindProperty("_mediaPlayer");
_propExternalTexture = this.CheckFindProperty("_externalTexture");
_propResolveFlags = this.CheckFindProperty("_resolveFlags");
_propOptionsApplyHSBC = this.CheckFindProperty("_options.applyHSBC");
_propOptionsHue = this.CheckFindProperty("_options.hue");
_propOptionsSaturation = this.CheckFindProperty("_options.saturation");
_propOptionsBrightness = this.CheckFindProperty("_options.brightness");
_propOptionsContrast = this.CheckFindProperty("_options.contrast");
_propOptionsGamma = this.CheckFindProperty("_options.gamma");
_propOptionsTint = this.CheckFindProperty("_options.tint");
_propOptionsAspectRatio = this.CheckFindProperty("_options.aspectRatio");
}
private void ButtonFloatReset(SerializedProperty prop, float value)
{
GUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(prop);
if (GUILayout.Button("Reset", GUILayout.ExpandWidth(false)))
{
prop.floatValue = value;
}
GUILayout.EndHorizontal();
}
private void ButtonColorReset(SerializedProperty prop, Color value)
{
GUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(prop);
if (GUILayout.Button("Reset", GUILayout.ExpandWidth(false)))
{
prop.colorValue = value;
}
GUILayout.EndHorizontal();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(_propMediaPlayer);
EditorGUILayout.PropertyField(_propExternalTexture);
_propResolveFlags.intValue = EditorGUILayout.MaskField("Resolve Flags", _propResolveFlags.intValue, System.Enum.GetNames(typeof( VideoRender.ResolveFlags)));
EditorGUI.BeginChangeCheck();
{
EditorGUILayout.PropertyField(_propOptionsApplyHSBC);
EditorGUI.BeginDisabledGroup(!_propOptionsApplyHSBC.boolValue);
{
EditorGUI.indentLevel++;
ButtonFloatReset(_propOptionsHue, 0f);
ButtonFloatReset(_propOptionsSaturation, 0.5f);
ButtonFloatReset(_propOptionsBrightness, 0.5f);
ButtonFloatReset(_propOptionsContrast, 0.5f);
ButtonFloatReset(_propOptionsGamma, 1f);
EditorGUI.indentLevel--;
}
EditorGUI.EndDisabledGroup();
ButtonColorReset(_propOptionsTint, Color.white);
}
if (EditorGUI.EndChangeCheck())
{
Object[] resolves = this.serializedObject.targetObjects;
if (resolves != null)
{
foreach (ResolveToRenderTexture resolve in resolves)
{
resolve.SetMaterialDirty();
}
}
}
EditorGUILayout.PropertyField(_propOptionsAspectRatio);
serializedObject.ApplyModifiedProperties();
{
ResolveToRenderTexture resolve = this.target as ResolveToRenderTexture;
if (resolve != null && resolve.TargetTexture != null)
{
Rect r = GUILayoutUtility.GetAspectRect(resolve.TargetTexture.width / (float)resolve.TargetTexture.height);
GUI.DrawTexture(r, resolve.TargetTexture, ScaleMode.StretchToFill, true);
if (GUILayout.Button("Select Texture"))
{
Selection.activeObject = resolve.TargetTexture;
}
Repaint();
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b8e6745d22bfa424b83014fd0ed7bd29
timeCreated: 1653302586
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: