Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
Tweaked video player handler inspector
  • Loading branch information
JLChnToZ committed Apr 6, 2024
1 parent cb39d45 commit a333cc2
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 91 deletions.
81 changes: 81 additions & 0 deletions Packages/idv.jlchntoz.vvmw/Editor/Common/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Rendering;
using UnityEditor;

namespace JLChnToZ.VRC.VVMW {
public static class Utils {
static GUIContent tempContent;
static GUIStyle textFieldDropDownTextStyle, textFieldDropDownStyle;

public static IEnumerable<T> IterateAllComponents<T>(this Scene scene, bool includeEditorOnly = false) where T : Component {
var pending = new Stack<Transform>();
Expand Down Expand Up @@ -74,6 +76,85 @@ public static GUIContent GetTempContent(string text = "", string tooltip = "", T
return tempContent;
}

public static void DrawShaderPropertiesField(
SerializedProperty property,
GUIContent label,
Shader selectedShader,
Material[] materials,
ShaderUtil.ShaderPropertyType type
) {
if (textFieldDropDownTextStyle == null) textFieldDropDownTextStyle = GUI.skin.FindStyle("TextFieldDropDownText");
if (textFieldDropDownStyle == null) textFieldDropDownStyle = GUI.skin.FindStyle("TextFieldDropDown");
var controlRect = EditorGUILayout.GetControlRect(true);
using (new EditorGUI.PropertyScope(controlRect, label, property)) {
controlRect = EditorGUI.PrefixLabel(controlRect, label);
var size = textFieldDropDownStyle.CalcSize(GUIContent.none);
var textRect = controlRect;
textRect.xMin -= EditorGUI.indentLevel * 15F;
textRect.xMax -= size.x;
property.stringValue = EditorGUI.TextField(textRect, property.stringValue, textFieldDropDownTextStyle);
var buttonRect = controlRect;
buttonRect.xMin = buttonRect.xMax - size.x;
buttonRect.size = size;
using (new EditorGUI.DisabledScope(selectedShader == null && (materials == null || materials.Length == 0))) {
if (EditorGUI.DropdownButton(buttonRect, GUIContent.none, FocusType.Passive, textFieldDropDownStyle)) {
var menu = new GenericMenu();
if (selectedShader != null)
AppendShaderPropertiesToMenu(menu, selectedShader, property, type);
else {
var shaderSet = new HashSet<Shader>();
for (int j = 0; j < materials.Length; j++) {
var material = materials[j];
if (material == null) continue;
shaderSet.Add(material.shader);
}
foreach (var shader in shaderSet) {
if (menu.GetItemCount() > 0) menu.AddSeparator("");
AppendShaderPropertiesToMenu(menu, shader, property, type);
}
}
menu.DropDown(controlRect);
}
}
}
}

static void AppendShaderPropertiesToMenu(
GenericMenu menu,
Shader shader,
SerializedProperty property,
ShaderUtil.ShaderPropertyType type
) {
int count = ShaderUtil.GetPropertyCount(shader);
for (int j = 0; j < count; j++) {
if (ShaderUtil.GetPropertyType(shader, j) != type) continue;
var propertyName = ShaderUtil.GetPropertyName(shader, j);
menu.AddItem(
new GUIContent($"{ShaderUtil.GetPropertyDescription(shader, j)} ({propertyName})".Replace('/', '.')),
property.stringValue == propertyName, SetValue, (property, propertyName)
);
}
}

static void SetValue(object entry) {
(SerializedProperty prop, string value) = ((SerializedProperty, string))entry;
prop.stringValue = value;
prop.serializedObject.ApplyModifiedProperties();
}

public static string FindMainTexturePropertyName(Material material) {
if (material != null) {
var shader = material.shader;
if (shader == null) return "";
int count = shader.GetPropertyCount();
for (int i = 0; i < count; i++)
if (shader.GetPropertyType(i) == ShaderPropertyType.Texture &&
shader.GetPropertyFlags(i).HasFlag(ShaderPropertyFlags.MainTexture))
return shader.GetPropertyName(i);
}
return "_MainTex";
}

#if !NETSTANDARD2_1
// Polyfill for old .NET Framework
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
76 changes: 4 additions & 72 deletions Packages/idv.jlchntoz.vvmw/Editor/VVMW/CoreEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public class CoreEditor : VVMWEditorBase {
static readonly Dictionary<Type, FieldInfo> controllableTypes = new Dictionary<Type, FieldInfo>();
readonly Dictionary<Core, UdonSharpBehaviour> autoPlayControllers = new Dictionary<Core, UdonSharpBehaviour>();
static readonly string[] materialModeOptions = new [] { "Property Block", "Shared Material", "Cloned Materal" };
static GUIStyle textFieldDropDownTextStyle, textFieldDropDownStyle;
SerializedProperty trustedUrlDomainsProperty;
SerializedProperty playerHandlersProperty;
SerializedProperty audioSourcesProperty;
Expand Down Expand Up @@ -356,13 +355,13 @@ void DrawScreenList() {
if (showMaterialOptions) {
var nameProperty = screenTargetPropertyNamesProperty.GetArrayElementAtIndex(i);
var avProProperty = avProPropertyNamesProperty.GetArrayElementAtIndex(i);
DrawShaderPropertiesField(
Utils.DrawShaderPropertiesField(
nameProperty, Utils.GetTempContent("Video Texture Property Name", "The name of the property in material to set the video texture."),
selectedShader, materials, ShaderUtil.ShaderPropertyType.TexEnv
);
using (var changed = new EditorGUI.ChangeCheckScope()) {
useST = EditorGUILayout.Toggle(Utils.GetTempContent("Use Scale Offset", "Will use scale offset (_Texture_ST) to adjust the texture if it is flipped upside-down."), useST);
if (!useST) DrawShaderPropertiesField(
if (!useST) Utils.DrawShaderPropertiesField(
avProProperty, Utils.GetTempContent("AVPro Flag Property Name", "If it is using AVPro player, this property value will set to 1, otherwise 0."),
selectedShader, materials, ShaderUtil.ShaderPropertyType.Float
);
Expand Down Expand Up @@ -398,43 +397,6 @@ void DrawScreenList() {
EditorGUILayout.Space();
}

static void DrawShaderPropertiesField(SerializedProperty property, GUIContent label, Shader selectedShader, Material[] materials, ShaderUtil.ShaderPropertyType type) {
if (textFieldDropDownTextStyle == null) textFieldDropDownTextStyle = GUI.skin.FindStyle("TextFieldDropDownText");
if (textFieldDropDownStyle == null) textFieldDropDownStyle = GUI.skin.FindStyle("TextFieldDropDown");
var controlRect = EditorGUILayout.GetControlRect(true);
using (new EditorGUI.PropertyScope(controlRect, label, property)) {
controlRect = EditorGUI.PrefixLabel(controlRect, label);
var size = textFieldDropDownStyle.CalcSize(GUIContent.none);
var textRect = controlRect;
textRect.xMin -= EditorGUI.indentLevel * 15F;
textRect.xMax -= size.x;
property.stringValue = EditorGUI.TextField(textRect, property.stringValue, textFieldDropDownTextStyle);
var buttonRect = controlRect;
buttonRect.xMin = buttonRect.xMax - size.x;
buttonRect.size = size;
using (new EditorGUI.DisabledScope(selectedShader == null && (materials == null || materials.Length == 0))) {
if (EditorGUI.DropdownButton(buttonRect, GUIContent.none, FocusType.Passive, textFieldDropDownStyle)) {
var menu = new GenericMenu();
if (selectedShader != null)
AppendShaderPropertiesToMenu(menu, selectedShader, property, type);
else {
var shaderSet = new HashSet<Shader>();
for (int j = 0; j < materials.Length; j++) {
var material = materials[j];
if (material == null) continue;
shaderSet.Add(material.shader);
}
foreach (var shader in shaderSet) {
if (menu.GetItemCount() > 0) menu.AddSeparator("");
AppendShaderPropertiesToMenu(menu, shader, property, type);
}
}
menu.DropDown(controlRect);
}
}
}
}

public static bool AddTarget(Core core, UnityObject newTarget, bool recordUndo = true, bool copyToUdon = false) {
using (var so = new SerializedObject(core)) {
if (newTarget is AudioSource)
Expand Down Expand Up @@ -472,14 +434,14 @@ SerializedProperty avProPropertyNamesProperty
if (newTarget is CustomRenderTexture crt)
newTarget = crt.material;
if (newTarget is Material material) {
mainTexturePropertyName = FindMainTexturePropertyName(material);
mainTexturePropertyName = Utils.FindMainTexturePropertyName(material);
avProPropertyName = FindAVProPropertyName(material);
screenTargetMode = avProPropertyName == null ? 8 : 0;
defaultTexture = material.GetTexture(mainTexturePropertyName);
} else if (newTarget is Renderer renderer || (newTarget is GameObject rendererGO && rendererGO.TryGetComponent(out renderer))) {
newTarget = renderer;
material = renderer.sharedMaterial;
mainTexturePropertyName = FindMainTexturePropertyName(material);
mainTexturePropertyName = Utils.FindMainTexturePropertyName(material);
avProPropertyName = FindAVProPropertyName(material);
screenTargetMode = avProPropertyName == null ? 9 : 1;
defaultTexture = material != null ? material.GetTexture(mainTexturePropertyName) : null;
Expand All @@ -497,36 +459,6 @@ SerializedProperty avProPropertyNamesProperty
return true;
}

static void SetValue(object entry) {
(SerializedProperty prop, string value) = ((SerializedProperty, string))entry;
prop.stringValue = value;
prop.serializedObject.ApplyModifiedProperties();
}

static void AppendShaderPropertiesToMenu(GenericMenu menu, Shader shader, SerializedProperty property, ShaderUtil.ShaderPropertyType type) {
int count = ShaderUtil.GetPropertyCount(shader);
for (int j = 0; j < count; j++) {
if (ShaderUtil.GetPropertyType(shader, j) != type) continue;
var propertyName = ShaderUtil.GetPropertyName(shader, j);
menu.AddItem(
new GUIContent($"{ShaderUtil.GetPropertyDescription(shader, j)} ({propertyName})".Replace('/', '.')),
property.stringValue == propertyName, SetValue, (property, propertyName)
);
}
}

static string FindMainTexturePropertyName(Material material) {
if (material != null) {
var shader = material.shader;
if (shader == null) return "";
int count = shader.GetPropertyCount();
for (int i = 0; i < count; i++)
if (shader.GetPropertyType(i) == ShaderPropertyType.Texture && shader.GetPropertyFlags(i).HasFlag(ShaderPropertyFlags.MainTexture))
return shader.GetPropertyName(i);
}
return "_MainTex";
}

static string FindAVProPropertyName(Material material) {
if (material == null) return null;
var shader = material.shader;
Expand Down
31 changes: 28 additions & 3 deletions Packages/idv.jlchntoz.vvmw/Editor/VVMW/VideoPlayerHandlerEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ namespace JLChnToZ.VRC.VVMW.Editors {
[CustomEditor(typeof(VideoPlayerHandler))]
public class VideoPlayerHandlerEditor : VVMWEditorBase {

SerializedProperty texturePropertyNameProperty, useSharedMaterialProperty, isAvProProperty, playerNameProperty, primaryAudioSourceProperty, useFlickerWorkaroundProperty, blitMaterialProperty;
SerializedProperty texturePropertyNameProperty,
useSharedMaterialProperty,
isAvProProperty,
playerNameProperty,
primaryAudioSourceProperty,
useFlickerWorkaroundProperty,
blitMaterialProperty;
Material[] materials;

protected override void OnEnable() {
base.OnEnable();
Expand All @@ -20,6 +27,7 @@ protected override void OnEnable() {
primaryAudioSourceProperty = serializedObject.FindProperty("primaryAudioSource");
useFlickerWorkaroundProperty = serializedObject.FindProperty("useFlickerWorkaround");
blitMaterialProperty = serializedObject.FindProperty("blitMaterial");
materials = null;
}

public override void OnInspectorGUI() {
Expand All @@ -44,10 +52,27 @@ public override void OnInspectorGUI() {
HideControlledComponent(renderer);
using (var so = new SerializedObject(renderer)) {
so.FindProperty("m_Enabled").boolValue = false;
EditorGUILayout.PropertyField(so.FindProperty("m_Materials"), true);
var materialsProperty = so.FindProperty("m_Materials");
bool isChanged = false;
using (var changed = new EditorGUI.ChangeCheckScope()) {
EditorGUILayout.PropertyField(materialsProperty, true);
isChanged = changed.changed;
}
if (materials == null || materials.Length != materialsProperty.arraySize) {
materials = new Material[materialsProperty.arraySize];
isChanged = true;
}
if (isChanged)
for (int i = 0; i < materials.Length; i++)
materials[i] = materialsProperty.GetArrayElementAtIndex(i).objectReferenceValue as Material;
so.ApplyModifiedProperties();
}
EditorGUILayout.PropertyField(texturePropertyNameProperty);
Utils.DrawShaderPropertiesField(
texturePropertyNameProperty,
Utils.GetTempContent(texturePropertyNameProperty.displayName, texturePropertyNameProperty.tooltip),
null, materials,
ShaderUtil.ShaderPropertyType.TexEnv
);
var meshFilter = target.GetComponent<MeshFilter>();
HideControlledComponent(meshFilter);
EditorGUILayout.Space();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ MonoBehaviour:
Data:
- Name: $k
Entry: 1
Data: rtspVaildProtocols
Data: realTimeProtocols
- Name: $v
Entry: 7
Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: rtspVaildProtocols
Data: realTimeProtocols
- Name: <UserType>k__BackingField
Entry: 7
Data: 3|System.RuntimeType, mscorlib
Expand Down Expand Up @@ -1216,13 +1216,13 @@ MonoBehaviour:
Data:
- Name: $k
Entry: 1
Data: isRTSP
Data: isRealTimeProtocol
- Name: $v
Entry: 7
Data: 68|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: isRTSP
Data: isRealTimeProtocol
- Name: <UserType>k__BackingField
Entry: 9
Data: 18
Expand Down
28 changes: 16 additions & 12 deletions Packages/idv.jlchntoz.vvmw/Runtime/VVMW/VideoPlayerHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace JLChnToZ.VRC.VVMW {
[DefaultExecutionOrder(0)]
[HelpURL("https://github.com/JLChnToZ/VVMW/blob/main/Packages/idv.jlchntoz.vvmw/README.md#builtin-module--avpro-module")]
public class VideoPlayerHandler : UdonSharpBehaviour {
string[] rtspVaildProtocols = new string[] { "rtsp", "rtmp", "rtspt", "rtspu", "rtmps", "rtsps" };
string[] realTimeProtocols = new string[] { "rtsp", "rtmp", "rtspt", "rtspu", "rtmps", "rtsps" };
[NonSerialized] public Core core;
[Tooltip("The name of current video player. Can be the key mapped in language pack JSON.")]
public string playerName = "";
Expand All @@ -37,7 +37,7 @@ public class VideoPlayerHandler : UdonSharpBehaviour {
MaterialPropertyBlock propertyBlock;
int texturePropertyID;
VRCUrl lastUrl;
bool isRTSP;
bool isRealTimeProtocol;
bool afterFirstRun;

public bool IsActive {
Expand All @@ -59,7 +59,7 @@ public float Time {

public bool IsAvPro => isAvPro && bufferedTexture == null;

public float Duration => isRTSP ? float.PositiveInfinity : videoPlayer.GetDuration();
public float Duration => isRealTimeProtocol ? float.PositiveInfinity : videoPlayer.GetDuration();

public Texture Texture => texture != null && bufferedTexture != null ? bufferedTexture : texture;

Expand Down Expand Up @@ -154,7 +154,7 @@ public void LoadUrl(VRCUrl url, bool reload) {
ClearTexture();
}
lastUrl = url;
isRTSP = IsRTSP(url);
isRealTimeProtocol = IsRealTimeProtocol(url);
isPaused = false;
}

Expand All @@ -173,8 +173,8 @@ public void Pause() {
public void Stop() {
if (!isActive) return;
videoPlayer.Stop();
if (isRTSP) {
isRTSP = false;
if (isRealTimeProtocol) {
isRealTimeProtocol = false;
lastUrl = VRCUrl.Empty;
}
OnVideoEnd();
Expand Down Expand Up @@ -219,10 +219,14 @@ public override void OnVideoPause() {
}

public override void OnVideoEnd() {
if (isRTSP) return; // Don't do anything if it's RTSP
// For AVPro players, even it fires OnVideoEnd event,
// its IsPlaying flag doesn't change to false,
// so we have to stop it manually.
// Here are quirky behaviors of AVPro video player for firing OnVideoEnd event:
// 1. If it's real-time protocol,
// it doesn't mean the stream is ended,
// so we have to ignore this event.
if (isRealTimeProtocol) return;
// 2. For video has measurable duration,
// its IsPlaying flag doesn't change to false even it reaches the end,
// so we have to stop it manually.
if (videoPlayer.IsPlaying) videoPlayer.Stop();
isPaused = false;
if (!isActive) return;
Expand All @@ -236,14 +240,14 @@ public override void OnVideoLoop() {
core.OnVideoLoop();
}

bool IsRTSP(VRCUrl url) {
bool IsRealTimeProtocol(VRCUrl url) {
if (!Utilities.IsValid(url)) return false;
var urlStr = url.Get();
if (string.IsNullOrEmpty(urlStr) || urlStr.Length < 7) return false;
int index = urlStr.IndexOf("://");
if (index < 0 || index > 5) return false;
var protocol = urlStr.Substring(0, index).ToLower();
return Array.IndexOf(rtspVaildProtocols, protocol) >= 0;
return Array.IndexOf(realTimeProtocols, protocol) >= 0;
}

void ClearTexture() {
Expand Down

0 comments on commit a333cc2

Please sign in to comment.