浏览代码
Merge pull request #121 from Unity-Technologies/labeling-improvements
Merge pull request #121 from Unity-Technologies/labeling-improvements
New Labeling and Label Config UI/main
GitHub
4 年前
当前提交
245b8d01
共有 56 个文件被更改,包括 3221 次插入 和 222 次删除
-
305com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs
-
2com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs.meta
-
929com.unity.perception/Editor/GroundTruth/LabelingEditor.cs
-
2com.unity.perception/Editor/GroundTruth/LabelingEditor.cs.meta
-
141com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs
-
4com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs.meta
-
20com.unity.perception/Editor/Randomization/Uss/Styles.uss
-
1com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs
-
3com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs
-
25com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs
-
37com.unity.perception/Runtime/GroundTruth/Labeling/Labeling.cs
-
13com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs
-
8com.unity.perception/Editor/AssetPreparation.meta
-
396com.unity.perception/Editor/GroundTruth/AddToConfigWindow.cs
-
3com.unity.perception/Editor/GroundTruth/AddToConfigWindow.cs.meta
-
459com.unity.perception/Editor/GroundTruth/LabelConfigEditor.cs
-
3com.unity.perception/Editor/GroundTruth/LabelConfigEditor.cs.meta
-
8com.unity.perception/Editor/GroundTruth/Uss.meta
-
8com.unity.perception/Editor/GroundTruth/Uxml.meta
-
11com.unity.perception/Editor/AssetPreparation/AssetPreparationTools.cs.meta
-
24com.unity.perception/Editor/AssetPreparation/AssetPreparationTools.cs
-
3com.unity.perception/Editor/GroundTruth/Uss/Styles.uss.meta
-
228com.unity.perception/Editor/GroundTruth/Uss/Styles.uss
-
13com.unity.perception/Editor/GroundTruth/Uxml/AddToConfigWindow.uxml
-
10com.unity.perception/Editor/GroundTruth/Uxml/AddToConfigWindow.uxml.meta
-
7com.unity.perception/Editor/GroundTruth/Uxml/AddedLabelElement.uxml
-
3com.unity.perception/Editor/GroundTruth/Uxml/AddedLabelElement.uxml.meta
-
7com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementLabelNotPresent.uxml
-
3com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementLabelNotPresent.uxml.meta
-
8com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementLabelPresent.uxml
-
3com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementLabelPresent.uxml.meta
-
38com.unity.perception/Editor/GroundTruth/Uxml/Labeling_Main.uxml
-
10com.unity.perception/Editor/GroundTruth/Uxml/Labeling_Main.uxml.meta
-
7com.unity.perception/Editor/GroundTruth/Uxml/SuggestedLabelElement.uxml
-
3com.unity.perception/Editor/GroundTruth/Uxml/SuggestedLabelElement.uxml.meta
-
13com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementForAddingLabelsFrom.uxml
-
3com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementForAddingLabelsFrom.uxml.meta
-
10com.unity.perception/Editor/GroundTruth/Uxml/LabelConfig_Main.uxml.meta
-
14com.unity.perception/Editor/GroundTruth/Uxml/ColoredLabelElementInLabelConfig.uxml
-
3com.unity.perception/Editor/GroundTruth/Uxml/ColoredLabelElementInLabelConfig.uxml.meta
-
14com.unity.perception/Editor/GroundTruth/Uxml/IdLabelElementInLabelConfig.uxml
-
3com.unity.perception/Editor/GroundTruth/Uxml/IdLabelElementInLabelConfig.uxml.meta
-
53com.unity.perception/Editor/GroundTruth/Uxml/LabelConfig_Main.uxml
-
3com.unity.perception/Editor/Icons/ChevronDown.png
-
142com.unity.perception/Editor/Icons/ChevronDown.png.meta
-
6com.unity.perception/Editor/Icons/ChevronDownPadded.png
-
142com.unity.perception/Editor/Icons/ChevronDownPadded.png.meta
-
4com.unity.perception/Editor/Icons/ChevronUp.png
-
142com.unity.perception/Editor/Icons/ChevronUp.png.meta
-
4com.unity.perception/Editor/Icons/ChevronUpPadded.png
-
142com.unity.perception/Editor/Icons/ChevronUpPadded.png.meta
-
0/com.unity.perception/Editor/Icons.meta
-
0/com.unity.perception/Editor/Icons
|
|||
fileFormatVersion: 2 |
|||
guid: 910dd3186e1c4fad8eb6aca9b9ee0f48 |
|||
guid: 43cb2a3117353435abe59ca5217974a8 |
|||
timeCreated: 1585940009 |
|
|||
fileFormatVersion: 2 |
|||
guid: 2e725508a34c40a0938c8d891b371980 |
|||
guid: 387b8732b87094321af57795df93aec4 |
|||
timeCreated: 1585933334 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Generic; |
|||
using UnityEditorInternal; |
|||
using UnityEditor.UIElements; |
|||
using UnityEngine.UIElements; |
|||
class SemanticSegmentationLabelConfigEditor : Editor |
|||
class SemanticSegmentationLabelConfigEditor : LabelConfigEditor<SemanticSegmentationLabelEntry> |
|||
ReorderableList m_LabelsList; |
|||
const float k_Margin = 5f; |
|||
protected override void InitUiExtended() |
|||
{ |
|||
m_MoveButtons.style.display = DisplayStyle.None; |
|||
m_IdSpecificUi.style.display = DisplayStyle.None; |
|||
} |
|||
static List<Color> s_StandardColors = new List<Color>() |
|||
public override void PostRemoveOperations() |
|||
{ } |
|||
|
|||
protected override void SetupPresentLabelsListView() |
|||
Color.blue, |
|||
Color.green, |
|||
Color.red, |
|||
Color.white, |
|||
Color.yellow, |
|||
Color.gray |
|||
}; |
|||
base.SetupPresentLabelsListView(); |
|||
|
|||
VisualElement MakeItem() => |
|||
new ColoredLabelElementInLabelConfig(this, m_SerializedLabelsArray); |
|||
|
|||
void BindItem(VisualElement e, int i) |
|||
{ |
|||
if (e is ColoredLabelElementInLabelConfig addedLabel) |
|||
{ |
|||
addedLabel.indexInList = i; |
|||
addedLabel.labelTextField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i) |
|||
.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.label))); |
|||
addedLabel.colorField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i) |
|||
.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color))); |
|||
} |
|||
} |
|||
public void OnEnable() |
|||
{ |
|||
m_LabelsList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName), true, false, true, true); |
|||
m_LabelsList.elementHeight = EditorGUIUtility.singleLineHeight * 2 + k_Margin; |
|||
m_LabelsList.drawElementCallback = DrawElement; |
|||
m_LabelsList.onAddCallback += OnAdd; |
|||
m_LabelListView.bindItem = BindItem; |
|||
m_LabelListView.makeItem = MakeItem; |
|||
void OnAdd(ReorderableList list) |
|||
protected override SemanticSegmentationLabelEntry CreateLabelEntryFromLabelString(SerializedProperty serializedArray, string labelToAdd) |
|||
var standardColorList = new List<Color>(s_StandardColors); |
|||
for (int i = 0; i < list.serializedProperty.arraySize; i++) |
|||
var standardColorList = new List<Color>(SemanticSegmentationLabelConfig.s_StandardColors); |
|||
for (int i = 0; i < serializedArray.arraySize; i++) |
|||
var item = list.serializedProperty.GetArrayElementAtIndex(i); |
|||
var item = serializedArray.GetArrayElementAtIndex(i); |
|||
var index = list.serializedProperty.arraySize; |
|||
list.serializedProperty.InsertArrayElementAtIndex(index); |
|||
var element = list.serializedProperty.GetArrayElementAtIndex(index); |
|||
var labelProperty = element.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.label)); |
|||
labelProperty.stringValue = ""; |
|||
var colorProperty = element.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)); |
|||
if (standardColorList.Any()) |
|||
colorProperty.colorValue = standardColorList.First(); |
|||
else |
|||
colorProperty.colorValue = Random.ColorHSV(0, 1, .5f, 1, 1, 1); |
|||
|
|||
var foundColor = standardColorList.Any() ? standardColorList.First() : Random.ColorHSV(0, 1, .5f, 1, 1, 1); |
|||
serializedObject.ApplyModifiedProperties(); |
|||
EditorUtility.SetDirty(target); |
|||
return new SemanticSegmentationLabelEntry |
|||
{ |
|||
color = foundColor, |
|||
label = labelToAdd |
|||
}; |
|||
void DrawElement(Rect rect, int index, bool isactive, bool isfocused) |
|||
protected override void AppendLabelEntryToSerializedArray(SerializedProperty serializedArray, SemanticSegmentationLabelEntry semanticSegmentationLabelEntry) |
|||
var element = m_LabelsList.serializedProperty.GetArrayElementAtIndex(index); |
|||
var index = serializedArray.arraySize; |
|||
serializedArray.InsertArrayElementAtIndex(index); |
|||
var element = serializedArray.GetArrayElementAtIndex(index); |
|||
var labelProperty = element.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.label)); |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
colorProperty.colorValue = semanticSegmentationLabelEntry.color; |
|||
var labelProperty = element.FindPropertyRelative(nameof(ILabelEntry.label)); |
|||
labelProperty.stringValue = semanticSegmentationLabelEntry.label; |
|||
} |
|||
|
|||
public int IndexOfGivenColorInSerializedLabelsArray(Color color) |
|||
{ |
|||
for (int i = 0; i < m_SerializedLabelsArray.arraySize; i++) |
|||
var contentRect = new Rect(rect.position, new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
var newLabel = EditorGUI.TextField(contentRect, nameof(SemanticSegmentationLabelEntry.label), labelProperty.stringValue); |
|||
if (change.changed) |
|||
{ |
|||
labelProperty.stringValue = newLabel; |
|||
} |
|||
} |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var contentRect = new Rect(rect.position + new Vector2(0, EditorGUIUtility.singleLineHeight), new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
var newLabel = EditorGUI.ColorField(contentRect, nameof(SemanticSegmentationLabelEntry.color), colorProperty.colorValue); |
|||
if (change.changed) |
|||
var element = m_SerializedLabelsArray.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)); |
|||
if (element.colorValue == color) |
|||
colorProperty.colorValue = newLabel; |
|||
return i; |
|||
return -1; |
|||
} |
|||
public override void OnInspectorGUI() |
|||
class ColoredLabelElementInLabelConfig : LabelElementInLabelConfig<SemanticSegmentationLabelEntry> |
|||
{ |
|||
protected override string UxmlPath => k_UxmlDir + "ColoredLabelElementInLabelConfig.uxml"; |
|||
|
|||
public ColorField colorField; |
|||
|
|||
public ColoredLabelElementInLabelConfig(LabelConfigEditor<SemanticSegmentationLabelEntry> editor, SerializedProperty labelsArray) : base(editor, labelsArray) |
|||
{ } |
|||
|
|||
protected override void InitExtended() |
|||
serializedObject.Update(); |
|||
colorField = this.Q<ColorField>("label-color-value"); |
|||
|
|||
colorField.RegisterValueChangedCallback((cEvent) => |
|||
{ |
|||
var index = ((SemanticSegmentationLabelConfigEditor)m_LabelConfigEditor).IndexOfGivenColorInSerializedLabelsArray(cEvent.newValue); |
|||
|
|||
if (index != -1 && index != indexInList) |
|||
{ |
|||
//The listview recycles child visual elements and that causes the RegisterValueChangedCallback event to be called when scrolling.
|
|||
//Therefore, we need to make sure we are not in this code block just because of scrolling, but because the user is actively changing one of the labels.
|
|||
//The index check is for this purpose.
|
|||
m_LabelsList.DoLayoutList(); |
|||
this.serializedObject.ApplyModifiedProperties(); |
|||
Debug.LogWarning("A label with the chosen color " + cEvent.newValue + " has already been added to this label configuration."); |
|||
} |
|||
}); |
|||
|
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e8cb4fead5b34d41884c1c9a77308c72 |
|||
timeCreated: 1593454492 |
|||
guid: c8e809a6323844c71aa3cb751a6ae9a1 |
|||
timeCreated: 1585940009 |
|
|||
fileFormatVersion: 2 |
|||
guid: 0c2b01a759f934aa099b2949e1580c97 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using UnityEditor.UIElements; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using UnityEngine.UIElements; |
|||
using Object = UnityEngine.Object; |
|||
using Random = UnityEngine.Random; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth |
|||
{ |
|||
class AddToConfigWindow : EditorWindow |
|||
{ |
|||
VisualElement m_Root; |
|||
|
|||
const string k_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/"; |
|||
string m_UxmlPath; |
|||
|
|||
static List<string> s_LabelValues = new List<string>(); |
|||
static Label s_TitleLabel; |
|||
static Label s_Status; |
|||
|
|||
public void SetStatus(string status) |
|||
{ |
|||
s_Status.text = status; |
|||
s_Status.style.display = DisplayStyle.Flex; |
|||
} |
|||
|
|||
List<string> m_AllLabelConfigGuids = new List<string>(); |
|||
List<ScriptableObject> m_ConfigsContainingLabel = new List<ScriptableObject>(); |
|||
List<ScriptableObject> m_ConfigsNotContainingLabel = new List<ScriptableObject>(); |
|||
|
|||
static ListView s_PresentConfigsListview; |
|||
static ListView s_NonPresentConfigsListview; |
|||
static ListView s_SelectedLabelsListview; |
|||
static Label s_CurrentlyPresentTitle; |
|||
static Label s_OtherConfigsTitle; |
|||
|
|||
List<Type> m_LabelConfigTypes = new List<Type>(); |
|||
public static void ShowWindow(string labelValue) |
|||
{ |
|||
s_LabelValues.Clear(); |
|||
s_LabelValues.Add(labelValue); |
|||
ShowWindow(s_LabelValues); |
|||
} |
|||
|
|||
public static void ShowWindow(List<string> labelValues) |
|||
{ |
|||
s_LabelValues = new List<string>(labelValues); |
|||
var window = GetWindow<AddToConfigWindow>(); |
|||
|
|||
if (s_Status != null) |
|||
{ |
|||
s_Status.style.display = DisplayStyle.None; |
|||
} |
|||
|
|||
if (labelValues.Count == 1) |
|||
{ |
|||
|
|||
if(s_TitleLabel != null) |
|||
s_TitleLabel.text = "Label: \"" + s_LabelValues.First() + "\""; |
|||
|
|||
if (s_PresentConfigsListview != null) |
|||
{ |
|||
s_PresentConfigsListview.style.display = DisplayStyle.Flex; |
|||
} |
|||
|
|||
if (s_CurrentlyPresentTitle != null) |
|||
{ |
|||
s_CurrentlyPresentTitle.style.display = DisplayStyle.Flex; |
|||
} |
|||
|
|||
if (s_OtherConfigsTitle != null) |
|||
{ |
|||
s_OtherConfigsTitle.text = "Other Label Configs in Project"; |
|||
} |
|||
|
|||
if (s_NonPresentConfigsListview != null) |
|||
{ |
|||
s_NonPresentConfigsListview.style.height = 150; |
|||
} |
|||
|
|||
if (s_SelectedLabelsListview != null) |
|||
{ |
|||
s_SelectedLabelsListview.style.display = DisplayStyle.None; |
|||
} |
|||
|
|||
window.titleContent = new GUIContent("Manage Label"); |
|||
window.minSize = new Vector2(400, 390); |
|||
window.maxSize = new Vector2(700, 390); |
|||
} |
|||
else |
|||
{ |
|||
if(s_TitleLabel != null) |
|||
s_TitleLabel.text = "Labels to Add"; |
|||
|
|||
if (s_PresentConfigsListview != null) |
|||
{ |
|||
s_PresentConfigsListview.style.display = DisplayStyle.None; |
|||
} |
|||
|
|||
if (s_CurrentlyPresentTitle != null) |
|||
{ |
|||
s_CurrentlyPresentTitle.style.display = DisplayStyle.None; |
|||
} |
|||
|
|||
if (s_OtherConfigsTitle != null) |
|||
{ |
|||
s_OtherConfigsTitle.text = "All Label Configurations in Project"; |
|||
} |
|||
|
|||
if (s_NonPresentConfigsListview != null) |
|||
{ |
|||
s_NonPresentConfigsListview.style.height = 250; |
|||
} |
|||
|
|||
if (s_SelectedLabelsListview != null) |
|||
{ |
|||
s_SelectedLabelsListview.style.display = DisplayStyle.Flex; |
|||
|
|||
} |
|||
|
|||
window.titleContent = new GUIContent("Manage Labels"); |
|||
window.minSize = new Vector2(400, 370); |
|||
window.maxSize = new Vector2(700, 1000); |
|||
} |
|||
|
|||
window.Init(); |
|||
} |
|||
|
|||
|
|||
void Init() |
|||
{ |
|||
Show(); |
|||
|
|||
m_ConfigsContainingLabel.Clear(); |
|||
|
|||
m_LabelConfigTypes = FindAllSubTypes(typeof(LabelConfig<>)); |
|||
|
|||
RefreshConfigAssets(); |
|||
CheckInclusionInConfigs(m_AllLabelConfigGuids, s_LabelValues.Count == 1? s_LabelValues.First() : null); |
|||
SetupListViews(); |
|||
} |
|||
|
|||
void RefreshConfigAssets() |
|||
{ |
|||
AssetDatabase.Refresh(); |
|||
|
|||
m_AllLabelConfigGuids.Clear(); |
|||
foreach (var type in m_LabelConfigTypes) |
|||
{ |
|||
m_AllLabelConfigGuids.AddRange(AssetDatabase.FindAssets("t:"+type.Name)); |
|||
} |
|||
} |
|||
|
|||
void SetupListViews() |
|||
{ |
|||
//configs containing label
|
|||
if (s_LabelValues.Count == 1) |
|||
{ |
|||
//we are dealing with only one label
|
|||
|
|||
s_PresentConfigsListview.itemsSource = m_ConfigsContainingLabel; |
|||
VisualElement MakeItem1() => new ConfigElementLabelPresent(this, s_LabelValues.First()); |
|||
|
|||
void BindItem1(VisualElement e, int i) |
|||
{ |
|||
if (e is ConfigElementLabelPresent element) |
|||
{ |
|||
element.labelElement.text = m_ConfigsContainingLabel[i].name; |
|||
element.labelConfig = m_ConfigsContainingLabel[i]; |
|||
} |
|||
} |
|||
|
|||
s_PresentConfigsListview.itemHeight = 30; |
|||
s_PresentConfigsListview.bindItem = BindItem1; |
|||
s_PresentConfigsListview.makeItem = MakeItem1; |
|||
s_PresentConfigsListview.selectionType = SelectionType.None; |
|||
} |
|||
|
|||
|
|||
//Configs not containing label
|
|||
s_NonPresentConfigsListview.itemsSource = m_ConfigsNotContainingLabel; |
|||
VisualElement MakeItem2() => new ConfigElementLabelNotPresent(this, s_LabelValues); |
|||
|
|||
void BindItem2(VisualElement e, int i) |
|||
{ |
|||
if (e is ConfigElementLabelNotPresent element) |
|||
{ |
|||
element.labelElement.text = m_ConfigsNotContainingLabel[i].name; |
|||
element.labelConfig = m_ConfigsNotContainingLabel[i]; |
|||
} |
|||
} |
|||
|
|||
s_NonPresentConfigsListview.itemHeight = 30; |
|||
s_NonPresentConfigsListview.bindItem = BindItem2; |
|||
s_NonPresentConfigsListview.makeItem = MakeItem2; |
|||
s_NonPresentConfigsListview.selectionType = SelectionType.None; |
|||
|
|||
|
|||
//Selected labels
|
|||
s_SelectedLabelsListview.itemsSource = s_LabelValues; |
|||
|
|||
VisualElement MakeItem3() => new Label(); |
|||
void BindItem3(VisualElement e, int i) |
|||
{ |
|||
if (e is Label label) |
|||
{ |
|||
label.text = s_LabelValues[i]; |
|||
label.style.marginLeft = 2; |
|||
label.style.marginRight = 2; |
|||
} |
|||
} |
|||
|
|||
s_SelectedLabelsListview.itemHeight = 20; |
|||
s_SelectedLabelsListview.bindItem = BindItem3; |
|||
s_SelectedLabelsListview.makeItem = MakeItem3; |
|||
s_SelectedLabelsListview.selectionType = SelectionType.None; |
|||
} |
|||
|
|||
public void RefreshLists() |
|||
{ |
|||
CheckInclusionInConfigs(m_AllLabelConfigGuids, s_LabelValues.Count == 1? s_LabelValues.First() : null); |
|||
s_PresentConfigsListview.Refresh(); |
|||
s_NonPresentConfigsListview.Refresh(); |
|||
} |
|||
void OnEnable() |
|||
{ |
|||
m_UxmlPath = k_UxmlDir + "AddToConfigWindow.uxml"; |
|||
|
|||
m_Root = rootVisualElement; |
|||
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(m_UxmlPath).CloneTree(m_Root); |
|||
|
|||
s_TitleLabel = m_Root.Q<Label>("title"); |
|||
s_CurrentlyPresentTitle = m_Root.Q<Label>("currently-present-label"); |
|||
s_OtherConfigsTitle = m_Root.Q<Label>("other-configs-label"); |
|||
s_PresentConfigsListview = m_Root.Q<ListView>("current-configs-listview"); |
|||
s_NonPresentConfigsListview = m_Root.Q<ListView>("other-configs-listview"); |
|||
s_SelectedLabelsListview = m_Root.Q<ListView>("selected-labels-list"); |
|||
s_Status = m_Root.Q<Label>("status"); |
|||
s_Status.style.display = DisplayStyle.None; |
|||
} |
|||
|
|||
void CheckInclusionInConfigs(List<string> configGuids, string label = null) |
|||
{ |
|||
m_ConfigsContainingLabel.Clear(); |
|||
m_ConfigsNotContainingLabel.Clear(); |
|||
|
|||
foreach (var configGuid in configGuids) |
|||
{ |
|||
var asset = AssetDatabase.LoadAssetAtPath<ScriptableObject>(AssetDatabase.GUIDToAssetPath(configGuid)); |
|||
if (label != null) |
|||
{ |
|||
//means we are dealing with only one label not a set
|
|||
var methodInfo = asset.GetType().GetMethod(IdLabelConfig.DoesLabelMatchAnEntryName); |
|||
|
|||
if (methodInfo == null) |
|||
continue; |
|||
|
|||
object[] parametersArray = new object[1]; |
|||
parametersArray[0] = label; |
|||
|
|||
var labelExistsInConfig = (bool) methodInfo.Invoke(asset, parametersArray); |
|||
|
|||
if (labelExistsInConfig) |
|||
{ |
|||
m_ConfigsContainingLabel.Add(asset); |
|||
} |
|||
else |
|||
{ |
|||
m_ConfigsNotContainingLabel.Add(asset); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
m_ConfigsNotContainingLabel.Add(asset); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static List<Type> FindAllSubTypes(Type superType) |
|||
{ |
|||
Assembly assembly = Assembly.GetAssembly(superType); |
|||
Type[] types = assembly.GetTypes(); |
|||
List<Type> subclasses = types.Where(t => IsSubclassOfRawGeneric(superType, t)).ToList(); |
|||
return subclasses; |
|||
|
|||
|
|||
bool IsSubclassOfRawGeneric(Type generic, Type toCheck) { |
|||
while (toCheck != null && toCheck != typeof(object)) { |
|||
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; |
|||
if (generic == cur) { |
|||
return true; |
|||
} |
|||
toCheck = toCheck.BaseType; |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
class ConfigElementLabelPresent : VisualElement |
|||
{ |
|||
const string k_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/"; |
|||
VisualElement m_Root; |
|||
ObjectField m_ConfigObjectField; |
|||
|
|||
public Label labelElement; |
|||
public ScriptableObject labelConfig; |
|||
|
|||
public ConfigElementLabelPresent(AddToConfigWindow window, string targetLabel) |
|||
{ |
|||
var uxmlPath = k_UxmlDir + "ConfigElementLabelPresent.uxml"; |
|||
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxmlPath).CloneTree(this); |
|||
labelElement = this.Q<Label>("config-name"); |
|||
var removeButton = this.Q<Button>("remove-from-config-button"); |
|||
removeButton.text = "Remove Label"; |
|||
|
|||
var openButton = this.Q<Button>("open-config-button"); |
|||
openButton.clicked += () => |
|||
{ |
|||
Selection.SetActiveObjectWithContext(labelConfig, null); |
|||
}; |
|||
|
|||
removeButton.clicked += () => |
|||
{ |
|||
var editor = Editor.CreateEditor(labelConfig); |
|||
if (editor is SemanticSegmentationLabelConfigEditor semanticEditor) |
|||
{ |
|||
semanticEditor.RemoveLabel(targetLabel); |
|||
} |
|||
else if (editor is IdLabelConfigEditor idEditor) |
|||
{ |
|||
idEditor.RemoveLabel(targetLabel); |
|||
} |
|||
|
|||
window.RefreshLists(); |
|||
Object.DestroyImmediate(editor); |
|||
}; |
|||
} |
|||
} |
|||
|
|||
|
|||
class ConfigElementLabelNotPresent : VisualElement |
|||
{ |
|||
const string k_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/"; |
|||
VisualElement m_Root; |
|||
ObjectField m_ConfigObjectField; |
|||
public Label labelElement; |
|||
public ScriptableObject labelConfig; |
|||
|
|||
public ConfigElementLabelNotPresent(AddToConfigWindow window, List<string> targetLabels) |
|||
{ |
|||
var uxmlPath = k_UxmlDir + "ConfigElementLabelPresent.uxml"; |
|||
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxmlPath).CloneTree(this); |
|||
labelElement = this.Q<Label>("config-name"); |
|||
var addButton = this.Q<Button>("remove-from-config-button"); |
|||
addButton.text = targetLabels.Count ==1 ? "Add Label" : "Add All Labels"; |
|||
|
|||
var openButton = this.Q<Button>("open-config-button"); |
|||
openButton.clicked += () => |
|||
{ |
|||
Selection.SetActiveObjectWithContext(labelConfig, null); |
|||
}; |
|||
|
|||
addButton.clicked += () => |
|||
{ |
|||
var editor = Editor.CreateEditor(labelConfig); |
|||
if (editor is SemanticSegmentationLabelConfigEditor semanticEditor) |
|||
{ |
|||
foreach (var label in targetLabels) |
|||
{ |
|||
semanticEditor.AddLabel(label); |
|||
} |
|||
} |
|||
else if (editor is IdLabelConfigEditor idEditor) |
|||
{ |
|||
foreach (var label in targetLabels) |
|||
{ |
|||
idEditor.AddLabel(label); |
|||
} |
|||
} |
|||
|
|||
if (targetLabels.Count > 1) |
|||
{ |
|||
window.SetStatus("All Labels Added to " + labelConfig.name); |
|||
} |
|||
|
|||
window.RefreshLists(); |
|||
Object.DestroyImmediate(editor); |
|||
}; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2485979b726fe4f3b829a3a4173a72c6 |
|||
timeCreated: 1585933334 |
|
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using Newtonsoft.Json.Linq; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using UnityEngine.UIElements; |
|||
using UnityEditor.UIElements; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth |
|||
{ |
|||
abstract class LabelConfigEditor<T> : Editor where T : ILabelEntry |
|||
{ |
|||
string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/"; |
|||
string m_UxmlPath; |
|||
|
|||
int m_AddedLabelsItemHeight = 37; |
|||
int m_OtherLabelsItemHeight = 27; |
|||
|
|||
List<string> m_AddedLabels = new List<string>(); |
|||
|
|||
protected SerializedProperty m_SerializedLabelsArray; |
|||
|
|||
HashSet<string> m_AllLabelsInProject = new HashSet<string>(); |
|||
List<string> m_LabelsNotPresentInConfig = new List<string>(); |
|||
bool m_UiInitialized; |
|||
bool m_EditorHasUi; |
|||
|
|||
VisualElement m_Root; |
|||
|
|||
Button m_SaveButton; |
|||
Button m_AddNewLabelButton; |
|||
Button m_RemoveAllButton; |
|||
Button m_AddAllButton; |
|||
Button m_ImportFromFileButton; |
|||
Button m_ExportToFileButton; |
|||
ListView m_NonPresentLabelsListView; |
|||
|
|||
protected ListView m_LabelListView; |
|||
protected Button m_MoveUpButton; |
|||
protected Button m_MoveDownButton; |
|||
protected VisualElement m_MoveButtons; |
|||
protected VisualElement m_IdSpecificUi; |
|||
protected EnumField m_StartingIdEnumField; |
|||
protected Toggle m_AutoIdToggle; |
|||
|
|||
|
|||
public void OnEnable() |
|||
{ |
|||
m_SerializedLabelsArray = serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName); |
|||
m_UiInitialized = false; |
|||
ChangesHappeningInForeground = true; |
|||
RefreshListDataAndPresentation(); |
|||
} |
|||
|
|||
int m_PreviousLabelsArraySize = -1; |
|||
/// <summary>
|
|||
/// This boolean is used to signify when changes in the model are triggered directly from the inspector UI by the user.
|
|||
/// In these cases, the scheduled model checker does not need to update the UI again.
|
|||
/// </summary>
|
|||
public bool ChangesHappeningInForeground { get; set; } |
|||
|
|||
void CheckForModelChanges() |
|||
{ |
|||
if (ChangesHappeningInForeground) |
|||
{ |
|||
ChangesHappeningInForeground = false; |
|||
m_PreviousLabelsArraySize = m_SerializedLabelsArray.arraySize; |
|||
return; |
|||
} |
|||
|
|||
if (m_SerializedLabelsArray.arraySize != m_PreviousLabelsArraySize) |
|||
{ |
|||
RefreshListDataAndPresentation(); |
|||
m_PreviousLabelsArraySize = m_SerializedLabelsArray.arraySize; |
|||
} |
|||
} |
|||
|
|||
protected abstract void InitUiExtended(); |
|||
|
|||
public abstract void PostRemoveOperations(); |
|||
|
|||
public override VisualElement CreateInspectorGUI() |
|||
{ |
|||
if (!m_UiInitialized) |
|||
{ |
|||
InitUi(); |
|||
m_UiInitialized = true; |
|||
} |
|||
serializedObject.Update(); |
|||
RefreshListDataAndPresentation(); |
|||
return m_Root; |
|||
} |
|||
|
|||
void InitUi() |
|||
{ |
|||
m_EditorHasUi = true; |
|||
|
|||
m_UxmlPath = m_UxmlDir + "LabelConfig_Main.uxml"; |
|||
m_Root = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(m_UxmlPath).CloneTree(); |
|||
m_LabelListView = m_Root.Q<ListView>("labels-listview"); |
|||
|
|||
m_NonPresentLabelsListView = m_Root.Q<ListView>("labels-in-project-listview"); |
|||
m_SaveButton = m_Root.Q<Button>("save-button"); |
|||
m_AddNewLabelButton = m_Root.Q<Button>("add-label"); |
|||
m_RemoveAllButton = m_Root.Q<Button>("remove-all-labels"); |
|||
m_MoveUpButton = m_Root.Q<Button>("move-up-button"); |
|||
m_MoveDownButton = m_Root.Q<Button>("move-down-button"); |
|||
m_MoveButtons = m_Root.Q<VisualElement>("move-buttons"); |
|||
m_ImportFromFileButton = m_Root.Q<Button>("import-file-button"); |
|||
m_ExportToFileButton = m_Root.Q<Button>("export-file-button"); |
|||
m_AddAllButton = m_Root.Q<Button>("add-all-labels-in-project"); |
|||
m_StartingIdEnumField = m_Root.Q<EnumField>("starting-id-dropdown"); |
|||
m_AutoIdToggle = m_Root.Q<Toggle>("auto-id-toggle"); |
|||
m_IdSpecificUi = m_Root.Q<VisualElement>("id-specific-ui"); |
|||
|
|||
m_SaveButton.SetEnabled(false); |
|||
|
|||
SetupPresentLabelsListView(); |
|||
RefreshLabelsMasterList(); |
|||
RefreshNonPresentLabels(); |
|||
SetupNonPresentLabelsListView(); |
|||
|
|||
InitUiExtended(); |
|||
UpdateMoveButtonState(null); |
|||
|
|||
m_AddNewLabelButton.clicked += () => { AddNewLabel(m_AddedLabels); }; |
|||
|
|||
#if UNITY_2020_1_OR_NEWER
|
|||
m_LabelListView.onSelectionChange += UpdateMoveButtonState; |
|||
#else
|
|||
m_LabelListView.onSelectionChanged += UpdateMoveButtonState; |
|||
#endif
|
|||
m_RemoveAllButton.clicked += () => |
|||
{ |
|||
m_SerializedLabelsArray.ClearArray(); |
|||
serializedObject.ApplyModifiedProperties(); |
|||
ChangesHappeningInForeground = true; |
|||
RefreshListDataAndPresentation(); |
|||
}; |
|||
|
|||
m_AddAllButton.clicked += () => |
|||
{ |
|||
foreach (var label in m_LabelsNotPresentInConfig) |
|||
{ |
|||
AppendLabelEntryToSerializedArray(m_SerializedLabelsArray, CreateLabelEntryFromLabelString(m_SerializedLabelsArray, label)); |
|||
} |
|||
serializedObject.ApplyModifiedProperties(); |
|||
ChangesHappeningInForeground = true; |
|||
RefreshListDataAndPresentation(); |
|||
}; |
|||
|
|||
m_ImportFromFileButton.clicked += () => |
|||
{ |
|||
var path = EditorUtility.OpenFilePanel("Import label configuration from file", "", "json"); |
|||
if (path.Length != 0) |
|||
{ |
|||
var fileContent = File.ReadAllText(path); |
|||
var jsonObj = JObject.Parse(fileContent); |
|||
ImportFromJson(jsonObj); |
|||
} |
|||
}; |
|||
|
|||
m_ExportToFileButton.clicked += () => |
|||
{ |
|||
var path = EditorUtility.SaveFilePanel("Export label configuration to file", "", this.name, "json"); |
|||
if (path.Length != 0) |
|||
{ |
|||
string fileContents = ExportToJson(); |
|||
var writer = File.CreateText(path); |
|||
|
|||
writer.Write(fileContents); |
|||
writer.Flush(); |
|||
writer.Close(); |
|||
} |
|||
}; |
|||
|
|||
m_Root.schedule.Execute(CheckForModelChanges).Every(30); |
|||
} |
|||
|
|||
void RefreshLabelsMasterList() |
|||
{ |
|||
m_AllLabelsInProject.Clear(); |
|||
|
|||
var allPrefabPaths = GetAllPrefabsInProject(); |
|||
foreach (var path in allPrefabPaths) |
|||
{ |
|||
var asset = AssetDatabase.LoadAssetAtPath<GameObject>(path); |
|||
var labeling = asset.GetComponent<Labeling>(); |
|||
if (labeling) |
|||
{ |
|||
m_AllLabelsInProject.UnionWith(labeling.labels); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void RefreshNonPresentLabels() |
|||
{ |
|||
m_LabelsNotPresentInConfig.Clear(); |
|||
m_LabelsNotPresentInConfig.AddRange(m_AllLabelsInProject); |
|||
m_LabelsNotPresentInConfig.RemoveAll(label => m_AddedLabels.Contains(label)); |
|||
} |
|||
|
|||
static IEnumerable<string> GetAllPrefabsInProject() |
|||
{ |
|||
var allPaths = AssetDatabase.GetAllAssetPaths(); |
|||
return allPaths.Where(path => path.EndsWith(".prefab")).ToList(); |
|||
} |
|||
|
|||
void UpdateMoveButtonState(IEnumerable<object> objectList) |
|||
{ |
|||
var selectedIndex = m_LabelListView.selectedIndex; |
|||
m_MoveDownButton.SetEnabled(selectedIndex < m_LabelListView.itemsSource.Count - 1); |
|||
m_MoveUpButton.SetEnabled(selectedIndex > 0); |
|||
} |
|||
|
|||
public void RefreshListDataAndPresentation() |
|||
{ |
|||
serializedObject.Update(); |
|||
RefreshAddedLabels(); |
|||
if (m_EditorHasUi && m_UiInitialized) |
|||
{ |
|||
RefreshNonPresentLabels(); |
|||
m_NonPresentLabelsListView.Refresh(); |
|||
RefreshListViewHeight(); |
|||
m_LabelListView.Refresh(); |
|||
} |
|||
} |
|||
|
|||
void ScrollToBottomAndSelectLastItem() |
|||
{ |
|||
m_LabelListView.selectedIndex = m_LabelListView.itemsSource.Count - 1; |
|||
UpdateMoveButtonState(null); |
|||
|
|||
m_Root.schedule.Execute(() => { m_LabelListView.ScrollToItem(-1); }) |
|||
.StartingIn( |
|||
10); //to circumvent the delay in listview's internal scrollview updating its geometry (when new items are added).
|
|||
} |
|||
|
|||
protected void RefreshAddedLabels() |
|||
{ |
|||
m_AddedLabels.Clear(); |
|||
m_SerializedLabelsArray = serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName); |
|||
|
|||
for (int i = 0; i < m_SerializedLabelsArray.arraySize; i++) |
|||
{ |
|||
m_AddedLabels.Add(m_SerializedLabelsArray.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(ILabelEntry.label)).stringValue); |
|||
} |
|||
} |
|||
|
|||
protected virtual void SetupPresentLabelsListView() |
|||
{ |
|||
m_LabelListView.itemsSource = m_AddedLabels; |
|||
m_LabelListView.itemHeight = m_AddedLabelsItemHeight; |
|||
m_LabelListView.selectionType = SelectionType.Single; |
|||
|
|||
m_LabelListView.RegisterCallback<AttachToPanelEvent>(evt => { RefreshListViewHeight(); }); |
|||
} |
|||
|
|||
void SetupNonPresentLabelsListView() |
|||
{ |
|||
m_NonPresentLabelsListView.itemsSource = m_LabelsNotPresentInConfig; |
|||
|
|||
VisualElement MakeItem() |
|||
{ |
|||
var element = new NonPresentLabelElement<T>(this); |
|||
return element; |
|||
} |
|||
|
|||
void BindItem(VisualElement e, int i) |
|||
{ |
|||
if (e is NonPresentLabelElement<T> nonPresentLabel) |
|||
{ |
|||
nonPresentLabel.label.text = m_LabelsNotPresentInConfig[i]; |
|||
} |
|||
} |
|||
|
|||
m_NonPresentLabelsListView.bindItem = BindItem; |
|||
m_NonPresentLabelsListView.makeItem = MakeItem; |
|||
m_NonPresentLabelsListView.itemHeight = m_OtherLabelsItemHeight; |
|||
m_NonPresentLabelsListView.selectionType = SelectionType.None; |
|||
} |
|||
|
|||
protected void RefreshListViewHeight() |
|||
{ |
|||
m_LabelListView.style.minHeight = |
|||
Mathf.Clamp(m_LabelListView.itemsSource.Count * m_LabelListView.itemHeight, 300, 600); |
|||
} |
|||
|
|||
string FindNewLabelString(List<string> labels) |
|||
{ |
|||
string baseLabel = "New Label"; |
|||
string label = baseLabel; |
|||
int count = 1; |
|||
while (labels.Contains(label)) |
|||
{ |
|||
label = baseLabel + "_" + count++; |
|||
} |
|||
|
|||
return label; |
|||
} |
|||
|
|||
void AddNewLabel(List<string> presentLabels) |
|||
{ |
|||
AddLabel(FindNewLabelString(presentLabels)); |
|||
} |
|||
|
|||
public void AddLabel(string labelToAdd) |
|||
{ |
|||
if (m_AddedLabels.Contains(labelToAdd)) //label has already been added, cannot add again
|
|||
return; |
|||
|
|||
AppendLabelEntryToSerializedArray(m_SerializedLabelsArray, CreateLabelEntryFromLabelString(m_SerializedLabelsArray, labelToAdd)); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
RefreshListDataAndPresentation(); |
|||
if (m_EditorHasUi) |
|||
ScrollToBottomAndSelectLastItem(); |
|||
} |
|||
|
|||
public void RemoveLabel(string labelToRemove) |
|||
{ |
|||
var index = IndexOfStringLabelInSerializedLabelsArray(labelToRemove); |
|||
if (index >= 0) |
|||
{ |
|||
m_SerializedLabelsArray.DeleteArrayElementAtIndex(index); |
|||
} |
|||
serializedObject.ApplyModifiedProperties(); |
|||
RefreshListDataAndPresentation(); |
|||
if (m_EditorHasUi) |
|||
ScrollToBottomAndSelectLastItem(); |
|||
} |
|||
|
|||
protected abstract T CreateLabelEntryFromLabelString(SerializedProperty serializedArray, string labelToAdd); |
|||
|
|||
protected abstract void AppendLabelEntryToSerializedArray(SerializedProperty serializedArray, T labelEntry); |
|||
|
|||
void ImportFromJson(JObject jsonObj) |
|||
{ |
|||
Undo.RegisterCompleteObjectUndo(serializedObject.targetObject, "Import new label config"); |
|||
JsonUtility.FromJsonOverwrite(jsonObj.ToString(), serializedObject.targetObject); |
|||
ChangesHappeningInForeground = true; |
|||
RefreshListDataAndPresentation(); |
|||
} |
|||
|
|||
string ExportToJson() |
|||
{ |
|||
return JsonUtility.ToJson(serializedObject.targetObject); |
|||
} |
|||
|
|||
public int IndexOfStringLabelInSerializedLabelsArray(string label) |
|||
{ |
|||
for (int i = 0; i < m_SerializedLabelsArray.arraySize; i++) |
|||
{ |
|||
var element = m_SerializedLabelsArray.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(ILabelEntry.label)); |
|||
if (element.stringValue == label) |
|||
{ |
|||
return i; |
|||
} |
|||
} |
|||
return -1; |
|||
} |
|||
} |
|||
|
|||
abstract class LabelElementInLabelConfig<T> : VisualElement where T : ILabelEntry |
|||
{ |
|||
protected const string k_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/"; |
|||
protected abstract string UxmlPath { get; } |
|||
|
|||
Button m_RemoveButton; |
|||
|
|||
public TextField labelTextField; |
|||
|
|||
public int indexInList; |
|||
|
|||
protected SerializedProperty m_LabelsArray; |
|||
|
|||
protected LabelConfigEditor<T> m_LabelConfigEditor; |
|||
|
|||
protected LabelElementInLabelConfig(LabelConfigEditor<T> editor, SerializedProperty labelsArray) |
|||
{ |
|||
m_LabelConfigEditor = editor; |
|||
m_LabelsArray = labelsArray; |
|||
|
|||
Init(); |
|||
} |
|||
|
|||
void Init() |
|||
{ |
|||
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(UxmlPath).CloneTree(this); |
|||
labelTextField = this.Q<TextField>("label-value"); |
|||
m_RemoveButton = this.Q<Button>("remove-button"); |
|||
|
|||
labelTextField.isDelayed = true; |
|||
|
|||
InitExtended(); |
|||
|
|||
labelTextField.RegisterValueChangedCallback((cEvent) => |
|||
{ |
|||
int index = m_LabelConfigEditor.IndexOfStringLabelInSerializedLabelsArray(cEvent.newValue); |
|||
|
|||
if (index != -1 && index != indexInList) |
|||
{ |
|||
//The listview recycles child visual elements and that causes the RegisterValueChangedCallback event to be called when scrolling.
|
|||
//Therefore, we need to make sure we are not in this code block just because of scrolling, but because the user is actively changing one of the labels.
|
|||
//The index check is for this purpose.
|
|||
|
|||
Debug.LogError("A label with the string " + cEvent.newValue + " has already been added to this label configuration."); |
|||
m_LabelsArray.GetArrayElementAtIndex(indexInList).FindPropertyRelative(nameof(ILabelEntry.label)) |
|||
.stringValue = cEvent.previousValue; //since the textfield is bound to this property, it has already changed the property, so we need to revert the property.
|
|||
m_LabelsArray.serializedObject.ApplyModifiedProperties(); |
|||
m_LabelConfigEditor.ChangesHappeningInForeground = true; |
|||
m_LabelConfigEditor.RefreshListDataAndPresentation(); |
|||
return; |
|||
} |
|||
|
|||
|
|||
//even though the textfield is already bound to the relevant property, we need to explicitly set the
|
|||
//property here too in order to make "hasModifiedProperties" return the right value in the next line. Otherwise it will always be false.
|
|||
m_LabelsArray.GetArrayElementAtIndex(indexInList).FindPropertyRelative(nameof(ILabelEntry.label)) |
|||
.stringValue = cEvent.newValue; |
|||
if (m_LabelsArray.serializedObject.hasModifiedProperties) |
|||
{ |
|||
//the value change event is called even when the listview recycles its child elements for re-use during scrolling, therefore, we should check to make sure there are modified properties, otherwise we would be doing the refresh for no reason (reduces scrolling performance)
|
|||
m_LabelsArray.serializedObject.ApplyModifiedProperties(); |
|||
m_LabelConfigEditor.ChangesHappeningInForeground = true; |
|||
m_LabelConfigEditor.RefreshListDataAndPresentation(); |
|||
} |
|||
}); |
|||
|
|||
m_RemoveButton.clicked += () => |
|||
{ |
|||
m_LabelsArray.DeleteArrayElementAtIndex(indexInList); |
|||
m_LabelConfigEditor.PostRemoveOperations(); |
|||
m_LabelConfigEditor.serializedObject.ApplyModifiedProperties(); |
|||
m_LabelConfigEditor.ChangesHappeningInForeground = true; |
|||
m_LabelConfigEditor.RefreshListDataAndPresentation(); |
|||
}; |
|||
} |
|||
|
|||
protected abstract void InitExtended(); |
|||
} |
|||
|
|||
class NonPresentLabelElement<T> : VisualElement where T : ILabelEntry |
|||
{ |
|||
string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/"; |
|||
public Label label; |
|||
|
|||
public NonPresentLabelElement(LabelConfigEditor<T> editor) |
|||
{ |
|||
var uxmlPath = m_UxmlDir + "SuggestedLabelElement.uxml"; |
|||
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxmlPath).CloneTree(this); |
|||
label = this.Q<Label>("label-value"); |
|||
var addButton = this.Q<Button>("add-button"); |
|||
|
|||
addButton.clicked += () => { editor.AddLabel(label.text); }; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ffb8bb7ed73a343f3ae88c68aaf8a84f |
|||
timeCreated: 1585940009 |
|
|||
fileFormatVersion: 2 |
|||
guid: c9dfe1921f7e84112aa13f8a71d7a2f1 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d98210a441f014a5cb3b1f68cfa69326 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: c9787ce9a433e4916b180bf69288f689 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.IO; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Perception.AssetPreparation |
|||
{ |
|||
static class AssetPreparationMenuItems |
|||
{ |
|||
/// <summary>
|
|||
/// Function for creating prefabs from multiple models with one click. Created prefabs will be placed in the same folder as their corresponding model.
|
|||
/// </summary>
|
|||
[MenuItem("Assets/Perception/Create Prefabs from Selected Models")] |
|||
static void CreatePrefabsFromSelectedModels() |
|||
{ |
|||
foreach (var selection in Selection.gameObjects) |
|||
{ |
|||
var path = AssetDatabase.GetAssetPath(selection); |
|||
var tmpGameObject = Object.Instantiate(selection); |
|||
var destinationPath = Path.GetDirectoryName(path) + "/" + selection.name + ".prefab"; |
|||
PrefabUtility.SaveAsPrefabAsset(tmpGameObject, destinationPath); |
|||
Object.DestroyImmediate(tmpGameObject); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: dbe9e8ec4b8ef4ff384a22001ff72674 |
|||
timeCreated: 1601665266 |
|
|||
|
|||
.labeling__remove-item-button { |
|||
width: 16px; |
|||
height: 16px; |
|||
background-image: resource('Packages/com.unity.perception/Editor/Icons/X.png'); |
|||
background-color: #505050; |
|||
align-self: center; |
|||
} |
|||
|
|||
.labeling__remove-item-button:hover { |
|||
background-color: #808080; |
|||
} |
|||
.added-label { |
|||
margin: 3px 4px 3px 4px; |
|||
flex-direction: row; |
|||
align-content: center; |
|||
} |
|||
|
|||
.labeling__added-label-value { |
|||
width: 40%; |
|||
flex-grow: 1; |
|||
color: black; |
|||
} |
|||
|
|||
.labeling__added-label-value > .unity-text-field__input { |
|||
color: rgb(195, 195, 195); |
|||
background-color: #313131; |
|||
border-width: 0; |
|||
} |
|||
|
|||
|
|||
.suggested-label { |
|||
flex-direction: row; |
|||
align-content: center; |
|||
margin: 4px 6px 0 6px; |
|||
padding: 2px; |
|||
padding-left: 5px; |
|||
border-radius: 4px; |
|||
background-color: #313131; |
|||
} |
|||
|
|||
.labeling__suggested-label-value { |
|||
width: auto; |
|||
flex-grow: 1; |
|||
align-self: center; |
|||
color: rgb(180, 180, 180); |
|||
} |
|||
|
|||
.labeling__label-listview { |
|||
flex-grow: 1; |
|||
min-height: 120px; |
|||
border-radius: 4px; |
|||
margin-right: 2px; |
|||
margin-top: 2px; |
|||
padding: 6px; |
|||
padding-top: 6px; |
|||
border-bottom-right-radius: 0; |
|||
background-color: #272727; |
|||
} |
|||
|
|||
.labeling__configs-listview { |
|||
flex-grow: 1; |
|||
min-height: 150px; |
|||
background-color: rgb(32, 32, 32); |
|||
border-radius: 4px; |
|||
margin: 6px; |
|||
padding: 6px; |
|||
border-bottom-right-radius: 0; |
|||
} |
|||
|
|||
.labeling__add-label-button { |
|||
align-self: flex-end; |
|||
border-top-right-radius: 0; |
|||
border-top-left-radius: 0; |
|||
background-color: #222222; |
|||
border-color: #707070; |
|||
border-width: 0; |
|||
margin-right: 2px; |
|||
margin-top: 2px; |
|||
border-radius: 2px; |
|||
color: #CACACA; |
|||
} |
|||
|
|||
.labeling__add-label-button:hover{ |
|||
background-color: #606060; |
|||
} |
|||
.labeling__add-label-button:active{ |
|||
background-color: #303030; |
|||
} |
|||
|
|||
.outer-container { |
|||
padding-top: 5px; |
|||
flex-grow: 1; |
|||
} |
|||
|
|||
.outer-container-in-window{ |
|||
padding: 7px; |
|||
} |
|||
|
|||
.inner-container { |
|||
margin-top: 5px; |
|||
border-radius: 4px; |
|||
border-width: 1px; |
|||
padding: 5px; |
|||
background-color: #454545; |
|||
align-content: flex-start; |
|||
} |
|||
|
|||
.inner-container .depth2{ |
|||
background-color: rgb(60, 60, 60); |
|||
} |
|||
|
|||
.labeling__add-to-list-button { |
|||
align-self: flex-end; |
|||
background-color: #505050; |
|||
border-width: 0; |
|||
color: #EEEEEE; |
|||
} |
|||
|
|||
.labeling__add-to-config-button { |
|||
padding: 6px; |
|||
flex-shrink: 1; |
|||
-unity-text-align: middle-left; |
|||
background-color: #505050; |
|||
border-width: 0; |
|||
color: #EEEEEE; |
|||
} |
|||
|
|||
.title-label { |
|||
-unity-font-style: bold; |
|||
margin-bottom: 5px; |
|||
color: #CACACA; |
|||
} |
|||
|
|||
.subtitle-label { |
|||
color: #CACACA; |
|||
} |
|||
|
|||
.collapse-toggle { |
|||
flex-shrink: 0; |
|||
margin-right: 3px; |
|||
margin-left: 3px; |
|||
width: 10px; |
|||
height: 10px; |
|||
align-self: center; |
|||
background-image: resource("Packages/com.unity.perception/Editor/Icons/FoldoutOpen.png"); |
|||
} |
|||
|
|||
.collapsed-toggle-state{ |
|||
background-image: resource("Packages/com.unity.perception/Editor/Icons/FoldoutClosed.png"); |
|||
} |
|||
|
|||
.collapse-toggle:hover { |
|||
-unity-background-image-tint-color: cornflowerblue; |
|||
} |
|||
|
|||
.label-config-header{ |
|||
background-color: #272727; |
|||
flex-direction: row; |
|||
} |
|||
|
|||
.suggested-label.label_add_from_config{ |
|||
margin: 3px 3px 3px 3px; |
|||
} |
|||
|
|||
.label-config-add-from{ |
|||
border-radius: 4px; |
|||
margin: 2px 0 2px 0; |
|||
background-color: #272727; |
|||
padding: 3px 1px 3px 1px; |
|||
} |
|||
|
|||
.labeling__config-name-label { |
|||
color: rgb(220, 220, 220); |
|||
width: auto; |
|||
flex-grow: 1; |
|||
align-self: center; |
|||
padding: 4px; |
|||
} |
|||
|
|||
.collapsed { |
|||
display: none; |
|||
} |
|||
|
|||
.config-label-present{ |
|||
flex-direction: row; |
|||
align-content: center; |
|||
border-radius: 4px; |
|||
margin: 3px; |
|||
background-color: #272727; |
|||
} |
|||
|
|||
.move-label-in-config-button{ |
|||
background-color: #505050; |
|||
width: 30px; |
|||
height: 16px; |
|||
align-self: center; |
|||
-unity-background-scale-mode: scale-to-fit; |
|||
} |
|||
|
|||
.move-up{ |
|||
background-image: resource('Packages/com.unity.perception/Editor/Icons/ChevronUpPadded.png'); |
|||
} |
|||
|
|||
.move-down{ |
|||
background-image: resource('Packages/com.unity.perception/Editor/Icons/ChevronDownPadded.png'); |
|||
} |
|||
|
|||
.move-label-in-config-button:hover{ |
|||
background-color: #808080; |
|||
} |
|||
.move-label-in-config-button:active{ |
|||
background-color: #303030; |
|||
} |
|||
|
|||
.generic-hover:hover{ |
|||
background-color: #555555; |
|||
} |
|||
|
|||
.helpbox{ |
|||
border-width: 1px; |
|||
border-color: #808080; |
|||
border-radius: 4px; |
|||
padding: 7px; |
|||
white-space: normal; |
|||
margin-top: 4px; |
|||
margin-bottom: 4px; |
|||
} |
|
|||
<UXML xmlns="UnityEngine.UIElements"> |
|||
<VisualElement class="outer-container-in-window" name="outer-container"> |
|||
<Style src="../Uss/Styles.uss"/> |
|||
<Label name="title" class="title-label"/> |
|||
<ListView name="selected-labels-list" class="labeling__label-listview" style="height:800px; margin: 0;"/> |
|||
<Label name="currently-present-label" text="Currently Present In:" style="margin: 10px 0 4px 0"/> |
|||
<ListView name="current-configs-listview" class="labeling__configs-listview" style="height:150px; margin: 0; max-height:150px"/> |
|||
<Label name="other-configs-label" style="margin: 10px 0 4px 0"/> |
|||
<ListView name="other-configs-listview" class="labeling__configs-listview" style="height:150px; margin: 0; max-height:150px"/> |
|||
<Label name="status" style="display:none; margin-top: 7px; -unity-font-style: bold; color:yellow"/> |
|||
</VisualElement> |
|||
</UXML> |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: 8b8acfa72087c43698d342a06e2b30e6 |
|||
ScriptedImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} |
|
|||
<UXML xmlns="UnityEngine.UIElements"> |
|||
<VisualElement class="added-label"> |
|||
<Button name="remove-button" class="labeling__remove-item-button" /> |
|||
<TextField name="label-value" class="labeling__added-label-value" /> |
|||
<Button name="add-to-config-button" text="Add to Label Config..." class="labeling__add-to-config-button" /> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: ab7eae2a6fad4a95ac73aa5d46704ef6 |
|||
timeCreated: 1603311500 |
|
|||
<UXML xmlns="UnityEngine.UIElements"> |
|||
<VisualElement> |
|||
<Style src="../Uss/Styles.uss"/> |
|||
<Label name="config-name" class="labeling__config-name-label"/> |
|||
<Button name="add-to-config-button" class="labeling__addremove-config-button"/> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: 5335f0007841a4aae96d6ec9e95d1b39 |
|||
timeCreated: 1603311500 |
|
|||
<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements"> |
|||
<VisualElement class="config-label-present"> |
|||
<Style src="../Uss/Styles.uss"/> |
|||
<Label name="config-name" class="labeling__config-name-label"/> |
|||
<Button name="remove-from-config-button" class="labeling__addremove-config-button"/> |
|||
<Button name="open-config-button" class="labeling__addremove-config-button" text="Open"/> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: f65364e03181f4f24acd20305f6c34bb |
|||
timeCreated: 1603311500 |
|
|||
<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements"> |
|||
<VisualElement class="outer-container" name="outer-container"> |
|||
<Style src="../Uss/Styles.uss"/> |
|||
<Toggle name = "auto-or-manual-toggle" text="Use Automatic Labeling" style="margin-top: 5px"/> |
|||
<VisualElement name="automatic-labeling" class="inner-container"> |
|||
<VisualElement name = "drop-down-parent"/> |
|||
<VisualElement style="flex-direction:row; flex-shrink:1; width:auto"> |
|||
<Label name ="current-auto-label-title" text="Automatic Label:"/> |
|||
<Label name ="current-auto-label" style="-unity-font-style: bold; margin-left: 54px;"/> |
|||
</VisualElement> |
|||
<Button name ="add-auto-label-to-config" text="Add to Label Config..." style="margin-top: 5px; align-self: flex-end;"/> |
|||
</VisualElement> |
|||
<VisualElement name="manual-labeling" class="inner-container" style="margin-top:5px"> |
|||
<Label text="Added Labels" name="added-labels-title" class="title-label"/> |
|||
<ListView name="current-labels-listview" class="labeling__label-listview" style="margin-top: 2px"/> |
|||
<Button name="add-label" text="Add New Label" class="labeling__add-label-button"/> |
|||
<Label name = "add-manual-labels-title" text="Add Labels" class="title-label" style = "margin-top:0px"/> |
|||
<VisualElement name="from-label-configs" class="inner-container depth2" style="margin-top:0"> |
|||
<Label text="From Existing Label Configs" class="title-label"/> |
|||
<VisualElement name="add-from-label-configs" style="padding-top: 0px;"> |
|||
<ScrollView name="label-configs-scrollview" class="labeling__label-configs-scrollview" style="min-height: 100px;"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
<VisualElement name="suggested-labels" class="inner-container depth2"> |
|||
<Label text="Other Suggested Labels" class="title-label"/> |
|||
<VisualElement name="suggested-labels-from-name" style="padding-top: 5px;"> |
|||
<Label text="Based on asset name" class="subtitle-label"/> |
|||
<ListView name="suggested-labels-name-listview" class="labeling__label-listview" style="min-height: 100px;"/> |
|||
</VisualElement> |
|||
<VisualElement name="suggested-labels-from-path" style="padding-top: 5px;"> |
|||
<Label text="Based on asset path" class="subtitle-label"/> |
|||
<ListView name="suggested-labels-path-listview" class="labeling__label-listview" style="min-height: 100px;"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</UXML> |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: 3cef46fa678f14155a2dfb5393f41af1 |
|||
ScriptedImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} |
|
|||
<UXML xmlns="UnityEngine.UIElements"> |
|||
<VisualElement class="suggested-label"> |
|||
<Style src="../Uss/Styles.uss"/> |
|||
<Label name="label-value" class="labeling__suggested-label-value"/> |
|||
<Button name="add-button" class="labeling__add-to-list-button" text="Add to Labels"/> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: 194f2c0998a924e0eb89baba7fa4141a |
|||
timeCreated: 1603311500 |
|
|||
<UXML xmlns="UnityEngine.UIElements"> |
|||
<Toggle name="collapsed-state" style="display:none"/> |
|||
<VisualElement class="label-config-add-from"> |
|||
<Style src="../Uss/Styles.uss"/> |
|||
<VisualElement class="label-config-header"> |
|||
<VisualElement name="collapse-toggle" class="collapse-toggle"/> |
|||
<Label name="config-name" class="labeling__config-name-label"/> |
|||
<VisualElement style="flex-grow:1"/> |
|||
<Button name="open-config-button" text="Open"/> |
|||
</VisualElement> |
|||
<ListView name="label-config-contents-listview" class="labeling__label-listview" style="height: 300px"/> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: 0b6d5a00362234d9488a43570dfd15ae |
|||
timeCreated: 1603311500 |
|
|||
fileFormatVersion: 2 |
|||
guid: 5a298ce54f2b64db49ada97cd180b99d |
|||
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="added-label" style="padding-top: 3px;"> |
|||
<Button name="remove-button" class="labeling__remove-item-button"/> |
|||
<VisualElement class="generic-hover" |
|||
style="flex-direction: row; padding: 3px 0 3px 6px; margin-left: 3px; margin-right: 3px; border-width: 1px; border-color: #555555; border-radius: 4px;"> |
|||
<editor:ColorField name="label-color-value" style="min-width : 60px; max-width: 60px; align-self:center;"/> |
|||
</VisualElement> |
|||
<TextField name="label-value" class="labeling__added-label-value"/> |
|||
<VisualElement style="min-width:20px; flex-direction: row; display:none"> |
|||
<Button name="move-up-button" class="move-label-in-config-button move-up" style="margin-right:-2px"/> |
|||
<Button name="move-down-button" class="move-label-in-config-button move-down"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: 092a4ceabfda6410dbc745780dd88616 |
|||
timeCreated: 1603311500 |
|
|||
<UXML xmlns="UnityEngine.UIElements"> |
|||
<VisualElement class="added-label" style="padding-top: 3px;"> |
|||
<Button name="remove-button" class="labeling__remove-item-button" /> |
|||
<VisualElement class="generic-hover" style = "flex-direction: row; padding: 3px; margin-left: 3px; margin-right: 3px; border-width: 1px; border-color: #555555; border-radius: 4px;"> |
|||
<Label name="label-id-title" text = "ID = " style="align-self:center; color: #888888;"/> |
|||
<TextField name="label-id-value" style="-unity-font-style: bold; color: #888888; min-width : 30px; align-self:center;"/> |
|||
</VisualElement> |
|||
<TextField name="label-value" class="labeling__added-label-value"/> |
|||
<VisualElement style="min-width:20px; flex-direction: row; display:none"> |
|||
<Button name="move-up-button" class="move-label-in-config-button move-up" style="margin-right:-2px"/> |
|||
<Button name="move-down-button" class="move-label-in-config-button move-down"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
fileFormatVersion: 2 |
|||
guid: 2961168094add41168cf3b38ba7009dd |
|||
timeCreated: 1603311500 |
|
|||
<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements"> |
|||
<VisualElement class="outer-container" name="outer-container"> |
|||
<Style src="../Uss/Styles.uss"/> |
|||
<VisualElement class="inner-container" name="id-specific-ui"> |
|||
<Toggle name="auto-id-toggle" text="Auto Assign IDs" style="margin:0" binding-path="autoAssignIds"/> |
|||
<VisualElement style="flex-direction: row; flex-grow: 1;"> |
|||
<editor:EnumField label="Starting ID" name="starting-id-dropdown" binding-path="startingLabelId" |
|||
style="flex-grow:1; margin:0"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
<VisualElement name="added-labels" class="inner-container" style="margin-top:5px"> |
|||
<Label text="Added Labels" name="added-labels-title" class="title-label"/> |
|||
<ListView name="labels-listview" class="labeling__label-listview" style="margin-top: 5px;"/> |
|||
<Button name="save-button" text="Save" style="display:none"/> |
|||
<VisualElement name="button-bar" style="min-width:20px; flex-direction: row; margin-top: 5px"> |
|||
<VisualElement name="move-buttons" style="flex-direction: row; min-width:100px"> |
|||
<Label text="Move Selected Label:" style="align-self:center; margin-left: 2px; flex-shrink:1"/> |
|||
<Button name="move-up-button" class="move-label-in-config-button move-up" |
|||
style="margin-right:-2px"/> |
|||
<Button name="move-down-button" class="move-label-in-config-button move-down"/> |
|||
</VisualElement> |
|||
<VisualElement style="flex-grow:1"/> |
|||
<Button name="remove-all-labels" text="Remove All" class="labeling__add-label-button" |
|||
style="color:red"/> |
|||
<Button name="add-label" text="Add New Label" class="labeling__add-label-button"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
|
|||
<VisualElement name="other-labels" class="inner-container depth2"> |
|||
<Label text="Other Labels in Project" class="title-label"/> |
|||
<ListView name="labels-in-project-listview" class="labeling__label-listview" |
|||
style="margin-top: 5px; min-height: 200px"/> |
|||
<Button name="add-all-labels-in-project" text="Add All Labels to Config" class="labeling__add-label-button" |
|||
style="margin-top: 5px"/> |
|||
</VisualElement> |
|||
|
|||
<VisualElement name="other-labels" class="inner-container depth2"> |
|||
<Label text="Import or Export Label Config" name="added-labels-title" class="title-label"/> |
|||
<VisualElement style="flex-direction: row; flex-grow: 1; padding: 0; margin: 8 0 3 0"> |
|||
<Button name="import-file-button" text="Import from File" class="title-label" |
|||
style="align-self: center; padding: 10px; flex-grow:1; height: 40px; margin: 0 3 0 0"/> |
|||
<Button name="export-file-button" text="Export to File" class="title-label" |
|||
style="align-self: center; padding: 10px; flex-grow:1; height: 40px; margin: 0 0 0 3"/> |
|||
</VisualElement> |
|||
<VisualElement class="helpbox" style="margin: 7px 0 7px 0 "> |
|||
<TextElement |
|||
text="Importing a label config file will overwrite all existing contents of this label config."/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
|
|||
</VisualElement> |
|||
</UXML> |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: fa47b84af1c764637bf825673d76949a |
|||
TextureImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 11 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 1 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
vTOnly: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: 2 |
|||
mipBias: -100 |
|||
wrapU: 0 |
|||
wrapV: 0 |
|||
wrapW: 0 |
|||
nPOTScale: 1 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 0 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 0 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
ignorePngGamma: 0 |
|||
applyGammaDecoding: 0 |
|||
platformSettings: |
|||
- serializedVersion: 3 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Standalone |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: iPhone |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Android |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Windows Store Apps |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
internalID: 0 |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
secondaryTextures: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 7d8b0ddb7696e48a6a9e037ba7d08e73 |
|||
TextureImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 11 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 1 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
vTOnly: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: 2 |
|||
mipBias: -100 |
|||
wrapU: 0 |
|||
wrapV: 0 |
|||
wrapW: 0 |
|||
nPOTScale: 1 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 0 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 0 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
ignorePngGamma: 0 |
|||
applyGammaDecoding: 0 |
|||
platformSettings: |
|||
- serializedVersion: 3 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Standalone |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: iPhone |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Android |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Windows Store Apps |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
internalID: 0 |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
secondaryTextures: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 7c5db57ceb3164158b79c2eceb75cdbc |
|||
TextureImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 11 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 1 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
vTOnly: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: 2 |
|||
mipBias: -100 |
|||
wrapU: 0 |
|||
wrapV: 0 |
|||
wrapW: 0 |
|||
nPOTScale: 1 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 0 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 0 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
ignorePngGamma: 0 |
|||
applyGammaDecoding: 0 |
|||
platformSettings: |
|||
- serializedVersion: 3 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Standalone |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: iPhone |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Android |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Windows Store Apps |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
internalID: 0 |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
secondaryTextures: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 110dd95b59b974fd28227e7a929eec75 |
|||
TextureImporter: |
|||
internalIDToNameTable: [] |
|||
externalObjects: {} |
|||
serializedVersion: 11 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 1 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
vTOnly: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: 2 |
|||
mipBias: -100 |
|||
wrapU: 0 |
|||
wrapV: 0 |
|||
wrapW: 0 |
|||
nPOTScale: 1 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 0 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 0 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
ignorePngGamma: 0 |
|||
applyGammaDecoding: 0 |
|||
platformSettings: |
|||
- serializedVersion: 3 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Standalone |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: iPhone |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Android |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
- serializedVersion: 3 |
|||
buildTarget: Windows Store Apps |
|||
maxTextureSize: 8192 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
forceMaximumCompressionQuality_BC6H_BC7: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
internalID: 0 |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
secondaryTextures: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue