public SuggestedLabelElement(LabelingEditor 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 += () => { foreach (var targetObject in editor.serializedObject.targetObjects) { if (targetObject is Labeling labeling) { if (labeling.labels.Contains(label.text)) { continue; //Do not allow duplicate labels in one asset. Duplicate labels have no use and cause other operations (especially mutlt asset editing) to get messed up } var serializedLabelingObject2 = new SerializedObject(targetObject); var serializedLabelArray2 = serializedLabelingObject2.FindProperty("labels"); serializedLabelArray2.InsertArrayElementAtIndex(serializedLabelArray2.arraySize); serializedLabelArray2.GetArrayElementAtIndex(serializedLabelArray2.arraySize - 1).stringValue = label.text; serializedLabelingObject2.ApplyModifiedProperties(); serializedLabelingObject2.SetIsDifferentCacheDirty(); editor.serializedObject.SetIsDifferentCacheDirty(); } } editor.ChangesHappeningInForeground = true; editor.RefreshManualLabelingData(); }; }
public LabelConfigElement(LabelingEditor editor, ScriptableObject config) { 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"); var configName = this.Q <Label>("config-name"); configName.text = config.name; m_CollapseToggle = this.Q <VisualElement>("collapse-toggle"); openButton.clicked += () => { Selection.SetActiveObjectWithContext(config, null); }; var propertyInfo = config.GetType().GetProperty(IdLabelConfig.publicLabelEntriesFieldName); if (propertyInfo != null) { var objectList = (IEnumerable)propertyInfo.GetValue(config); var labelEntryList = objectList.Cast <ILabelEntry>().ToList(); var labelList = labelEntryList.Select(entry => entry.label).ToList(); m_LabelsListView.itemsSource = labelList; VisualElement MakeItem() { var element = new SuggestedLabelElement(editor); element.AddToClassList("label_add_from_config"); return(element); } void BindItem(VisualElement e, int i) { if (e is SuggestedLabelElement suggestedLabel) { suggestedLabel.label.text = labelList[i]; } } const int itemHeight = 27; m_LabelsListView.bindItem = BindItem; m_LabelsListView.makeItem = MakeItem; m_LabelsListView.itemHeight = itemHeight; m_LabelsListView.selectionType = SelectionType.None; } m_CollapseToggle.RegisterCallback <MouseUpEvent>(evt => { m_Collapsed = !m_Collapsed; ApplyCollapseState(); }); ApplyCollapseState(); }
///<inheritdoc/> public override string GenerateLabel(UnityEngine.Object asset) { string assetPath = LabelingEditor.GetAssetOrPrefabPath(asset); var stringList = assetPath.Split(LabelingEditor.PathSeparators, StringSplitOptions.RemoveEmptyEntries) .ToList(); return(stringList.Count > 1 ? stringList[stringList.Count - 2] : null); }
public AddedLabelEditor(LabelingEditor editor, ListView listView) { var uxmlPath = m_UxmlDir + "AddedLabelElement.uxml"; AssetDatabase.LoadAssetAtPath <VisualTreeAsset>(uxmlPath).CloneTree(this); labelTextField = this.Q <TextField>("label-value"); var removeButton = this.Q <Button>("remove-button"); var addToConfigButton = this.Q <Button>("add-to-config-button"); labelTextField.isDelayed = true; labelTextField.RegisterValueChangedCallback((cEvent) => { //Do not let the user define a duplicate label if (editor.CommonLabels.Contains(cEvent.newValue) && editor.CommonLabels.IndexOf(cEvent.newValue) != 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 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; } bool shouldRefresh = false; foreach (var targetObject in editor.targets) { if (targetObject is Labeling labeling) { var indexToModifyInTargetLabelList = labeling.labels.IndexOf(editor.CommonLabels[indexInList]); var serializedLabelingObject2 = new SerializedObject(labeling); var serializedLabelArray2 = serializedLabelingObject2.FindProperty(nameof(Labeling.labels)); serializedLabelArray2.GetArrayElementAtIndex(indexToModifyInTargetLabelList).stringValue = cEvent.newValue; shouldRefresh = shouldRefresh || serializedLabelArray2.serializedObject.hasModifiedProperties; serializedLabelingObject2.ApplyModifiedProperties(); serializedLabelingObject2.SetIsDifferentCacheDirty(); } } //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; editor.RefreshManualLabelingData(); } }); addToConfigButton.clicked += () => { AddToConfigWindow.ShowWindow(labelTextField.value); }; removeButton.clicked += () => { List <string> commonLabels = new List <string>(); commonLabels.Clear(); var firstTarget = editor.targets[0] as Labeling; if (firstTarget != null) { commonLabels.AddRange(firstTarget.labels); foreach (var obj in editor.targets) { commonLabels = commonLabels.Intersect(((Labeling)obj).labels).ToList(); } foreach (var targetObject in editor.targets) { if (targetObject is Labeling labeling) { RemoveLabelFromLabelingSerObj(labeling, commonLabels); } } editor.serializedObject.SetIsDifferentCacheDirty(); editor.RefreshManualLabelingData(); } }; }