浏览代码

fixed undo issue with json importing

/main
Mohsen Kamalzadeh 4 年前
当前提交
dad3e482
共有 17 个文件被更改,包括 444 次插入387 次删除
  1. 109
      com.unity.perception/Editor/GroundTruth/AddToConfigWindow.cs
  2. 164
      com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs
  3. 288
      com.unity.perception/Editor/GroundTruth/LabelConfigEditor.cs
  4. 80
      com.unity.perception/Editor/GroundTruth/LabelingEditor.cs
  5. 82
      com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs
  6. 7
      com.unity.perception/Editor/GroundTruth/Uss/Styles.uss
  7. 5
      com.unity.perception/Editor/GroundTruth/Uxml/AddToConfigWindow.uxml
  8. 2
      com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementForAddingLabelsFrom.uxml
  9. 1
      com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementLabelPresent.uxml
  10. 4
      com.unity.perception/Editor/GroundTruth/Uxml/IdLabelElementInLabelConfig.uxml
  11. 12
      com.unity.perception/Editor/GroundTruth/Uxml/LabelConfig_Main.uxml
  12. 18
      com.unity.perception/Editor/GroundTruth/Uxml/Labeling_Main.uxml
  13. 2
      com.unity.perception/Editor/GroundTruth/Uxml/SuggestedLabelElement.uxml
  14. 30
      com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs
  15. 20
      com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs
  16. 3
      com.unity.perception/Runtime/GroundTruth/Labeling/Labeling.cs
  17. 4
      com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs

109
com.unity.perception/Editor/GroundTruth/AddToConfigWindow.cs


using UnityEngine;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace UnityEditor.Perception.GroundTruth
{

private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
private string m_UxmlPath;
private static HashSet<string> m_LabelValues = new HashSet<string>();
private static List<string> m_LabelValues = new List<string>();
private static Label m_TitleLabel;
private static Label m_Status;

private static ListView m_PresentConfigsListview;
private static ListView m_NonPresentConfigsListview;
private static ListView m_SelectedLabelsListview;
private static Label m_CurrentlyPresentTitle;
private static Label m_OtherConfigsTitle;

ShowWindow(m_LabelValues);
}
public static void ShowWindow(HashSet<string> labelValues)
public static void ShowWindow(List<string> labelValues)
m_LabelValues = new HashSet<string>(labelValues);
m_LabelValues = new List<string>(labelValues);
var window = GetWindow<AddToConfigWindow>();
if (labelValues.Count == 1)
{

if (m_OtherConfigsTitle != null)
{
m_OtherConfigsTitle.text = "Other Label Configs in Project:";
m_OtherConfigsTitle.text = "Other Label Configs in Project";
}
if (m_NonPresentConfigsListview != null)

if (m_SelectedLabelsListview != null)
{
m_SelectedLabelsListview.style.display = DisplayStyle.None;
}
window.minSize = new Vector2(350, 385);
window.maxSize = new Vector2(350, 600);
window.minSize = new Vector2(400, 390);
window.maxSize = new Vector2(400, 390);
m_TitleLabel.text = "Multiple Labels Selected";
m_TitleLabel.text = "Labels to Add";
if (m_PresentConfigsListview != null)
{

if (m_OtherConfigsTitle != null)
{
m_OtherConfigsTitle.text = "All Label Configurations in Project:";
m_OtherConfigsTitle.text = "All Label Configurations in Project";
}
if (m_NonPresentConfigsListview != null)

if (m_SelectedLabelsListview != null)
{
m_SelectedLabelsListview.style.display = DisplayStyle.Flex;
}
window.minSize = new Vector2(350, 300);
window.maxSize = new Vector2(350, 600);
window.minSize = new Vector2(400, 370);
window.maxSize = new Vector2(400, 1000);
}
window.Init();

m_NonPresentConfigsListview.bindItem = BindItem2;
m_NonPresentConfigsListview.makeItem = MakeItem2;
m_NonPresentConfigsListview.selectionType = SelectionType.None;
//Selected labels
m_SelectedLabelsListview.itemsSource = m_LabelValues;
VisualElement MakeItem3() => new Label();
void BindItem3(VisualElement e, int i)
{
if (e is Label label)
{
label.text = m_LabelValues[i];
label.style.marginLeft = 2;
label.style.marginRight = 2;
}
}
m_SelectedLabelsListview.itemHeight = 20;
m_SelectedLabelsListview.bindItem = BindItem3;
m_SelectedLabelsListview.makeItem = MakeItem3;
m_SelectedLabelsListview.selectionType = SelectionType.None;
}
public void RefreshLists()

m_OtherConfigsTitle = m_Root.Q<Label>("other-configs-label");
m_PresentConfigsListview = m_Root.Q<ListView>("current-configs-listview");
m_NonPresentConfigsListview = m_Root.Q<ListView>("other-configs-listview");
m_SelectedLabelsListview = m_Root.Q<ListView>("selected-labels-list");
m_Status = m_Root.Q<Label>("status");
m_Status.style.display = DisplayStyle.None;
}

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(m_LabelConfig, null);
};
var methodInfo = m_LabelConfig.GetType().GetMethod(IdLabelConfig.RemoveLabelName);
if (methodInfo != null)
var editor = Editor.CreateEditor(m_LabelConfig);
if (editor is SemanticSegmentationLabelConfigEditor semanticEditor)
object[] parametersArray = new object[1];
parametersArray[0] = targetLabel;
semanticEditor.RemoveLabel(targetLabel);
}
else if (editor is IdLabelConfigEditor idEditor)
{
idEditor.RemoveLabel(targetLabel);
}
methodInfo.Invoke(m_LabelConfig, parametersArray);
EditorUtility.SetDirty(m_LabelConfig);
window.RefreshLists();
}
window.RefreshLists();
//AssetDatabase.SaveAssets();
Object.DestroyImmediate(editor);
};
}
}

public Label m_Label;
public ScriptableObject m_LabelConfig;
public ConfigElementLabelNotPresent(AddToConfigWindow window, HashSet<string> targetLabels)
public ConfigElementLabelNotPresent(AddToConfigWindow window, List<string> targetLabels)
{
var uxmlPath = m_UxmlDir + "ConfigElementLabelPresent.uxml";
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxmlPath).CloneTree(this);

var openButton = this.Q<Button>("open-config-button");
openButton.clicked += () =>
{
Selection.SetActiveObjectWithContext(m_LabelConfig, null);
};
var methodInfo = m_LabelConfig.GetType().GetMethod(IdLabelConfig.AddLabelName);
if (methodInfo != null)
var editor = Editor.CreateEditor(m_LabelConfig);
if (editor is SemanticSegmentationLabelConfigEditor semanticEditor)
{
foreach (var label in targetLabels)
{
semanticEditor.AddLabel(label);
}
}
else if (editor is IdLabelConfigEditor idEditor)
object[] parametersArray = new object[1];
foreach (var targetLabel in targetLabels)
foreach (var label in targetLabels)
parametersArray[0] = targetLabel;
methodInfo.Invoke(m_LabelConfig, parametersArray);
idEditor.AddLabel(label);
EditorUtility.SetDirty(m_LabelConfig);
window.RefreshLists();
}
if (targetLabels.Count > 1)

window.RefreshLists();
//AssetDatabase.SaveAssets();
Object.DestroyImmediate(editor);
};
}
}

164
com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs


#define ENABLED
#if ENABLED
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Mathematics;

using UnityEngine.UIElements;
using Newtonsoft.Json.Linq;
namespace UnityEditor.Perception.GroundTruth
{

protected override LabelConfig<IdLabelEntry> TargetLabelConfig => (IdLabelConfig) serializedObject.targetObject;
protected override void OnEnableExtended()
protected override void InitUiExtended()
var prop = serializedObject.FindProperty(nameof(IdLabelConfig.startingLabelId));
var id = (int) ((StartingLabelId) evt.newValue);
serializedObject.FindProperty(nameof(IdLabelConfig.startingLabelId)).enumValueIndex = id;
serializedObject.ApplyModifiedProperties();

m_AutoIdToggle.RegisterValueChangedCallback(evt =>
{
serializedObject.FindProperty(nameof(IdLabelConfig.autoAssignIds)).boolValue = evt.newValue;
m_StartingIdEnumField.SetEnabled(evt.newValue);
serializedObject.ApplyModifiedProperties();
if (!evt.newValue)
{
ChangesHappeningInForeground = true;
RefreshListDataAndPresentation();
//if evt.newValue is true, the auto assign function will perform the above refresh, so no need to do this twice
//refresh is needed because the id textfields of the labels need to be enabled or disabled accordingly
}
AutoAssignIdsIfNeeded();
});
m_StartingIdEnumField.SetEnabled(AutoAssign);
AutoAssignIdsIfNeeded();
m_MoveDownButton.clicked += MoveSelectedItemDown;
m_MoveUpButton.clicked += MoveSelectedItemUp;

topProperty.stringValue = currentProperty.stringValue;
currentProperty.stringValue = tmpString;
if (!AutoAssign)
{
var currentIdProperty =
m_SerializedLabelsArray.GetArrayElementAtIndex(selectedIndex)
.FindPropertyRelative(nameof(IdLabelEntry.id));
var topIdProperty = m_SerializedLabelsArray.GetArrayElementAtIndex(selectedIndex - 1)
.FindPropertyRelative(nameof(IdLabelEntry.id));
var tmpInt = topIdProperty.intValue;
topIdProperty.intValue = currentIdProperty.intValue;
currentIdProperty.intValue = tmpInt;
}
m_LabelListView.selectedIndex = selectedIndex - 1;
serializedObject.ApplyModifiedProperties();

bottomProperty.stringValue = currentProperty.stringValue;
currentProperty.stringValue = tmpString;
if (!AutoAssign)
{
var currentIdProperty =
m_SerializedLabelsArray.GetArrayElementAtIndex(selectedIndex)
.FindPropertyRelative(nameof(IdLabelEntry.id));
var bottomIdProperty = m_SerializedLabelsArray.GetArrayElementAtIndex(selectedIndex + 1)
.FindPropertyRelative(nameof(IdLabelEntry.id));
var tmpInt = bottomIdProperty.intValue;
bottomIdProperty.intValue = currentIdProperty.intValue;
currentIdProperty.intValue = tmpInt;
}
m_LabelListView.selectedIndex = selectedIndex + 1;
serializedObject.ApplyModifiedProperties();

addedLabel.m_IndexInList = i;
addedLabel.m_LabelTextField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i)
.FindPropertyRelative(nameof(IdLabelEntry.label)));
addedLabel.m_LabelId.text = TargetLabelConfig.labelEntries[i].id.ToString();
addedLabel.UpdateMoveButtonVisibility(m_SerializedLabelsArray);
addedLabel.m_LabelIdTextField.value = m_SerializedLabelsArray.GetArrayElementAtIndex(i)
.FindPropertyRelative(nameof(IdLabelEntry.id)).intValue.ToString();
}
}

};
}
protected override IdLabelEntry ImportFromJsonExtended(string labelString, JObject labelEntryJObject,
List<IdLabelEntry> previousEntries, bool preventDuplicateIdentifiers = true)
{
bool invalid = false;
int parsedId = -1;
if (labelEntryJObject.TryGetValue("Id", out var idToken))
{
var idString = idToken.Value<string>();
if (Int32.TryParse(idString, out parsedId))
{
if (preventDuplicateIdentifiers && previousEntries.FindAll(entry => entry.id == parsedId).Count > 0)
{
Debug.LogError("File contains a duplicate Label Id: " + parsedId);
invalid = true;
}
}
else
{
Debug.LogError("Error parsing Id for Label Entry" + labelEntryJObject +
" from file. Please make sure a string value is provided in the file and that it is convertible to an integer.");
invalid = true;
}
}
else
{
Debug.LogError("Error reading the Id field for Label Entry" + labelEntryJObject +
" from file. Please check the formatting.");
invalid = true;
}
return new IdLabelEntry
{
label = invalid? InvalidLabel : labelString,
id = parsedId
};
}
protected override void AddLabelIdentifierToJson(SerializedProperty labelEntry, JObject jObj)
{
jObj.Add("Id", labelEntry.FindPropertyRelative(nameof(IdLabelEntry.id)).intValue.ToString());
}
protected override void AppendLabelEntryToSerializedArray(SerializedProperty serializedArray,
IdLabelEntry labelEntry)
{

labelProperty.stringValue = labelEntry.label;
}
protected override void ImportLabelEntryListIntoSerializedArray(SerializedProperty serializedArray,
List<IdLabelEntry> labelEntriesToAdd)
{
labelEntriesToAdd = labelEntriesToAdd.OrderBy(entry => entry.id).ToList();
base.ImportLabelEntryListIntoSerializedArray(serializedArray, labelEntriesToAdd);
}
private bool AutoAssign => serializedObject.FindProperty(nameof(IdLabelConfig.autoAssignIds)).boolValue;
public bool AutoAssign => serializedObject.FindProperty(nameof(IdLabelConfig.autoAssignIds)).boolValue;
serializedObject.Update();
var serializedProperty = serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName);
var size = serializedProperty.arraySize;
if (size == 0)

}
serializedObject.ApplyModifiedProperties();
RefreshListDataAndPresenation();
ChangesHappeningInForeground = true;
RefreshListDataAndPresentation();
EditorUtility.SetDirty(target);
}

AutoAssignIds();
}
}
public int IndexOfGivenIdInSerializedLabelsArray(int id)
{
for (int i = 0; i < m_SerializedLabelsArray.arraySize; i++)
{
var element = m_SerializedLabelsArray.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(IdLabelEntry.id));
if (element.intValue == id)
{
return i;
}
}
return -1;
}
}
internal class IdLabelElementInLabelConfig : LabelElementInLabelConfig<IdLabelEntry>

public Label m_LabelId;
public TextField m_LabelIdTextField;
public IdLabelElementInLabelConfig(LabelConfigEditor<IdLabelEntry> editor, SerializedProperty labelsArray) :
base(editor, labelsArray)

protected override void InitExtended()
{
m_LabelId = this.Q<Label>("label-id-value");
m_LabelIdTextField = this.Q<TextField>("label-id-value");
m_LabelIdTextField.isDelayed = true;
m_LabelIdTextField.SetEnabled(!((IdLabelConfigEditor) m_LabelConfigEditor).AutoAssign);
m_LabelIdTextField.RegisterValueChangedCallback(evt =>
{
if(int.TryParse(evt.newValue, out int parsedId))
{
m_LabelsArray.GetArrayElementAtIndex(m_IndexInList).FindPropertyRelative(nameof(IdLabelEntry.id))
.intValue = parsedId;
if (m_LabelsArray.serializedObject.hasModifiedProperties)
{
m_LabelsArray.serializedObject.ApplyModifiedProperties();
m_LabelConfigEditor.ChangesHappeningInForeground = true;
m_LabelConfigEditor.RefreshListDataAndPresentation();
}
int index = ((IdLabelConfigEditor)m_LabelConfigEditor).IndexOfGivenIdInSerializedLabelsArray(parsedId);
if (index != -1 && index != m_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.LogWarning("A label with the ID " + evt.newValue + " has already been added to this label configuration.");
}
}
else
{
Debug.LogError("Provided id is not a valid integer. Please provide integer values.");
m_LabelIdTextField.value = evt.previousValue;
}
});
#endif

288
com.unity.perception/Editor/GroundTruth/LabelConfigEditor.cs


private int m_AddedLabelsItemHeight = 37;
private int m_OtherLabelsItemHeight = 27;
protected abstract LabelConfig<T> TargetLabelConfig { get; }
public List<string> AddedLabels => m_AddedLabels;
private bool m_UiInitialized;
private bool m_EditorHasUi;
private VisualElement m_Root;

protected Button m_MoveUpButton;
protected Button m_MoveDownButton;
protected VisualElement m_MoveButtons;
protected VisualElement m_IdSpecificUi;
protected Toggle m_AutoIdToggle;
m_SerializedLabelsArray = serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName);
m_UiInitialized = false;
ChangesHappeningInForeground = true;
RefreshListDataAndPresentation();
Undo.undoRedoPerformed += () =>
{
ChangesHappeningInForeground = true;
RefreshListDataAndPresentation();
};
}
private 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; }
private 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;
}
private 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_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_SerializedLabelsArray = serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName);
UpdateMoveButtonState();
RefreshAddedLabels();
OnEnableExtended();
InitUiExtended();
UpdateMoveButtonState(null);
m_AddNewLabelButton.clicked += () => { AddNewLabel(m_SerializedLabelsArray, m_AddedLabels); };
m_AddNewLabelButton.clicked += () => { AddNewLabel(m_AddedLabels); };
m_LabelListView.onSelectionChanged += UpdateMoveButtonState;
RefreshListDataAndPresenation();
ChangesHappeningInForeground = true;
RefreshListDataAndPresentation();
};
m_AddAllButton.clicked += () =>

AppendLabelEntryToSerializedArray(m_SerializedLabelsArray, CreateLabelEntryFromLabelString(m_SerializedLabelsArray, label));
}
serializedObject.ApplyModifiedProperties();
RefreshListDataAndPresenation();
ChangesHappeningInForeground = true;
RefreshListDataAndPresentation();
};
m_ImportFromFileButton.clicked += () =>

writer.Close();
}
};
}
protected abstract void OnEnableExtended();
public abstract void PostRemoveOperations();
public override VisualElement CreateInspectorGUI()
{
serializedObject.Update();
RefreshListDataAndPresenation();
return m_Root;
m_Root.schedule.Execute(CheckForModelChanges).Every(30);
}
static void RefreshLabelsMasterList()

return allPaths.Where(path => path.EndsWith(".prefab")).ToList();
}
private void UpdateMoveButtonState()
private void UpdateMoveButtonState(IEnumerable<object> objectList)
m_MoveDownButton.SetEnabled(selectedIndex > -1);
m_MoveUpButton.SetEnabled(selectedIndex > -1);
m_MoveDownButton.SetEnabled(selectedIndex < m_LabelListView.itemsSource.Count - 1);
m_MoveUpButton.SetEnabled(selectedIndex > 0);
public void RefreshListDataAndPresenation()
public void RefreshListDataAndPresentation()
RefreshNonPresentLabels();
m_NonPresentLabelsListView.Refresh();
RefreshListViewHeight();
m_LabelListView.Refresh();
if (m_EditorHasUi && m_UiInitialized)
{
RefreshNonPresentLabels();
m_NonPresentLabelsListView.Refresh();
RefreshListViewHeight();
m_LabelListView.Refresh();
}
UpdateMoveButtonState();
UpdateMoveButtonState(null);
m_Root.schedule.Execute(() => { m_LabelListView.ScrollToItem(-1); })
.StartingIn(

protected void RefreshAddedLabels()
{
m_AddedLabels.Clear();
m_AddedLabels.AddRange(TargetLabelConfig.labelEntries.Select(entry => entry.label));
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()

VisualElement MakeItem()
{
var element = new NonPresentLabelElement<T>(this, m_SerializedLabelsArray);
var element = new NonPresentLabelElement<T>(this);
return element;
}

m_NonPresentLabelsListView.selectionType = SelectionType.None;
}
// public void SetSaveButtonEnabled(bool enabled)
// {
// m_SaveButton.SetEnabled(enabled);
// }
protected void RefreshListViewHeight()
{
m_LabelListView.style.minHeight =

return label;
}
private void AddNewLabel(SerializedProperty serializedArray, List<string> presentLabels)
private void AddNewLabel(List<string> presentLabels)
AddLabel(serializedArray, FindNewLabelString(presentLabels));
AddLabel(FindNewLabelString(presentLabels));
public void AddLabel(SerializedProperty serializedArray, string labelToAdd)
public void AddLabel(string labelToAdd)
AppendLabelEntryToSerializedArray(serializedArray, CreateLabelEntryFromLabelString(serializedArray, labelToAdd));
AppendLabelEntryToSerializedArray(m_SerializedLabelsArray, CreateLabelEntryFromLabelString(m_SerializedLabelsArray, labelToAdd));
RefreshListDataAndPresenation();
ScrollToBottomAndSelectLastItem();
RefreshListDataAndPresentation();
if (m_EditorHasUi)
ScrollToBottomAndSelectLastItem();
protected abstract T CreateLabelEntryFromLabelString(SerializedProperty serializedArray, string labelToAdd);
// Import a list of IdLabelEntry objects to the target object's serialized entries array. This function assumes the labelsToAdd list does not contain any duplicate labels.
protected virtual void ImportLabelEntryListIntoSerializedArray(SerializedProperty serializedArray,
List<T> labelEntriesToAdd)
public void RemoveLabel(string labelToRemove)
serializedArray.ClearArray();
foreach (var entry in labelEntriesToAdd)
var index = IndexOfStringLabelInSerializedLabelsArray(labelToRemove);
if (index >= 0)
AppendLabelEntryToSerializedArray(serializedArray, entry);
m_SerializedLabelsArray.DeleteArrayElementAtIndex(index);
RefreshListDataAndPresenation();
RefreshListDataAndPresentation();
if (m_EditorHasUi)
ScrollToBottomAndSelectLastItem();
protected abstract void AppendLabelEntryToSerializedArray(SerializedProperty serializedArray, T labelEntry);
protected abstract T CreateLabelEntryFromLabelString(SerializedProperty serializedArray, string labelToAdd);
protected abstract T ImportFromJsonExtended(string labelString, JObject jsonObject, List<T> previousEntries, bool preventDuplicateIdentifiers = true);
protected abstract void AppendLabelEntryToSerializedArray(SerializedProperty serializedArray, T labelEntry);
protected const string InvalidLabel = "INVALID_LABEL";
var importedLabelEntries = new List<T>();
if (jsonObj.TryGetValue("LabelEntryType", out var type))
{
if (type.Value<string>() == typeof(T).Name)
{
if (jsonObj.TryGetValue("LabelEntries", out var labelsArrayToken))
{
JArray labelsArray = JArray.Parse(labelsArrayToken.ToString());
if (labelsArray != null)
{
foreach (var labelEntryToken in labelsArray)
{
if (labelEntryToken is JObject entryObject)
{
if (entryObject.TryGetValue("Label", out var labelToken))
{
string labelString = labelToken.Value<string>();
if (importedLabelEntries.FindAll(entry => entry.label == labelString)
.Count > 0)
{
Debug.LogError("File contains a duplicate Label: " + labelString);
return;
}
T labelEntry = ImportFromJsonExtended(labelString, entryObject, importedLabelEntries);
Undo.RegisterCompleteObjectUndo(serializedObject.targetObject, "Import new label config");
JsonUtility.FromJsonOverwrite(jsonObj.ToString(), serializedObject.targetObject);
ChangesHappeningInForeground = true;
RefreshListDataAndPresentation();
if (labelEntry.label == InvalidLabel)
return;
importedLabelEntries.Add(labelEntry);
}
else
{
Debug.LogError("Error reading Label for Label Entry" + labelEntryToken +
" from file. Please check the formatting.");
return;
}
}
else
{
Debug.LogError("Error reading Label Entry " + labelEntryToken +
" from file. Please check the formatting.");
return;
}
}
ImportLabelEntryListIntoSerializedArray(m_SerializedLabelsArray, importedLabelEntries);
}
else
{
Debug.LogError(
"Could not read list of Label Entries from file. Please check the formatting.");
}
}
}
else
{
Debug.LogError("Specified LabelEntryType does not match " + typeof(T).Name);
}
}
else
{
Debug.LogError("LabelEntryType not found.");
}
protected abstract void AddLabelIdentifierToJson(SerializedProperty labelEntry, JObject jObj);
JObject result = new JObject();
result.Add("LabelEntryType", typeof(T).Name);
return JsonUtility.ToJson(serializedObject.targetObject);
}
JArray labelEntries = new JArray();
public int IndexOfStringLabelInSerializedLabelsArray(string label)
{
var entry = m_SerializedLabelsArray.GetArrayElementAtIndex(i);
JObject entryJobj = new JObject();
entryJobj.Add("Label", entry.FindPropertyRelative(nameof(ILabelEntry.label)).stringValue);
AddLabelIdentifierToJson(entry, entryJobj);
labelEntries.Add(entryJobj);
var element = m_SerializedLabelsArray.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(ILabelEntry.label));
if (element.stringValue == label)
{
return i;
}
result.Add("LabelEntries", labelEntries);
return result.ToString();
return -1;
}
}

protected abstract string UxmlPath { get; }
private Button m_RemoveButton;
private Button m_MoveUpButton;
private Button m_MoveDownButton;
public TextField m_LabelTextField;

//protected ListView m_LabelsListView;
protected LabelConfigEditor<T> m_LabelConfigEditor;
protected LabelElementInLabelConfig(LabelConfigEditor<T> editor, SerializedProperty labelsArray)

//m_LabelsListView = labelsListView;
Init();
}

AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(UxmlPath).CloneTree(this);
m_LabelTextField = this.Q<TextField>("label-value");
m_RemoveButton = this.Q<Button>("remove-button");
m_MoveUpButton = this.Q<Button>("move-up-button");
m_MoveDownButton = this.Q<Button>("move-down-button");
m_LabelTextField.isDelayed = true;

{
if (m_LabelConfigEditor.AddedLabels.Contains(cEvent.newValue) && m_LabelConfigEditor.AddedLabels.IndexOf(cEvent.newValue) != m_IndexInList)
int index = m_LabelConfigEditor.IndexOfStringLabelInSerializedLabelsArray(cEvent.newValue);
if (index != -1 && index != m_IndexInList)
//The m_LabelConfigEditor.AddedLabels.IndexOf(cEvent.newValue) != m_IndexInList check is for this purpose.
//The index check is for this purpose.
m_LabelConfigEditor.RefreshListDataAndPresenation();
m_LabelConfigEditor.ChangesHappeningInForeground = true;
m_LabelConfigEditor.RefreshListDataAndPresentation();
return;
}

{
//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.RefreshListDataAndPresenation();
m_LabelConfigEditor.ChangesHappeningInForeground = true;
m_LabelConfigEditor.RefreshListDataAndPresentation();
}
});

m_LabelConfigEditor.PostRemoveOperations();
m_LabelConfigEditor.serializedObject.ApplyModifiedProperties();
m_LabelConfigEditor.RefreshListDataAndPresenation();
m_LabelConfigEditor.ChangesHappeningInForeground = true;
m_LabelConfigEditor.RefreshListDataAndPresentation();
public void UpdateMoveButtonVisibility(SerializedProperty labelsArray)
{
m_MoveDownButton.visible = m_IndexInList != labelsArray.arraySize - 1;
m_MoveUpButton.visible = m_IndexInList != 0;
}
}
class NonPresentLabelElement<T> : VisualElement where T : ILabelEntry

public NonPresentLabelElement(LabelConfigEditor<T> editor, SerializedProperty labelsArray)
public NonPresentLabelElement(LabelConfigEditor<T> editor)
{
var uxmlPath = m_UxmlDir + "SuggestedLabelElement.uxml";
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxmlPath).CloneTree(this);

addButton.clicked += () => { editor.AddLabel(labelsArray, m_Label.text); };
addButton.clicked += () => { editor.AddLabel(m_Label.text); };
}
}
}

80
com.unity.perception/Editor/GroundTruth/LabelingEditor.cs


private VisualElement m_Root;
private VisualElement m_ManualLabelingContainer;
private VisualElement m_AutoLabelingContainer;
private VisualElement m_FromLabelConfigsContainer;
private VisualElement m_SuggestedLabelsContainer;
private ListView m_CurrentLabelsListView;
private ListView m_SuggestLabelsListView_FromName;
private ListView m_SuggestLabelsListView_FromPath;

private Toggle m_AutoLabelingToggle;
private Label m_CurrentAutoLabel;
private Label m_CurrentAutoLabelTitle;
private Label m_AddManualLabelsTitle;
private Labeling m_Labeling;

m_AutoLabelingToggle = m_Root.Q<Toggle>("auto-or-manual-toggle");
m_ManualLabelingContainer = m_Root.Q<VisualElement>("manual-labeling");
m_AutoLabelingContainer = m_Root.Q<VisualElement>("automatic-labeling");
m_FromLabelConfigsContainer = m_Root.Q<VisualElement>("from-label-configs");
m_SuggestedLabelsContainer = m_Root.Q<VisualElement>("suggested-labels");
m_AddManualLabelsTitle = m_Root.Q<Label>("add-manual-labels-title");
m_FirstItemLabelsArray = serializedObject.FindProperty(nameof(Labeling.labels));
if (serializedObject.targetObjects.Length > 1)
{

m_AddAutoLabelToConfButton.clicked += () =>
{
AddToConfigWindow.ShowWindow(CreateUnionOfAllLabels());
AddToConfigWindow.ShowWindow(CreateUnionOfAllLabels().ToList());
};
m_AddButton.clicked += () =>

serializedObject.SetIsDifferentCacheDirty();
}
}
ChangesHappeningInForeground = true;
RefreshManualLabelingData();
};

});
ChangesHappeningInForeground = true;
m_Root.schedule.Execute(CheckForModelChanges).Every(30);
}
private 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; }
private SerializedProperty m_FirstItemLabelsArray;
private void CheckForModelChanges()
{
if (ChangesHappeningInForeground)
{
ChangesHappeningInForeground = false;
m_PreviousLabelsArraySize = m_FirstItemLabelsArray.arraySize;
return;
}
if (m_FirstItemLabelsArray.arraySize != m_PreviousLabelsArraySize)
{
Debug.Log("model checker refreshing");
AssesAutoLabelingStatus();
RefreshManualLabelingData();
m_PreviousLabelsArraySize = m_FirstItemLabelsArray.arraySize;
}
}
private bool SerializedObjectHasValidLabelingScheme(SerializedObject serObj)

m_ManualLabelingContainer.SetEnabled(!m_AutoLabelingToggle.value);
m_AutoLabelingContainer.SetEnabled(m_AutoLabelingToggle.value);
m_AddManualLabelsTitle.style.display = m_AutoLabelingToggle.value ? DisplayStyle.None : DisplayStyle.Flex;
m_FromLabelConfigsContainer.style.display = m_AutoLabelingToggle.value ? DisplayStyle.None : DisplayStyle.Flex;
m_SuggestedLabelsContainer.style.display = m_AutoLabelingToggle.value ? DisplayStyle.None : DisplayStyle.Flex;
m_CurrentLabelsListView.style.minHeight = m_AutoLabelingToggle.value ? 70 : 120;
if (!m_AutoLabelingToggle.value || serializedObject.targetObjects.Length > 1 ||
!SerializedObjectHasValidLabelingScheme(new SerializedObject(serializedObject.targetObjects[0])))
{

{
UpdateUiAspects();
if (m_AutoLabelingToggle.value)
{
// if (serializedObject.targetObjects.Length == 1)
// {
// SyncAutoLabelWithSchemeSingleTarget(true);
// }
}
else
if (!m_AutoLabelingToggle.value)
m_ItIsPossibleToAddMultipleAutoLabelsToConfig = false;
foreach (var targetObj in serializedObject.targetObjects)
{
var serObj = new SerializedObject(targetObj);

serObj.SetIsDifferentCacheDirty();
}
}
ChangesHappeningInForeground = true;
RefreshManualLabelingData();
}

}
UpdateUiAspects();
ChangesHappeningInForeground = true;
RefreshManualLabelingData();
}

m_LabelingSchemesPopup.index =
m_LabelingSchemes.FindIndex(scheme => scheme.GetType().Name.ToString() == unifiedLabelingScheme) + 1;
if (enabledOrNot)
{
//all selected assets have the same scheme recorded in their serialized objects, and they all
//have auto labeling enabled
m_ItIsPossibleToAddMultipleAutoLabelsToConfig = true;
}
m_ItIsPossibleToAddMultipleAutoLabelsToConfig = enabledOrNot;
//if all selected assets have the same scheme recorded in their serialized objects, and they all
//have auto labeling enabled, we can now add all auto labels to a config
}
else
{

//The editor.CommonLabels.IndexOf(cEvent.newValue) != m_IndexInList check is for this purpose.
Debug.LogError("A label with the string " + cEvent.newValue + " has already been added to selected objects.");
editor.ChangesHappeningInForeground = true;
editor.RefreshManualLabelingData();
return;
}

//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)
if (shouldRefresh)
{
editor.ChangesHappeningInForeground = true;
}
});
addToConfigButton.clicked += () =>

editor.serializedObject.SetIsDifferentCacheDirty();
}
}
editor.ChangesHappeningInForeground = true;
editor.RefreshManualLabelingData();
};
}

var uxmlPath = m_UxmlDir + "ConfigElementForAddingLabelsFrom.uxml";
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(uxmlPath).CloneTree(this);
m_LabelsListView = this.Q<ListView>("label-config-contents-listview");
var openButton = this.Q<Button>("open-config-button");
openButton.clicked += () =>
{
Selection.SetActiveObjectWithContext(config, null);
};
var propertyInfo = config.GetType().GetProperty(IdLabelConfig.publicLabelEntriesFieldName);
if (propertyInfo != null)

82
com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs


using UnityEngine;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.UIElements;
using Newtonsoft.Json.Linq;
using Random = UnityEngine.Random;
namespace UnityEditor.Perception.GroundTruth

{
protected override LabelConfig<SemanticSegmentationLabelEntry> TargetLabelConfig => (SemanticSegmentationLabelConfig) serializedObject.targetObject;
protected override void OnEnableExtended()
protected override void InitUiExtended()
m_StartingIdEnumField.style.display = DisplayStyle.None;
m_IdSpecificUi.style.display = DisplayStyle.None;
}
public override void PostRemoveOperations()

.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.label)));
addedLabel.m_ColorField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i)
.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)));
addedLabel.UpdateMoveButtonVisibility(m_SerializedLabelsArray);
}
}

};
}
protected override SemanticSegmentationLabelEntry ImportFromJsonExtended(string labelString, JObject labelEntryJObject,
List<SemanticSegmentationLabelEntry> previousEntries, bool preventDuplicateIdentifiers = true)
{
bool invalid = false;
Color parsedColor = Color.black;
if (labelEntryJObject.TryGetValue("Color", out var colorToken))
{
var colorString = colorToken.Value<string>();
if (ColorUtility.TryParseHtmlString(colorString, out parsedColor))
{
if (preventDuplicateIdentifiers && previousEntries.FindAll(entry => entry.color == parsedColor).Count > 0)
{
Debug.LogError("File contains a duplicate Label Color: " + colorString);
invalid = true;
}
}
else
{
Debug.LogError("Error parsing Color for Label Entry" + labelEntryJObject +
" from file. Please make sure a string value is provided in the file and that it is properly formatted as an HTML color.");
invalid = true;
}
}
else
{
Debug.LogError("Error reading the Color field for Label Entry" + labelEntryJObject +
" from file. Please check the formatting.");
invalid = true;
}
return new SemanticSegmentationLabelEntry
{
label = invalid? InvalidLabel : labelString,
color = parsedColor
};
}
protected override void AddLabelIdentifierToJson(SerializedProperty labelEntry, JObject jObj)
{
jObj.Add("Color", "#"+ColorUtility.ToHtmlStringRGBA(
labelEntry.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)).colorValue));
}
protected override void AppendLabelEntryToSerializedArray(SerializedProperty serializedArray, SemanticSegmentationLabelEntry semanticSegmentationLabelEntry)
{
var index = serializedArray.arraySize;

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 element = m_SerializedLabelsArray.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color));
if (element.colorValue == color)
{
return i;
}
}
return -1;
}
}
internal class ColoredLabelElementInLabelConfig : LabelElementInLabelConfig<SemanticSegmentationLabelEntry>

public ColoredLabelElementInLabelConfig(LabelConfigEditor<SemanticSegmentationLabelEntry> editor, SerializedProperty labelsArray) : base(editor, labelsArray)
{ }
private Color previousColor;
m_ColorField.RegisterValueChangedCallback((cEvent) =>
{
int index = ((SemanticSegmentationLabelConfigEditor)m_LabelConfigEditor).IndexOfGivenColorInSerializedLabelsArray(cEvent.newValue);
if (index != -1 && index != m_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.LogWarning("A label with the chosen color " + cEvent.newValue + " has already been added to this label configuration.");
}
});
}
}
}

7
com.unity.perception/Editor/GroundTruth/Uss/Styles.uss


.labeling__label-listview {
flex-grow: 1;
min-height: 150px;
min-height: 120px;
border-radius: 4px;
margin-right: 2px;
margin-top: 2px;

}
.inner-container {
margin-top: 10px;
margin-top: 5px;
padding: 10px;
padding: 5px;
background-color: #454545;
align-content: flex-start;
}

.title-label {
-unity-font-style: bold;
margin-bottom: 5px;
color: #CACACA;
}

5
com.unity.perception/Editor/GroundTruth/Uxml/AddToConfigWindow.uxml


<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;"/>
<ListView name="current-configs-listview" class="labeling__configs-listview" style="height:150px; margin: 0"/>
<ListView name="current-configs-listview" class="labeling__configs-listview" style="height:150px; margin: 0; max-height:150px"/>
<ListView name="other-configs-listview" class="labeling__configs-listview" style="height:150px; margin: 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>

2
com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementForAddingLabelsFrom.uxml


<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>

1
com.unity.perception/Editor/GroundTruth/Uxml/ConfigElementLabelPresent.uxml


<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>

4
com.unity.perception/Editor/GroundTruth/Uxml/IdLabelElementInLabelConfig.uxml


<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;"/>
<Label name="label-id-value" style="-unity-font-style: bold; color: #888888; min-width : 25px; align-self:center;"/>
<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">

12
com.unity.perception/Editor/GroundTruth/Uxml/LabelConfig_Main.uxml


<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements">
<VisualElement class="outer-container" name="outer-container">
<Style src="../Uss/Styles.uss"/>
<VisualElement style="flex-direction: row; flex-grow: 1; margin-bottom: 5px">
<editor:EnumField label="Starting ID" name="starting-id-dropdown" binding-path="startingLabelId" style="flex-grow:1; margin:0"/>
<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 name="added-labels" class="inner-container" style="margin-top:0px">
<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>
<VisualElement name="other-labels" class="inner-container depth2">
<Label text="Import or Export List" name="added-labels-title" class="title-label"/>
<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"/>

18
com.unity.perception/Editor/GroundTruth/Uxml/Labeling_Main.uxml


</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="">
<VisualElement name="manual-labeling" class="inner-container" style="margin-top:5px">
<ListView name="current-labels-listview" class="labeling__label-listview" style="margin-top: 5px"/>
<ListView name="current-labels-listview" class="labeling__label-listview" style="margin-top: 2px"/>
<!--</VisualElement>
<VisualElement name="add-more-labels" class="inner-container"> -->
<Label text="Add Labels" class="title-label" style = "margin-top:10px"/>
<VisualElement name="from-label-configs" class="inner-container depth2">
<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">
<VisualElement name="add-from-label-configs" style="padding-top: 10px;">
<VisualElement name="add-from-label-configs" style="padding-top: 0px;">
<VisualElement name="suggested-labels-from-name" style="padding-top: 10px;">
<VisualElement name="suggested-labels-from-name" style="padding-top: 5px;">
<VisualElement name="suggested-labels-from-path" style="padding-top: 10px;">
<VisualElement name="suggested-labels-from-path" style="padding-top: 5px;">
<ListView name="suggested-labels-path-listview" class="labeling__label-listview" style="min-height: 97px;"/>
<ListView name="suggested-labels-path-listview" class="labeling__label-listview" style="min-height: 100px;"/>
</VisualElement>
</VisualElement>
</VisualElement>

2
com.unity.perception/Editor/GroundTruth/Uxml/SuggestedLabelElement.uxml


<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"/>
<Button name="add-button" class="labeling__add-to-list-button" text="Add to Labels"/>
</VisualElement>
</UXML>

30
com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs


using System.Diagnostics.CodeAnalysis;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
namespace UnityEngine.Perception.GroundTruth {
/// <summary>

public class IdLabelConfig : LabelConfig<IdLabelEntry>
{
/// <summary>
/// Whether the inspector will auto-assign ids based on the id of the first element.
/// </summary>

public bool TryGetLabelEntryFromInstanceId(uint instanceId, out IdLabelEntry labelEntry)
{
return TryGetLabelEntryFromInstanceId(instanceId, out labelEntry, out var _);
}
/// <summary>
/// Add a string to the list of label entries in this label configuration. The id for this entry will be the
/// maximum id present in the configuration plus one.
/// </summary>
/// <param name="labelToAdd"></param>
public override void AddLabel(string labelToAdd)
{
if (DoesLabelMatchAnEntry(labelToAdd))
return;
int newId = startingLabelId == StartingLabelId.One ? 1 : 0;
if(m_LabelEntries.Count > 0)
newId = m_LabelEntries.Max(entry => entry.id) + 1;
m_LabelEntries.Add(new IdLabelEntry
{
label = labelToAdd,
id = newId
});
if (autoAssignIds)
{
AutoAssignIds();
}
}
/// <summary>

20
com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine.Serialization;
namespace UnityEngine.Perception.GroundTruth

[FormerlySerializedAs("LabelingConfigurations")]
[SerializeField]
protected List<T> m_LabelEntries = new List<T>();
/// <summary>
/// Name of the public accessor for the list of label entries, used for reflection purposes.

}
/// <summary>
/// Name of label removal function with string argument, used for reflection purposes
/// </summary>
public const string RemoveLabelName = nameof(RemoveLabel);
/// <summary>
/// Remove the label entries matching the given string
/// </summary>
/// <param name="label"></param>

}
/// <summary>
/// Name of label adding function with string argument, used for reflection purposes
/// </summary>
public const string AddLabelName = nameof(AddLabel);
/// <summary>
/// To add a label carrying the given string
/// </summary>
/// <param name="label"></param>
public virtual void AddLabel(string label)
{
}
/// <summary>

3
com.unity.perception/Runtime/GroundTruth/Labeling/Labeling.cs


using Unity.Entities;
using UnityEditor;
using UnityEngine.Serialization;
using UnityEngine.UIElements;
namespace UnityEngine.Perception.GroundTruth
{

public class CurrentOrParentsFolderNameLabelingScheme : AssetLabelingScheme
{
///<inheritdoc/>
public override string Description => "Use folder name of asset or its ancestors";
public override string Description => "Use the asset's folder name";
///<inheritdoc/>
public override string GenerateLabel(Object asset)

4
com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs


Color.gray
};
public override void AddLabel(string labelToAdd)
public void AddLabel(string labelToAdd)
m_LabelEntries.Add(new SemanticSegmentationLabelEntry
{
label = labelToAdd,

正在加载...
取消
保存