Files
webRtc/Packages/com.unity.renderstreaming@3.1.0-exp.9/Editor/SignalingManagerEditor.cs
2026-04-28 16:48:04 +08:00

244 lines
11 KiB
C#

using System;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace Unity.RenderStreaming.Editor
{
/// <summary>
/// Render Streaming inspector.
/// </summary>
[CustomEditor(typeof(SignalingManager))]
internal class SignalingManagerEditor : UnityEditor.Editor
{
const string DefaultSignalingSettingsSavePath =
"Assets/SignalingSettings.asset";
const string DefaultSignalingSettingsLoadPath =
"Packages/com.unity.renderstreaming/Runtime/SignalingSettings.asset";
SerializedProperty m_UseDefault;
SerializedProperty m_SignalingSettingsObject;
SerializedProperty m_SignalingSettings;
SerializedProperty m_Handlers;
SerializedProperty m_RunOnAwake;
SerializedProperty m_EvaluateCommandlineArguments;
VisualElement root;
Button openProjectSettingsButton;
PopupField<SignalingSettingsObject> signalingSettingsPopupField;
PropertyField signalingSettingsField;
private void OnEnable()
{
EditorApplication.projectChanged += OnProjectChanged;
m_UseDefault = serializedObject.FindProperty(SignalingManager.UseDefaultPropertyName);
m_SignalingSettingsObject = serializedObject.FindProperty(SignalingManager.SignalingSettingsObjectPropertyName);
m_SignalingSettings = serializedObject.FindProperty(SignalingManager.SignalingSettingsPropertyName);
m_Handlers = serializedObject.FindProperty(SignalingManager.HandlersPropertyName);
m_RunOnAwake = serializedObject.FindProperty(SignalingManager.RunOnAwakePropertyName);
m_EvaluateCommandlineArguments = serializedObject.FindProperty(SignalingManager.EvaluateCommandlineArgumentsPropertyName);
}
private void OnDisable()
{
EditorApplication.projectChanged -= OnProjectChanged;
}
public override VisualElement CreateInspectorGUI()
{
root = new VisualElement();
bool useDefault = m_UseDefault.boolValue;
var useDefaultField = new PropertyField(m_UseDefault, "Use Default Settings in Project Settings");
useDefaultField.RegisterValueChangeCallback(OnChangeUseDefault);
openProjectSettingsButton = new Button { text = "Open Project Setings" };
openProjectSettingsButton.clicked += OnClickedOpenProjectSettingsButton;
signalingSettingsPopupField = CreatePopUpSignalingType(m_SignalingSettingsObject, "Signaling Settings Asset");
signalingSettingsPopupField.RegisterValueChangedCallback(OnValueChangeSignalingSettingsObject);
signalingSettingsField = new PropertyField(m_SignalingSettings, "Signaling Settings");
signalingSettingsField.RegisterValueChangeCallback(OnValueChangeSignalingSettings);
root.Add(useDefaultField);
root.Add(openProjectSettingsButton);
root.Add(signalingSettingsPopupField);
root.Add(signalingSettingsField);
if (useDefault)
{
signalingSettingsPopupField.style.display = DisplayStyle.None;
signalingSettingsField.style.display = DisplayStyle.None;
}
else
{
openProjectSettingsButton.style.display = DisplayStyle.None;
}
root.Add(new ReorderableListField(m_Handlers, "Signaling Handler List"));
root.Add(new PropertyField(m_RunOnAwake, "Run On Awake"));
root.Add(new PropertyField(m_EvaluateCommandlineArguments, "Evaluate Commandline Arguments"));
// Disable UI when running in Playmode
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
if (EditorApplication.isPlaying)
root.SetEnabled(false);
return root;
}
PopupField<SignalingSettingsObject> CreatePopUpSignalingType(SerializedProperty property, string label)
{
var asset = property.objectReferenceValue as SignalingSettingsObject;
var paths = GetAvailableSignalingSettingsPath();
var field = new PopupField<SignalingSettingsObject>(label: label);
field.tooltip = "Choose the signaling settings.";
field.formatSelectedValueCallback = v => AssetDatabase.GetAssetPath(v);
field.formatListItemCallback = v => AssetDatabase.GetAssetPath(v);
if (paths.Length == 0)
return field;
var availableObjects = paths.Select(path => AssetDatabase.LoadAssetAtPath<SignalingSettingsObject>(path)).ToArray();
var defaultIndex = ArrayHelpers.IndexOf(availableObjects, asset);
field.choices = availableObjects.ToList();
field.index = defaultIndex < 0 ? 0 : defaultIndex;
return field;
}
static string[] GetAvailableSignalingSettingsPath()
{
var guids = AssetDatabase.FindAssets("t:SignalingSettingsObject");
return guids.Select(AssetDatabase.GUIDToAssetPath).Where(_ => _.StartsWith("Assets")).ToArray();
}
static bool IsValidSignalingSettingsObject(SignalingSettingsObject asset)
{
if (asset == null)
return false;
if (AssetDatabase.GetAssetPath(asset).IndexOf("Assets", StringComparison.Ordinal) != 0)
return false;
return true;
}
void CreateDefaultSignalingSettings()
{
// Create Default SignalingSettings in Assets folder when the useDefault flag is turned off first time.
SignalingSettingsObject asset = AssetDatabase.LoadAssetAtPath<SignalingSettingsObject>(DefaultSignalingSettingsSavePath);
if (asset == null)
{
if (!AssetDatabase.CopyAsset(DefaultSignalingSettingsLoadPath, DefaultSignalingSettingsSavePath))
{
RenderStreaming.Logger.Log(LogType.Error, "CopyAssets is failed.");
return;
}
asset = AssetDatabase.LoadAssetAtPath<SignalingSettingsObject>(DefaultSignalingSettingsSavePath);
}
var handler = serializedObject.targetObject as SignalingManager;
handler.signalingSettingsObject = asset;
handler.SetSignalingSettings(handler.signalingSettingsObject.settings);
}
private void OnPlayModeStateChanged(PlayModeStateChange e)
{
switch (e)
{
case PlayModeStateChange.EnteredPlayMode:
root.SetEnabled(false);
break;
case PlayModeStateChange.ExitingPlayMode:
root.SetEnabled(true);
break;
}
}
private void OnProjectChanged()
{
if (root == null)
return;
var paths = GetAvailableSignalingSettingsPath();
// Force to use default settings if there are no available settings in project folder.
if (paths.Length == 0)
{
m_UseDefault.boolValue = true;
serializedObject.ApplyModifiedProperties();
return;
}
var asset = m_SignalingSettingsObject.objectReferenceValue;
var availableObjects = paths.Select(path => AssetDatabase.LoadAssetAtPath<SignalingSettingsObject>(path)).ToArray();
var defaultIndex = ArrayHelpers.IndexOf(availableObjects, asset);
if (defaultIndex < 0)
{
defaultIndex = 0;
using var e = ChangeEvent<SignalingSettingsObject>.GetPooled(null, availableObjects[defaultIndex]);
e.target = signalingSettingsPopupField;
root.SendEvent(e);
}
signalingSettingsPopupField.choices = availableObjects.ToList();
signalingSettingsPopupField.index = defaultIndex;
}
private void OnClickedOpenProjectSettingsButton()
{
SettingsService.OpenProjectSettings("Project/Render Streaming");
}
private void OnChangeUseDefault(SerializedPropertyChangeEvent e)
{
bool useDefault = e.changedProperty.boolValue;
if (useDefault)
{
signalingSettingsPopupField.style.display = DisplayStyle.None;
signalingSettingsField.style.display = DisplayStyle.None;
openProjectSettingsButton.style.display = DisplayStyle.Flex;
}
else
{
signalingSettingsPopupField.style.display = DisplayStyle.Flex;
signalingSettingsField.style.display = DisplayStyle.Flex;
openProjectSettingsButton.style.display = DisplayStyle.None;
if (!IsValidSignalingSettingsObject(m_SignalingSettingsObject.objectReferenceValue as SignalingSettingsObject))
{
CreateDefaultSignalingSettings();
}
}
}
private void OnValueChangeSignalingSettingsObject(ChangeEvent<SignalingSettingsObject> e)
{
var asset = e.newValue;
if (asset == null)
{
RenderStreaming.Logger.Log(LogType.Error, "Setting None is not allowed for this parameter. Reverted.");
return;
}
if (AssetDatabase.GetAssetPath(asset).IndexOf("Assets", StringComparison.Ordinal) != 0)
{
RenderStreaming.Logger.Log(LogType.Error, "Setting an asset not placed under Assets folder is not allowed for this parameter. Reverted.");
return;
}
m_SignalingSettingsObject.objectReferenceValue = asset;
serializedObject.ApplyModifiedProperties();
var handler = serializedObject.targetObject as SignalingManager;
handler.SetSignalingSettings(asset.settings);
// Send event to repaint SignalingSettingsDrawer.
using SerializedPropertyChangeEvent changeEvent = SerializedPropertyChangeEvent.GetPooled();
changeEvent.changedProperty = m_SignalingSettingsObject;
changeEvent.target = signalingSettingsField.Children().First();
root.SendEvent(changeEvent);
}
private void OnValueChangeSignalingSettings(SerializedPropertyChangeEvent e)
{
// Update SignalingSettings in ScriptableObject.
var handler = serializedObject.targetObject as SignalingManager;
if (handler.signalingSettingsObject != null)
handler.signalingSettingsObject.settings = handler.GetSignalingSettings();
}
}
}