浏览代码
Merge pull request #308 from Unity-Technologies/generic-asset-sources
Merge pull request #308 from Unity-Technologies/generic-asset-sources
Generic Asset Sources/main
GitHub
3 年前
当前提交
13eeb0a2
共有 61 个文件被更改,包括 1339 次插入 和 157 次删除
-
4com.unity.perception/CHANGELOG.md
-
13com.unity.perception/Editor/Randomization/Utilities/UIElementsEditorUtilities.cs
-
5com.unity.perception/Editor/Randomization/Utilities/StaticData.cs
-
2com.unity.perception/Editor/Randomization/Uxml/Sampler/SamplerInterfaceElement.uxml
-
7com.unity.perception/Editor/Randomization/Uxml/ScenarioBaseElement.uxml
-
8com.unity.perception/Editor/Randomization/Uxml/RunInUnitySimulationWindow.uxml
-
16com.unity.perception/Editor/Randomization/VisualElements/Parameter/ParameterElement.cs
-
15com.unity.perception/Editor/Randomization/VisualElements/Sampler/SamplerInterfaceElement.cs
-
2com.unity.perception/Editor/Randomization/VisualElements/Basic/UIntField.cs
-
2com.unity.perception/Editor/Randomization/VisualElements/Basic/UxmlUIntAttributeDescription.cs
-
188com.unity.perception/Editor/Randomization/Editors/RunInUnitySimulationWindow.cs
-
14com.unity.perception/Editor/Randomization/Editors/ScenarioBaseEditor.cs
-
6com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs
-
51com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs
-
1com.unity.perception/Runtime/Randomization/Scenarios/Serialization/ScenarioSerializer.cs
-
117com.unity.perception/Runtime/Randomization/Scenarios/ScenarioBase.cs
-
18com.unity.perception/Runtime/Randomization/Scenarios/UnitySimulationScenario.cs
-
109com.unity.perception/Runtime/Randomization/Randomizers/RandomizerExamples/Utilities/GameObjectOneWayCache.cs
-
2com.unity.perception/Tests/Runtime/GroundTruthTests/VisualizationTests.cs
-
4com.unity.perception/Tests/Runtime/Randomization/ScenarioTests/ScenarioTests.cs
-
8com.unity.perception/Editor/Pyrception.meta
-
11com.unity.perception/Editor/Randomization/PropertyDrawers/AssetSourceDrawer.cs.meta
-
26com.unity.perception/Editor/Randomization/PropertyDrawers/AssetSourceDrawer.cs
-
22com.unity.perception/Editor/Randomization/Utilities/AssetLoadingUtilities.cs
-
11com.unity.perception/Editor/Randomization/Utilities/AssetLoadingUtilities.cs.meta
-
8com.unity.perception/Editor/Randomization/Uxml/AssetSource.meta
-
8com.unity.perception/Editor/Randomization/VisualElements/AssetSource.meta
-
8com.unity.perception/Runtime/Randomization/Randomizers/AssetSources.meta
-
8com.unity.perception/Tests/Runtime/Randomization/AssetSourceTests.meta
-
8com.unity.perception/Editor/Pyrception/pyrception-utils.meta
-
10com.unity.perception/Editor/Randomization/Uxml/AssetSource/AssetListElement.uxml
-
10com.unity.perception/Editor/Randomization/Uxml/AssetSource/AssetListElement.uxml.meta
-
7com.unity.perception/Editor/Randomization/Uxml/AssetSource/AssetListItemElement.uxml
-
10com.unity.perception/Editor/Randomization/Uxml/AssetSource/AssetListItemElement.uxml.meta
-
10com.unity.perception/Editor/Randomization/Uxml/AssetSource/AssetSourceElement.uxml.meta
-
26com.unity.perception/Editor/Randomization/Uxml/AssetSource/AssetSourceElement.uxml
-
11com.unity.perception/Editor/Randomization/VisualElements/AssetSource/AssetListElement.cs.meta
-
39com.unity.perception/Editor/Randomization/VisualElements/AssetSource/AssetListItemElement.cs
-
11com.unity.perception/Editor/Randomization/VisualElements/AssetSource/AssetListItemElement.cs.meta
-
11com.unity.perception/Editor/Randomization/VisualElements/AssetSource/AssetSourceElement.cs.meta
-
93com.unity.perception/Editor/Randomization/VisualElements/AssetSource/AssetListElement.cs
-
153com.unity.perception/Editor/Randomization/VisualElements/AssetSource/AssetSourceElement.cs
-
3com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/AssetSource.cs.meta
-
35com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/AssetSourceLocation.cs
-
3com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/AssetSourceLocation.cs.meta
-
3com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/LocalAssetSourceLocation.cs.meta
-
22com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/AssetRole.cs
-
11com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/AssetRole.cs.meta
-
152com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/AssetSource.cs
-
34com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/LocalAssetSourceLocation.cs
-
24com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/AssetSourceEditorDescriptionAttribute.cs
-
11com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/AssetSourceEditorDescriptionAttribute.cs.meta
-
11com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/IAssetRoleBase.cs.meta
-
20com.unity.perception/Runtime/Randomization/Randomizers/AssetSources/IAssetRoleBase.cs
-
11com.unity.perception/Tests/Runtime/Randomization/AssetSourceTests/LocalAssetSourceTests.cs.meta
-
63com.unity.perception/Tests/Runtime/Randomization/AssetSourceTests/LocalAssetSourceTests.cs
|
|||
fileFormatVersion: 2 |
|||
guid: 5000b0088702b4f589e73939e27aa132 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 5be7d531a18f32b4f93a73b173259337 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Editor.Randomization.VisualElements.AssetSource; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.Randomization; |
|||
using UnityEngine.UIElements; |
|||
|
|||
namespace UnityEditor.Perception.Randomization.PropertyDrawers |
|||
{ |
|||
[CustomPropertyDrawer(typeof(AssetSource<>))] |
|||
class AssetSourceDrawer : PropertyDrawer |
|||
{ |
|||
public override VisualElement CreatePropertyGUI(SerializedProperty property) |
|||
{ |
|||
return new AssetSourceElement(property, fieldInfo); |
|||
} |
|||
|
|||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) |
|||
{ |
|||
EditorGUI.PropertyField(position, property, label, true); |
|||
} |
|||
|
|||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) |
|||
{ |
|||
return EditorGUI.GetPropertyHeight(property); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace UnityEditor.Perception.Randomization |
|||
{ |
|||
static class AssetLoadingUtilities |
|||
{ |
|||
public static List<Object> LoadAssetsFromFolder(string folderPath, Type assetType) |
|||
{ |
|||
if (!folderPath.StartsWith(Application.dataPath)) |
|||
throw new ApplicationException("Selected folder is not an asset folder in this project"); |
|||
var assetsPath = "Assets" + folderPath.Remove(0, Application.dataPath.Length); |
|||
var assetIds = AssetDatabase.FindAssets($"t:{assetType.Name}", new[] { assetsPath }); |
|||
var assets = new List<Object>(); |
|||
foreach (var guid in assetIds) |
|||
assets.Add(AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), assetType)); |
|||
return assets; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 30b11971d353ad648b466b3f7763859e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 7e7eabbe9ff71e64291989566ea6ec83 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 29370b0293eb9a046b454ffdd7b1c372 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: c3b723ce8e6a50141834747972131766 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: ea8713402c0e1a946ac6af555b908641 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 6c8dccf3511434d2aadb672239c0c571 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements"> |
|||
<VisualElement class="parameter__categorical-options-list"> |
|||
<ListView name="assets"/> |
|||
</VisualElement> |
|||
<VisualElement style="flex-direction: row; justify-content: flex-end;"> |
|||
<Button name="add-asset" text="Add Asset" class="parameter__categorical-options-list-button"/> |
|||
<Button name="add-folder" text="Add Folder" class="parameter__categorical-options-list-button"/> |
|||
<Button name="clear-assets" text="Clear Assets" class="parameter__categorical-options-list-button"/> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: e4915dfbbc1de39478264a8f5d168ca0 |
|||
ScriptedImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} |
|
|||
<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements"> |
|||
<VisualElement class="parameter__categorical-option"> |
|||
<Button name="remove" class="randomization__remove-item-button"/> |
|||
<Label name="index-label" text="[0]" style="min-width: 50px;"/> |
|||
<editor:ObjectField name="item" class="parameter__categorical-option-property-field"/> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: d710875a5224e1b4186c4334f791ca19 |
|||
ScriptedImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} |
|
|||
fileFormatVersion: 2 |
|||
guid: e6fba9b826939224fac37b7ead85df2a |
|||
ScriptedImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} |
|
|||
<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements"> |
|||
<VisualElement style="margin-bottom: 4px;"> |
|||
<Style src="../../Uss/Styles.uss"/> |
|||
<Label name="name" text="Field Name" class="unity-base-field__label"/> |
|||
<VisualElement style="margin-left: 18px;"> |
|||
<VisualElement style="flex-direction: row; align-items: center;"> |
|||
<Label |
|||
text="Location" |
|||
class="unity-base-field__label" |
|||
tooltip="The asset source location to load assets from"/> |
|||
<editor:ToolbarMenu name="location-dropdown" text="Type" class="sampler__type-menu"/> |
|||
</VisualElement> |
|||
<VisualElement style="margin-left: 18px;"> |
|||
<VisualElement name="fields-container" style="flex-grow: 1;"/> |
|||
<TextElement name="location-notes" class="scenario__info-box"/> |
|||
</VisualElement> |
|||
<VisualElement style="flex-direction: row; align-items: center;"> |
|||
<Label |
|||
text="Asset Role" |
|||
class="unity-base-field__label" |
|||
tooltip="Asset Roles preprocess assets loaded from the selected asset source location"/> |
|||
<editor:ToolbarMenu name="asset-role-dropdown" text="Type" class="sampler__type-menu"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: 7c9fc5cac7e306247a669a3f33479736 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEditor; |
|||
using UnityEditor.Perception.Randomization; |
|||
using UnityEditor.UIElements; |
|||
using UnityEngine.UIElements; |
|||
|
|||
namespace Editor.Randomization.VisualElements.AssetSource |
|||
{ |
|||
class AssetListItemElement : VisualElement |
|||
{ |
|||
int m_Index; |
|||
Type m_ItemType; |
|||
SerializedProperty m_Property; |
|||
|
|||
public AssetListItemElement(SerializedProperty property, Type itemType) |
|||
{ |
|||
m_Property = property; |
|||
m_ItemType = itemType; |
|||
} |
|||
|
|||
public void BindProperties(int i) |
|||
{ |
|||
Clear(); |
|||
var template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>( |
|||
$"{StaticData.uxmlDir}/AssetSource/{nameof(AssetListItemElement)}.uxml"); |
|||
template.CloneTree(this); |
|||
|
|||
m_Index = i; |
|||
var indexLabel = this.Q<Label>("index-label"); |
|||
indexLabel.text = $"[{m_Index}]"; |
|||
|
|||
var optionProperty = m_Property.GetArrayElementAtIndex(i); |
|||
var option = this.Q<ObjectField>("item"); |
|||
option.BindProperty(optionProperty); |
|||
option.objectType = m_ItemType; |
|||
option.allowSceneObjects = false; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5fd946360906cd5449f8d54f3c65e41c |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 43a7574956bc88b45a6597e2c94c9cb6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections; |
|||
using UnityEditor; |
|||
using UnityEditor.Perception.Randomization; |
|||
using UnityEngine; |
|||
using UnityEngine.UIElements; |
|||
|
|||
namespace Editor.Randomization.VisualElements.AssetSource |
|||
{ |
|||
class AssetListElement : VisualElement |
|||
{ |
|||
SerializedProperty m_Property; |
|||
IList list => (IList)StaticData.GetManagedReferenceValue(m_Property); |
|||
|
|||
public AssetListElement(SerializedProperty property, Type itemType) |
|||
{ |
|||
m_Property = property; |
|||
var template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>( |
|||
$"{StaticData.uxmlDir}/AssetSource/AssetListElement.uxml"); |
|||
template.CloneTree(this); |
|||
|
|||
var listView = this.Q<ListView>("assets"); |
|||
listView.itemsSource = list; |
|||
listView.itemHeight = 22; |
|||
listView.selectionType = SelectionType.None; |
|||
listView.style.flexGrow = 1.0f; |
|||
listView.style.height = new StyleLength(listView.itemHeight * 4); |
|||
listView.makeItem = () => |
|||
{ |
|||
return new AssetListItemElement(m_Property, itemType); |
|||
}; |
|||
listView.bindItem = (element, i) => |
|||
{ |
|||
var optionElement = (AssetListItemElement)element; |
|||
optionElement.BindProperties(i); |
|||
var removeButton = optionElement.Q<Button>("remove"); |
|||
removeButton.clicked += () => |
|||
{ |
|||
// First delete sets option to null, second delete removes option
|
|||
var numOptions = m_Property.arraySize; |
|||
m_Property.DeleteArrayElementAtIndex(i); |
|||
if (numOptions == m_Property.arraySize) |
|||
m_Property.DeleteArrayElementAtIndex(i); |
|||
|
|||
m_Property.serializedObject.ApplyModifiedProperties(); |
|||
listView.itemsSource = list; |
|||
listView.Refresh(); |
|||
}; |
|||
}; |
|||
|
|||
var addOptionButton = this.Q<Button>("add-asset"); |
|||
addOptionButton.clicked += () => |
|||
{ |
|||
m_Property.arraySize++; |
|||
m_Property.serializedObject.ApplyModifiedProperties(); |
|||
listView.itemsSource = list; |
|||
listView.Refresh(); |
|||
listView.ScrollToItem(m_Property.arraySize); |
|||
}; |
|||
|
|||
var addFolderButton = this.Q<Button>("add-folder"); |
|||
addFolderButton.clicked += () => |
|||
{ |
|||
var folderPath = EditorUtility.OpenFolderPanel( |
|||
"Add Assets From Folder", Application.dataPath, string.Empty); |
|||
if (folderPath == string.Empty) |
|||
return; |
|||
|
|||
var assets = AssetLoadingUtilities.LoadAssetsFromFolder(folderPath, itemType); |
|||
var optionsIndex = m_Property.arraySize; |
|||
m_Property.arraySize += assets.Count; |
|||
for (var i = 0; i < assets.Count; i++) |
|||
{ |
|||
var optionProperty = m_Property.GetArrayElementAtIndex(optionsIndex + i); |
|||
optionProperty.objectReferenceValue = assets[i]; |
|||
} |
|||
|
|||
m_Property.serializedObject.ApplyModifiedProperties(); |
|||
listView.itemsSource = list; |
|||
listView.Refresh(); |
|||
}; |
|||
|
|||
var clearOptionsButton = this.Q<Button>("clear-assets"); |
|||
clearOptionsButton.clicked += () => |
|||
{ |
|||
m_Property.arraySize = 0; |
|||
m_Property.serializedObject.ApplyModifiedProperties(); |
|||
listView.itemsSource = list; |
|||
listView.Refresh(); |
|||
}; |
|||
} |
|||
} |
|||
} |
|
|||
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})"; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 27aa08b82cf94015adc22309c8f3bc48 |
|||
timeCreated: 1618977151 |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEngine.Perception.Randomization |
|||
{ |
|||
/// <summary>
|
|||
/// Derive this class to load Unity assets from a specific location
|
|||
/// </summary>
|
|||
public abstract class AssetSourceLocation |
|||
{ |
|||
/// <summary>
|
|||
/// The number of assets available at this location
|
|||
/// </summary>
|
|||
public abstract int count { get; } |
|||
|
|||
/// <summary>
|
|||
/// Execute setup steps before accessing assets at this location
|
|||
/// </summary>
|
|||
/// <param name="assetRole">The asset role that will be used to preprocess assets from this location</param>
|
|||
/// <typeparam name="T">The type of assets that will be loaded from this location</typeparam>
|
|||
public abstract void Initialize<T>(AssetRole<T> assetRole) where T : Object; |
|||
|
|||
/// <summary>
|
|||
/// Unload all assets loaded from this location
|
|||
/// </summary>
|
|||
public abstract void ReleaseAssets(); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an asset from this location using the provided index
|
|||
/// </summary>
|
|||
/// <param name="index">The index to load the asset from</param>
|
|||
/// <typeparam name="T">The type of asset to load</typeparam>
|
|||
/// <returns>The loaded asset</returns>
|
|||
public abstract T LoadAsset<T>(int index) where T : Object; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9f2e99decdb94c7c898d7702e10cbce5 |
|||
timeCreated: 1619732135 |
|
|||
fileFormatVersion: 2 |
|||
guid: 20f161f5e56247c280fc1b56b567f49a |
|||
timeCreated: 1618983500 |
|
|||
namespace UnityEngine.Perception.Randomization |
|||
{ |
|||
/// <summary>
|
|||
/// Derive this class to create a typed asset role.
|
|||
/// Typed asset roles are used to apply preprocessing steps to assets loaded from an <see cref="AssetSource{T}"/>.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of asset to preprocess</typeparam>
|
|||
public abstract class AssetRole<T> : IAssetRoleBase where T : Object |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public abstract string label { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
public abstract string description { get; } |
|||
|
|||
/// <summary>
|
|||
/// Perform preprocessing operations on an asset loaded from an <see cref="AssetSource{T}"/>.
|
|||
/// </summary>
|
|||
/// <param name="asset">The asset to preprocess</param>
|
|||
public abstract void Preprocess(T asset); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3fce529b432e45f45bee917a2c4205b6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine.Perception.Randomization.Samplers; |
|||
|
|||
namespace UnityEngine.Perception.Randomization |
|||
{ |
|||
/// <summary>
|
|||
/// AssetSources are used to load assets from a generically within a <see cref="Randomizers.Randomizer"/>
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of asset to load</typeparam>
|
|||
[Serializable] |
|||
public sealed class AssetSource<T> where T : Object |
|||
{ |
|||
[SerializeReference] IAssetRoleBase m_AssetRoleBase; |
|||
|
|||
/// <summary>
|
|||
/// The location to load assets from
|
|||
/// </summary>
|
|||
[SerializeReference] public AssetSourceLocation assetSourceLocation = new LocalAssetSourceLocation(); |
|||
|
|||
bool m_Initialized; |
|||
UniformSampler m_Sampler = new UniformSampler(); |
|||
|
|||
/// <summary>
|
|||
/// The asset role used to preprocess assets from this source
|
|||
/// </summary>
|
|||
public AssetRole<T> assetRole |
|||
{ |
|||
get => (AssetRole<T>)m_AssetRoleBase; |
|||
set => m_AssetRoleBase = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The number of assets available within this asset source
|
|||
/// </summary>
|
|||
public int count |
|||
{ |
|||
get |
|||
{ |
|||
CheckIfInitialized(); |
|||
return assetSourceLocation.count; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Execute setup steps for this AssetSource. It is often unnecessary to call this API directly since all other
|
|||
/// relevant APIs in this class will Initialize() this AssetSource if it hasn't been already.
|
|||
/// </summary>
|
|||
public void Initialize() |
|||
{ |
|||
if (!m_Initialized) |
|||
{ |
|||
assetSourceLocation.Initialize(assetRole); |
|||
m_Initialized = true; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the unprocessed asset loaded from the provided index
|
|||
/// </summary>
|
|||
/// <param name="index">The index of the asset to load</param>
|
|||
/// <returns>The asset loaded at the provided index</returns>
|
|||
public T LoadRawAsset(int index) |
|||
{ |
|||
CheckIfInitialized(); |
|||
return assetSourceLocation.LoadAsset<T>(index); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns all unprocessed assets that can be loaded from this AssetSource
|
|||
/// </summary>
|
|||
/// <returns>All assets that can be loaded from this AssetSource</returns>
|
|||
public T[] LoadAllRawAssets() |
|||
{ |
|||
CheckIfInitialized(); |
|||
var array = new T[count]; |
|||
for (var i = 0; i < count; i++) |
|||
array[i] = LoadRawAsset(i); |
|||
return array; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates an instance of the asset loaded from the provided index and preprocesses it using the asset role
|
|||
/// assigned to this asset source
|
|||
/// </summary>
|
|||
/// <param name="index">The index of the asset to load</param>
|
|||
/// <returns>The instantiated instance</returns>
|
|||
public T CreateProcessedInstance(int index) |
|||
{ |
|||
CheckIfInitialized(); |
|||
return CreateProcessedInstance(LoadRawAsset(index)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Instantiates, preprocesses, and returns all assets that can be loaded from this asset source
|
|||
/// </summary>
|
|||
/// <returns>Instantiated instances from every loadable asset</returns>
|
|||
public T[] CreateProcessedInstances() |
|||
{ |
|||
CheckIfInitialized(); |
|||
var array = new T[count]; |
|||
for (var i = 0; i < count; i++) |
|||
array[i] = CreateProcessedInstance(i); |
|||
return array; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a uniformly random sampled asset from this AssetSource
|
|||
/// </summary>
|
|||
/// <returns>The randomly sampled asset</returns>
|
|||
public T SampleAsset() |
|||
{ |
|||
CheckIfInitialized(); |
|||
return count == 0 ? null : assetSourceLocation.LoadAsset<T>((int)(m_Sampler.Sample() * count)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Instantiates and preprocesses a uniformly random sampled asset from this AssetSource
|
|||
/// </summary>
|
|||
/// <returns>The generated random instance</returns>
|
|||
public T SampleInstance() |
|||
{ |
|||
CheckIfInitialized(); |
|||
return CreateProcessedInstance(SampleAsset()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Unloads all assets that have been loaded from this AssetSource
|
|||
/// </summary>
|
|||
public void ReleaseAssets() |
|||
{ |
|||
CheckIfInitialized(); |
|||
assetSourceLocation.ReleaseAssets(); |
|||
} |
|||
|
|||
void CheckIfInitialized() |
|||
{ |
|||
if (!m_Initialized) |
|||
Initialize(); |
|||
} |
|||
|
|||
T CreateProcessedInstance(T asset) |
|||
{ |
|||
if (asset == null) |
|||
return null; |
|||
|
|||
var instance = Object.Instantiate(asset); |
|||
if (assetRole != null) |
|||
assetRole.Preprocess(instance); |
|||
return instance; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel; |
|||
|
|||
namespace UnityEngine.Perception.Randomization |
|||
{ |
|||
/// <summary>
|
|||
/// A basic <see cref="AssetSourceLocation"/> for loading local project assets
|
|||
/// </summary>
|
|||
[Serializable] |
|||
[DisplayName("Assets In Project")] |
|||
public class LocalAssetSourceLocation : AssetSourceLocation |
|||
{ |
|||
/// <summary>
|
|||
/// The list of local assets available from this source
|
|||
/// </summary>
|
|||
public List<Object> assets = new List<Object>(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int count => assets.Count; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Initialize<T>(AssetRole<T> assetRole) { } |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ReleaseAssets() { } |
|||
|
|||
/// <inheritdoc/>
|
|||
public override T LoadAsset<T>(int index) |
|||
{ |
|||
return (T)assets[index]; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
|
|||
namespace UnityEngine.Perception.Randomization |
|||
{ |
|||
/// <summary>
|
|||
/// Used to annotate an AssetSourceLocation with description notes within the inspector UI
|
|||
/// </summary>
|
|||
public class AssetSourceEditorDescriptionAttribute : Attribute |
|||
{ |
|||
/// <summary>
|
|||
/// The text notes to display in the AssetSourceLocation's UI.
|
|||
/// </summary>
|
|||
public string notes; |
|||
|
|||
/// <summary>
|
|||
/// Constructs a new AssetSourceLocationNotes attribute
|
|||
/// </summary>
|
|||
/// <param name="notes">The text notes to display in the inspector</param>
|
|||
public AssetSourceEditorDescriptionAttribute(string notes) |
|||
{ |
|||
this.notes = notes; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2aa6aeb2e6318114fb5ac0829edcac00 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 7c335d3150918dc49be9cf2eddb144d2 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEngine.Perception.Randomization |
|||
{ |
|||
/// <summary>
|
|||
/// The base asset role class. Derive from <see cref="AssetRole{T}"/> instead to create a new asset role.
|
|||
/// </summary>
|
|||
interface IAssetRoleBase |
|||
{ |
|||
/// <summary>
|
|||
/// The string label uniquely associated with this asset role
|
|||
/// </summary>
|
|||
string label { get; } |
|||
|
|||
/// <summary>
|
|||
/// A description for this asset role
|
|||
/// </summary>
|
|||
string description { get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c7b5bdabb856bb5469fd4033fb6bda01 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using NUnit.Framework; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.Randomization; |
|||
using UnityEngine.Perception.Randomization.Randomizers.SampleRandomizers.Tags; |
|||
|
|||
namespace RandomizationTests.AssetSourceTests |
|||
{ |
|||
[TestFixture] |
|||
public class LocalAssetSourceTests |
|||
{ |
|||
GameObject m_TestObject; |
|||
TestBehaviour m_Behaviour; |
|||
|
|||
class TestAssetRole : AssetRole<GameObject> |
|||
{ |
|||
public override string label => "test"; |
|||
public override string description => ""; |
|||
|
|||
public override void Preprocess(GameObject asset) |
|||
{ |
|||
asset.AddComponent<RotationRandomizerTag>(); |
|||
} |
|||
} |
|||
|
|||
class TestBehaviour : MonoBehaviour |
|||
{ |
|||
public AssetSource<GameObject> gameObjectSource = new AssetSource<GameObject> |
|||
{ |
|||
assetRole = new TestAssetRole(), |
|||
assetSourceLocation = new LocalAssetSourceLocation() |
|||
}; |
|||
} |
|||
|
|||
[SetUp] |
|||
public void Setup() |
|||
{ |
|||
m_TestObject = new GameObject(); |
|||
m_Behaviour = m_TestObject.AddComponent<TestBehaviour>(); |
|||
} |
|||
|
|||
[TearDown] |
|||
public void TearDown() |
|||
{ |
|||
Object.DestroyImmediate(m_TestObject); |
|||
} |
|||
|
|||
[Test] |
|||
public void GetZeroCountWithoutThrowingException() |
|||
{ |
|||
Assert.DoesNotThrow(() => |
|||
{ |
|||
var count = m_Behaviour.gameObjectSource.count; |
|||
}); |
|||
} |
|||
|
|||
[Test] |
|||
public void SampleFromEmptySourceReturnsNull() |
|||
{ |
|||
Assert.IsNull(m_Behaviour.gameObjectSource.SampleAsset()); |
|||
Assert.IsNull(m_Behaviour.gameObjectSource.SampleInstance()); |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue