public void AddTag(Type tagType, float startTime = 0f, float duration = -1f) { if (!Valid) { return; } if (duration < 0) { duration = DurationInSeconds - startTime; } int existing = tags.Count(t => t.Type == tagType && FloatComparer.AreEqual(t.startTime, startTime, FloatComparer.kEpsilon) && FloatComparer.AreEqual(t.duration, duration, FloatComparer.kEpsilon)); if (existing > 0) { return; } Undo.RecordObject(m_Asset, $"Add {TagAttribute.GetDescription(tagType)} tag"); TagAnnotation newTag = TagAnnotation.Create(tagType, startTime, duration); tags.Add(newTag); NotifyChanged(); }
public void RemoveTag(TagAnnotation tag) { Undo.RecordObject(m_Asset, $"Remove {TagAttribute.GetDescription(tag.Type)} tag"); tags.RemoveAll(x => x == tag); tag.Dispose(); TagRemoved?.Invoke(tag); NotifyChanged(); }
static void AddTagMenu(ContextualMenuPopulateEvent evt, Action <DropdownMenuAction> action, DropdownMenuAction.Status menuStatus) { const string prefix = "Add Tag/"; foreach (var tagType in TagAttribute.GetVisibleTypesInInspector()) { evt.menu.AppendAction($"{prefix}{TagAttribute.GetDescription(tagType)}", action, a => menuStatus, tagType); } }
public void AddMarker(MarkerAnnotation marker) { if (!Valid) { return; } Undo.RecordObject(m_Asset, $"Add {TagAttribute.GetDescription(marker.payload.Type)}"); markers.Add(marker); MarkerAdded?.Invoke(marker); NotifyChanged(); }
public void AddTag(TagAnnotation tag) { if (!Valid) { return; } Undo.RecordObject(m_Asset, $"Add {TagAttribute.GetDescription(tag.Type)} tag"); tags.Add(tag); TagAdded?.Invoke(tag); NotifyChanged(); }
public void RemoveTag(Type type) { var matchingTags = tags.Where(t => t.Type == type && FloatComparer.s_ComparerWithDefaultTolerance.Equals(t.startTime, 0f) && FloatComparer.s_ComparerWithDefaultTolerance.Equals(t.duration, Clip.DurationInSeconds)).ToList(); if (matchingTags.Any()) { Undo.RecordObject(m_Asset, $"Remove {matchingTags.Count} {TagAttribute.GetDescription(type)} tag(s)"); foreach (var t in matchingTags) { tags.Remove(t); t.Dispose(); } NotifyChanged(); } }
void BuildAnimationClipItemMenu(ContextualMenuPopulateEvent evt, VisualElement ve) { var clip = ve.userData as TaggedAnimationClip; if (clip == null) { evt.menu.AppendSeparator("Missing Clip"); return; } if (m_AnimationLibraryListView.m_ClipSelection.Count > 0) { if (!m_AnimationLibraryListView.m_ClipSelection.Contains(clip)) { // We can't change the selection of the list from inside a context menu event return; } evt.menu.AppendAction("Delete Selected Clip(s)", action => m_AnimationLibraryListView.DeleteSelection(), DropdownMenuAction.AlwaysEnabled); evt.menu.AppendSeparator(); foreach (var tagType in TagAttribute.GetVisibleTypesInInspector()) { evt.menu.AppendAction($"Tag Selected Clip(s)/{TagAttribute.GetDescription(tagType)}", OnTagSelectionClicked, DropdownMenuAction.AlwaysEnabled, tagType); } evt.menu.AppendAction("Set Boundary Clips", action => BoundaryClipWindow.ShowWindow(m_Asset, m_AnimationLibraryListView.m_ClipSelection)); evt.menu.AppendAction("Experimental - Generate Procedural Annotations", action => m_AnimationLibraryListView.GenerateProceduralAnnotations(), m_AnimationLibraryListView.CanGenerateProceduralAnnotations()); } else { evt.menu.AppendAction("Delete Clip", action => { m_Asset.RemoveClips(new[] { clip }); m_AnimationLibraryListView.Refresh(); }, DropdownMenuAction.AlwaysEnabled); evt.menu.AppendSeparator(); foreach (var tagType in TagAttribute.GetVisibleTypesInInspector()) { evt.menu.AppendAction($"Tag Clip/{TagAttribute.GetDescription(tagType)}", action => clip.AddTag(tagType), DropdownMenuAction.AlwaysEnabled, tagType); } } }
protected override void OnMouseUpEvent(MouseUpEvent evt) { if (!m_Active || !target.HasMouseCapture() || !CanStopManipulation(evt)) { return; } base.OnMouseUpEvent(evt); float distanceFromMouseDown = Math.Abs(evt.mousePosition.x - m_MouseDownPosition.x); if (distanceFromMouseDown >= k_MinDistance && !EditorApplication.isPlaying) { float mouseUpTime = m_Timeline.WorldPositionToTime(evt.mousePosition.x); float startTime = Math.Min(m_MouseDownTime, mouseUpTime); float duration = Math.Max(m_MouseDownTime, mouseUpTime) - startTime; var menu = new GenericMenu(); foreach (Type tagType in TagAttribute.GetVisibleTypesInInspector()) { menu.AddItem(new GUIContent($"{TagAttribute.GetDescription(tagType)}"), false, () => { m_Timeline.OnAddTagSelection(tagType, startTime, duration); }); } menu.DropDown(new Rect(evt.mousePosition, Vector2.zero)); } else { m_Timeline.ReSelectCurrentClip(); } m_Target.style.visibility = Visibility.Hidden; }
internal TagEditor(TagAnnotation tag, TaggedAnimationClip clip) { m_Tag = tag; m_Clip = clip; UIElementsUtils.CloneTemplateInto("Inspectors/TagEditor.uxml", this); UIElementsUtils.ApplyStyleSheet(AnnotationsEditor.k_AnnotationsEditorStyle, this); AddToClassList(AnnotationsEditor.k_AnnotationsContainer); AddToClassList("drawerElement"); var deleteButton = this.Q <Button>("deleteButton"); deleteButton.clickable.clicked += () => { RemoveTag(m_Tag); }; if (!tag.payload.ValidPayloadType) { Clear(); var unknownLabel = new Label { text = TagAttribute.k_UnknownTagType }; unknownLabel.AddToClassList(AnnotationsEditor.k_UnknownAnnotationType); Add(unknownLabel); return; } TextField tagType = this.Q <TextField>("tagType"); tagType.value = TagAttribute.GetDescription(m_Tag.Type); tagType.SetEnabled(false); Asset asset = m_Clip.Asset; TextField tagName = this.Q <TextField>("name"); tagName.value = m_Tag.name; tagName.RegisterValueChangedCallback(evt => { if (!evt.newValue.Equals(m_Tag.name, StringComparison.Ordinal)) { Undo.RecordObject(asset, "Change tag name"); m_Tag.name = evt.newValue; m_Tag.NotifyChanged(); asset.MarkDirty(); } }); TextField metricLabel = this.Q <TextField>("metricLabel"); var metric = asset.GetMetricForTagType(m_Tag.Type); if (metric != null) { metricLabel.value = metric.name; metricLabel.SetEnabled(false); } else { metricLabel.style.display = DisplayStyle.None; } TimeField stf = this.Q <TimeField>("startTime"); stf.Init(m_Clip, m_Tag.startTime); stf.TimeChanged += (newTime) => { if (!EqualityComparer <float> .Default.Equals(m_Tag.startTime, newTime)) { Undo.RecordObject(asset, "Change tag start time"); m_Tag.startTime = newTime; m_Tag.NotifyChanged(); asset.MarkDirty(); } }; TimeField dtf = this.Q <TimeField>("durationTime"); dtf.Init(m_Clip, m_Tag.duration); dtf.TimeChanged += (newTime) => { if (!EqualityComparer <float> .Default.Equals(m_Tag.duration, newTime)) { Undo.RecordObject(asset, "Change tag duration"); m_Tag.duration = newTime; m_Tag.NotifyChanged(); asset.MarkDirty(); } }; var so = m_Tag.payload.ScriptableObject; if (so != null) { m_PayloadInspector = UnityEditor.Editor.CreateEditor(so) as GenericStructInspector; m_PayloadInspector.StructModified += () => { m_Tag.payload.Serialize(); m_Tag.NotifyChanged(); m_Clip.Asset.MarkDirty(); }; VisualElement inspectorElement = m_PayloadInspector.CreateInspectorGUI() ?? new IMGUIContainer(m_PayloadInspector.OnInspectorGUI); var inspectorContainer = this.Q <VisualElement>("payloadInspector"); inspectorContainer.Add(inspectorElement); } RegisterCallback <DetachFromPanelEvent>(OnDetachFromPanel); m_Tag.Changed += Refresh; asset.AssetWasDeserialized += Refresh; }