您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
287 行
10 KiB
287 行
10 KiB
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using UnityEditorInternal;
|
|
using UnityEngine;
|
|
using UnityEngine.Perception.GroundTruth;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace UnityEditor.Perception.GroundTruth
|
|
{
|
|
[CustomEditor(typeof(PerceptionCamera))]
|
|
public class PerceptionCameraEditor : Editor
|
|
{
|
|
ReorderableList m_LabelersList;
|
|
|
|
public void OnEnable()
|
|
{
|
|
m_LabelersList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty(nameof(PerceptionCamera.labelers)), true, false, true, true);
|
|
m_LabelersList.drawHeaderCallback = (rect) => {
|
|
EditorGUI.LabelField(rect, "Camera Labelers", EditorStyles.largeLabel);
|
|
};
|
|
m_LabelersList.elementHeightCallback = GetElementHeight;
|
|
m_LabelersList.drawElementCallback = DrawElement;
|
|
m_LabelersList.onAddCallback += OnAdd;
|
|
m_LabelersList.onRemoveCallback += OnRemove;
|
|
}
|
|
|
|
float GetElementHeight(int index)
|
|
{
|
|
var serializedProperty = this.serializedObject.FindProperty(nameof(PerceptionCamera.labelers));
|
|
var element = serializedProperty.GetArrayElementAtIndex(index);
|
|
var editor = GetCameraLabelerDrawer(element, index);
|
|
return editor.GetElementHeight(element);
|
|
}
|
|
|
|
PerceptionCamera PerceptionCamera => ((PerceptionCamera)this.target);
|
|
|
|
void DrawElement(Rect rect, int index, bool isactive, bool isfocused)
|
|
{
|
|
var element = this.serializedObject.FindProperty(nameof(PerceptionCamera.labelers)).GetArrayElementAtIndex(index);
|
|
var editor = GetCameraLabelerDrawer(element, index);
|
|
editor.OnGUI(rect, element);
|
|
}
|
|
|
|
void OnRemove(ReorderableList list)
|
|
{
|
|
var labelers = serializedObject.FindProperty(nameof(PerceptionCamera.labelers));
|
|
labelers.DeleteArrayElementAtIndex(list.index);
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
void OnAdd(ReorderableList list)
|
|
{
|
|
Undo.RegisterCompleteObjectUndo(target, "Remove camera labeler");
|
|
var labelers = this.serializedObject.FindProperty(nameof(PerceptionCamera.labelers));
|
|
|
|
var dropdownOptions = TypeCache.GetTypesDerivedFrom<CameraLabeler>();
|
|
var menu = new GenericMenu();
|
|
foreach (var option in dropdownOptions)
|
|
{
|
|
var localOption = option;
|
|
menu.AddItem(new GUIContent(option.Name),
|
|
false,
|
|
() => AddLabeler(labelers, localOption));
|
|
}
|
|
menu.ShowAsContext();
|
|
}
|
|
|
|
void AddLabeler(SerializedProperty labelers, Type labelerType)
|
|
{
|
|
var insertIndex = labelers.arraySize;
|
|
labelers.InsertArrayElementAtIndex(insertIndex);
|
|
var element = labelers.GetArrayElementAtIndex(insertIndex);
|
|
var labeler = (CameraLabeler) Activator.CreateInstance(labelerType);
|
|
labeler.enabled = true;
|
|
element.managedReferenceValue = labeler;
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(PerceptionCamera.description)));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(PerceptionCamera.period)));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(PerceptionCamera.startTime)));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(PerceptionCamera.captureRgbImages)));
|
|
//EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(PerceptionCamera.labelers)));
|
|
m_LabelersList.DoLayoutList();
|
|
}
|
|
|
|
|
|
|
|
Dictionary<SerializedProperty, CameraLabelerDrawer> cameraLabelerDrawers = new Dictionary<SerializedProperty, CameraLabelerDrawer>();
|
|
CameraLabelerDrawer GetCameraLabelerDrawer(SerializedProperty element, int listIndex)
|
|
{
|
|
CameraLabelerDrawer drawer;
|
|
|
|
if (cameraLabelerDrawers.TryGetValue(element, out drawer))
|
|
return drawer;
|
|
|
|
var labeler = PerceptionCamera.labelers[listIndex];
|
|
|
|
foreach (var drawerType in TypeCache.GetTypesWithAttribute(typeof(CameraLabelerDrawerAttribute)))
|
|
{
|
|
var attr = drawerType.GetCustomAttributes(typeof(CameraLabelerDrawerAttribute), true)[0] as CameraLabelerDrawerAttribute;
|
|
if (attr.targetLabelerType == labeler.GetType())
|
|
{
|
|
drawer = Activator.CreateInstance(drawerType) as CameraLabelerDrawer;
|
|
drawer.CameraLabeler = labeler;
|
|
break;
|
|
}
|
|
if (attr.targetLabelerType.IsAssignableFrom(labeler.GetType()))
|
|
{
|
|
drawer = Activator.CreateInstance(drawerType) as CameraLabelerDrawer;
|
|
drawer.CameraLabeler = labeler;
|
|
}
|
|
}
|
|
|
|
cameraLabelerDrawers[element] = drawer;
|
|
|
|
return drawer;
|
|
}
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Class)]
|
|
class CameraLabelerDrawerAttribute : Attribute
|
|
{
|
|
public CameraLabelerDrawerAttribute(Type targetLabelerType)
|
|
{
|
|
this.targetLabelerType = targetLabelerType;
|
|
}
|
|
public Type targetLabelerType;
|
|
}
|
|
|
|
[CameraLabelerDrawer(typeof(CameraLabeler))]
|
|
public class CameraLabelerDrawer
|
|
{
|
|
public CameraLabeler CameraLabeler { get; internal set; }
|
|
|
|
class Styles
|
|
{
|
|
public static float defaultLineSpace = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
|
|
public static float reorderableListHandleIndentWidth = 12;
|
|
public static GUIContent enabled = new GUIContent("Enabled", "Enable or Disable the custom pass");
|
|
}
|
|
|
|
bool firstTime = true;
|
|
|
|
// Serialized Properties
|
|
SerializedProperty m_Enabled;
|
|
SerializedProperty m_LabelerFoldout;
|
|
List<SerializedProperty> m_CustomPassUserProperties = new List<SerializedProperty>();
|
|
|
|
void FetchProperties(SerializedProperty property)
|
|
{
|
|
m_Enabled = property.FindPropertyRelative(nameof(CameraLabeler.enabled));
|
|
m_LabelerFoldout = property.FindPropertyRelative(nameof(CameraLabeler.foldout));
|
|
}
|
|
|
|
void LoadUserProperties(SerializedProperty customPass)
|
|
{
|
|
foreach (var field in CameraLabeler.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
|
|
{
|
|
var serializeField = field.GetCustomAttribute<SerializeField>();
|
|
var hideInInspector = field.GetCustomAttribute<HideInInspector>();
|
|
var nonSerialized = field.GetCustomAttribute<NonSerializedAttribute>();
|
|
|
|
if (nonSerialized != null || hideInInspector != null)
|
|
continue;
|
|
|
|
if (!field.IsPublic && serializeField == null)
|
|
continue;
|
|
|
|
if (field.Name == nameof(CameraLabeler.enabled) || field.Name == nameof(CameraLabeler.foldout))
|
|
continue;
|
|
|
|
var prop = customPass.FindPropertyRelative(field.Name);
|
|
if (prop != null)
|
|
m_CustomPassUserProperties.Add(prop);
|
|
}
|
|
}
|
|
|
|
void InitInternal(SerializedProperty customPass)
|
|
{
|
|
FetchProperties(customPass);
|
|
Initialize(customPass);
|
|
LoadUserProperties(customPass);
|
|
firstTime = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use this function to initialize the local SerializedProperty you will use in your pass.
|
|
/// </summary>
|
|
/// <param name="customPass">Your custom pass instance represented as a SerializedProperty</param>
|
|
protected virtual void Initialize(SerializedProperty customPass) {}
|
|
|
|
internal void OnGUI(Rect rect, SerializedProperty property)
|
|
{
|
|
rect.height = EditorGUIUtility.singleLineHeight;
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
if (firstTime)
|
|
InitInternal(property);
|
|
|
|
DoHeaderGUI(ref rect);
|
|
|
|
if (m_LabelerFoldout.boolValue)
|
|
{
|
|
EditorGUI.EndChangeCheck();
|
|
return;
|
|
}
|
|
|
|
EditorGUI.BeginDisabledGroup(!m_Enabled.boolValue);
|
|
{
|
|
DoPassGUI(property, rect);
|
|
}
|
|
EditorGUI.EndDisabledGroup();
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
property.serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implement this function to draw your custom GUI.
|
|
/// </summary>
|
|
/// <param name="customPass">Your custom pass instance represented as a SerializedProperty</param>
|
|
/// <param name="rect">space available for you to draw the UI</param>
|
|
protected virtual void DoPassGUI(SerializedProperty customPass, Rect rect)
|
|
{
|
|
foreach (var prop in m_CustomPassUserProperties)
|
|
{
|
|
EditorGUI.PropertyField(rect, prop);
|
|
rect.y += Styles.defaultLineSpace;
|
|
}
|
|
}
|
|
|
|
void DoHeaderGUI(ref Rect rect)
|
|
{
|
|
var enabledSize = EditorStyles.boldLabel.CalcSize(Styles.enabled) + new Vector2(Styles.reorderableListHandleIndentWidth, 0);
|
|
var headerRect = new Rect(rect.x + Styles.reorderableListHandleIndentWidth,
|
|
rect.y + EditorGUIUtility.standardVerticalSpacing,
|
|
rect.width - Styles.reorderableListHandleIndentWidth - enabledSize.x,
|
|
EditorGUIUtility.singleLineHeight);
|
|
rect.y += Styles.defaultLineSpace;
|
|
var enabledRect = headerRect;
|
|
enabledRect.x = rect.xMax - enabledSize.x;
|
|
enabledRect.width = enabledSize.x;
|
|
|
|
m_LabelerFoldout.boolValue = EditorGUI.Foldout(headerRect, m_LabelerFoldout.boolValue, $"{CameraLabeler.GetType().Name}", true, EditorStyles.boldLabel);
|
|
EditorGUIUtility.labelWidth = enabledRect.width - 14;
|
|
m_Enabled.boolValue = EditorGUI.Toggle(enabledRect, Styles.enabled, m_Enabled.boolValue);
|
|
EditorGUIUtility.labelWidth = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implement this functions if you implement DoPassGUI. The result of this function must match the number of lines displayed in your custom GUI.
|
|
/// Note that this height can be dynamic.
|
|
/// </summary>
|
|
/// <param name="customPass">Your custom pass instance represented as a SerializedProperty</param>
|
|
/// <returns>The height in pixels of tour custom pass GUI</returns>
|
|
protected virtual float GetHeight(SerializedProperty customPass)
|
|
{
|
|
float height = 0;
|
|
|
|
foreach (var prop in m_CustomPassUserProperties)
|
|
{
|
|
height += EditorGUI.GetPropertyHeight(prop);
|
|
height += EditorGUIUtility.standardVerticalSpacing;
|
|
}
|
|
|
|
return height;
|
|
}
|
|
|
|
internal float GetElementHeight(SerializedProperty property)
|
|
{
|
|
float height = Styles.defaultLineSpace;
|
|
|
|
if (firstTime)
|
|
InitInternal(property);
|
|
|
|
if (m_LabelerFoldout.boolValue)
|
|
return height;
|
|
|
|
return height + GetHeight(property);
|
|
}
|
|
}
|
|
}
|