您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
153 行
6.3 KiB
153 行
6.3 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
using UnityEditor.Perception.Randomization;
|
|
using UnityEditor.UIElements;
|
|
using UnityEngine;
|
|
using UnityEngine.Perception.Randomization;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace Editor.Randomization.VisualElements.AssetSource
|
|
{
|
|
class AssetSourceElement : VisualElement
|
|
{
|
|
SerializedProperty m_AssetRoleProperty;
|
|
SerializedProperty m_LocationProperty;
|
|
ToolbarMenu m_AssetRoleToolbarMenu;
|
|
ToolbarMenu m_LocationToolbarMenu;
|
|
VisualElement m_FieldsContainer;
|
|
TextElement m_LocationNotes;
|
|
Type m_AssetType;
|
|
Dictionary<string, Type> m_AssetRoleLabelsToTypes = new Dictionary<string, Type>();
|
|
|
|
IAssetRoleBase assetRole =>
|
|
(IAssetRoleBase)StaticData.GetManagedReferenceValue(m_AssetRoleProperty);
|
|
AssetSourceLocation assetSourceLocation =>
|
|
(AssetSourceLocation)StaticData.GetManagedReferenceValue(m_LocationProperty);
|
|
|
|
public AssetSourceElement(SerializedProperty property, FieldInfo fieldInfo)
|
|
{
|
|
m_AssetType = fieldInfo.FieldType.GetGenericArguments()[0];
|
|
m_AssetRoleProperty = property.FindPropertyRelative("m_AssetRoleBase");
|
|
m_LocationProperty = property.FindPropertyRelative(nameof(AssetSource<GameObject>.assetSourceLocation));
|
|
var template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
|
|
$"{StaticData.uxmlDir}/AssetSource/AssetSourceElement.uxml");
|
|
template.CloneTree(this);
|
|
|
|
var nameLabel = this.Q<Label>("name");
|
|
nameLabel.text = property.displayName;
|
|
|
|
m_FieldsContainer = this.Q<VisualElement>("fields-container");
|
|
|
|
m_AssetRoleToolbarMenu = this.Q<ToolbarMenu>("asset-role-dropdown");
|
|
var storedAssetRole = assetRole;
|
|
m_AssetRoleToolbarMenu.text = storedAssetRole != null
|
|
? GetAssetRoleDisplayName(assetRole.GetType()) : "None";
|
|
|
|
// ReSharper disable once PossibleNullReferenceException
|
|
var baseType = fieldInfo.FieldType.GetProperty("assetRole").PropertyType;
|
|
m_AssetRoleToolbarMenu.menu.AppendAction(
|
|
"None",
|
|
a => ReplaceAssetRole(null),
|
|
a => DropdownMenuAction.Status.Normal);
|
|
m_AssetRoleLabelsToTypes.Clear();
|
|
foreach (var type in StaticData.assetRoleTypes)
|
|
{
|
|
if (!type.IsSubclassOf(baseType))
|
|
continue;
|
|
var label = GetAssetRoleDisplayName(type);
|
|
|
|
if (m_AssetRoleLabelsToTypes.ContainsKey(label))
|
|
Debug.LogError($"The asset role classes {type.Name} && {m_AssetRoleLabelsToTypes[label].Name} have an identical label: \"{label}\". Asset role labels should be unique.");
|
|
else
|
|
m_AssetRoleLabelsToTypes.Add(label, type);
|
|
|
|
m_AssetRoleToolbarMenu.menu.AppendAction(
|
|
label,
|
|
a => ReplaceAssetRole(type),
|
|
a => DropdownMenuAction.Status.Normal);
|
|
}
|
|
|
|
m_LocationNotes = this.Q<TextElement>("location-notes");
|
|
m_LocationToolbarMenu = this.Q<ToolbarMenu>("location-dropdown");
|
|
foreach (var type in StaticData.assetSourceLocationTypes)
|
|
{
|
|
m_LocationToolbarMenu.menu.AppendAction(
|
|
GetDisplayName(type),
|
|
a => ReplaceLocation(type),
|
|
a => DropdownMenuAction.Status.Normal);
|
|
}
|
|
if (assetSourceLocation == null)
|
|
CreateAssetSourceLocation(typeof(LocalAssetSourceLocation));
|
|
UpdateLocationUI(assetSourceLocation.GetType());
|
|
}
|
|
|
|
void ReplaceAssetRole(Type type)
|
|
{
|
|
if (type == null)
|
|
{
|
|
m_AssetRoleToolbarMenu.text = "None";
|
|
m_AssetRoleProperty.managedReferenceValue = null;
|
|
}
|
|
else
|
|
{
|
|
m_AssetRoleToolbarMenu.text = GetAssetRoleDisplayName(type);
|
|
var newAssetRole = (IAssetRoleBase)Activator.CreateInstance(type);
|
|
m_AssetRoleProperty.managedReferenceValue = newAssetRole;
|
|
}
|
|
m_AssetRoleProperty.serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
void CreateAssetSourceLocation(Type type)
|
|
{
|
|
var newLocation = (AssetSourceLocation)Activator.CreateInstance(type);
|
|
m_LocationProperty.managedReferenceValue = newLocation;
|
|
m_LocationProperty.serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
void ReplaceLocation(Type type)
|
|
{
|
|
CreateAssetSourceLocation(type);
|
|
UpdateLocationUI(type);
|
|
}
|
|
|
|
void UpdateLocationUI(Type type)
|
|
{
|
|
m_LocationToolbarMenu.text = GetDisplayName(type);
|
|
var notesAttribute = (AssetSourceEditorDescriptionAttribute)Attribute.GetCustomAttribute(type, typeof(AssetSourceEditorDescriptionAttribute));
|
|
if (notesAttribute != null)
|
|
{
|
|
m_LocationNotes.text = notesAttribute.notes;
|
|
m_LocationNotes.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.Flex);
|
|
}
|
|
else
|
|
{
|
|
m_LocationNotes.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.None);
|
|
}
|
|
CreatePropertyFields();
|
|
}
|
|
|
|
void CreatePropertyFields()
|
|
{
|
|
m_FieldsContainer.Clear();
|
|
if (m_LocationProperty.type == $"managedReference<{nameof(LocalAssetSourceLocation)}>")
|
|
m_FieldsContainer.Add(
|
|
new AssetListElement(m_LocationProperty.FindPropertyRelative("assets"), m_AssetType));
|
|
else
|
|
UIElementsEditorUtilities.CreatePropertyFields(m_LocationProperty, m_FieldsContainer);
|
|
}
|
|
|
|
static string GetDisplayName(Type type)
|
|
{
|
|
var attribute = (DisplayNameAttribute)Attribute.GetCustomAttribute(type, typeof(DisplayNameAttribute));
|
|
return attribute != null ? attribute.DisplayName : type.Name;
|
|
}
|
|
|
|
static string GetAssetRoleDisplayName(Type type)
|
|
{
|
|
return $"{((IAssetRoleBase)Activator.CreateInstance(type)).label} ({type.Name})";
|
|
}
|
|
}
|
|
}
|