123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- using System.Collections.Generic;
- using UnityEditor.Experimental.GraphView;
- using UnityEngine;
- using UnityEngine.UIElements;
- using UnityEditor.ShaderGraph.Drawing.Interfaces;
-
- namespace UnityEditor.ShaderGraph.Drawing
- {
- class StickyNodeChangeEvent : EventBase<StickyNodeChangeEvent>
- {
- public static StickyNodeChangeEvent GetPooled(StickyNote target, Change change)
- {
- var evt = GetPooled();
- evt.target = target;
- evt.change = change;
- return evt;
- }
-
- public enum Change
- {
- title,
- contents,
- theme,
- textSize,
- }
-
- public Change change { get; protected set; }
- }
-
- class StickyNote : GraphElement, ISGResizable
- {
- GraphData m_Graph;
- public new StickyNoteData userData
- {
- get => (StickyNoteData)base.userData;
- set => base.userData = value;
- }
-
- public enum Theme
- {
- Classic,
- Black,
- Orange,
- Green,
- Blue,
- Red,
- Purple,
- Teal
- }
-
- Theme m_Theme = Theme.Classic;
- public Theme theme
- {
- get
- {
- return m_Theme;
- }
- set
- {
- if (m_Theme != value)
- {
- m_Theme = value;
- UpdateThemeClasses();
- }
- }
- }
-
- public enum TextSize
- {
- Small,
- Medium,
- Large,
- Huge
- }
-
- TextSize m_TextSize = TextSize.Medium;
-
- public TextSize textSize
- {
- get { return m_TextSize; }
- set
- {
- if (m_TextSize != value)
- {
- m_TextSize = value;
- UpdateSizeClasses();
- }
- }
- }
-
- public virtual void OnStartResize()
- {
- }
-
- public virtual void OnResized()
- {
- userData.position = new Rect(resolvedStyle.left, resolvedStyle.top, style.width.value.value, style.height.value.value);
- }
-
- public bool CanResizePastParentBounds()
- {
- return true;
- }
-
- Vector2 AllExtraSpace(VisualElement element)
- {
- return new Vector2(
- element.resolvedStyle.marginLeft + element.resolvedStyle.marginRight + element.resolvedStyle.paddingLeft + element.resolvedStyle.paddingRight + element.resolvedStyle.borderRightWidth + element.resolvedStyle.borderLeftWidth,
- element.resolvedStyle.marginTop + element.resolvedStyle.marginBottom + element.resolvedStyle.paddingTop + element.resolvedStyle.paddingBottom + element.resolvedStyle.borderBottomWidth + element.resolvedStyle.borderTopWidth
- );
- }
-
- void OnFitToText(DropdownMenuAction a)
- {
- FitText(false);
- }
-
- public void FitText(bool onlyIfSmaller)
- {
- Vector2 preferredTitleSize = Vector2.zero;
- if (!string.IsNullOrEmpty(m_Title.text))
- preferredTitleSize = m_Title.MeasureTextSize(m_Title.text, 0, MeasureMode.Undefined, 0, MeasureMode.Undefined); // This is the size of the string with the current title font and such
-
- preferredTitleSize += AllExtraSpace(m_Title);
- preferredTitleSize.x += m_Title.ChangeCoordinatesTo(this, Vector2.zero).x + resolvedStyle.width - m_Title.ChangeCoordinatesTo(this, new Vector2(m_Title.layout.width, 0)).x;
-
- Vector2 preferredContentsSizeOneLine = m_Contents.MeasureTextSize(m_Contents.text, 0, MeasureMode.Undefined, 0, MeasureMode.Undefined);
-
- Vector2 contentExtraSpace = AllExtraSpace(m_Contents);
- preferredContentsSizeOneLine += contentExtraSpace;
-
- Vector2 extraSpace = new Vector2(resolvedStyle.width, resolvedStyle.height) - m_Contents.ChangeCoordinatesTo(this, new Vector2(m_Contents.layout.width, m_Contents.layout.height));
- extraSpace += m_Title.ChangeCoordinatesTo(this, Vector2.zero);
- preferredContentsSizeOneLine += extraSpace;
-
- float width = 0;
- float height = 0;
- // The content in one line is smaller than the current width.
- // Set the width to fit both title and content.
- // Set the height to have only one line in the content
- if (preferredContentsSizeOneLine.x < Mathf.Max(preferredTitleSize.x, resolvedStyle.width))
- {
- width = Mathf.Max(preferredContentsSizeOneLine.x, preferredTitleSize.x);
- height = preferredContentsSizeOneLine.y + preferredTitleSize.y;
- }
- else // The width is not enough for the content: keep the width or use the title width if bigger.
- {
- width = Mathf.Max(preferredTitleSize.x + extraSpace.x, resolvedStyle.width);
- float contextWidth = width - extraSpace.x - contentExtraSpace.x;
- Vector2 preferredContentsSize = m_Contents.MeasureTextSize(m_Contents.text, contextWidth, MeasureMode.Exactly, 0, MeasureMode.Undefined);
-
- preferredContentsSize += contentExtraSpace;
-
- height = preferredTitleSize.y + preferredContentsSize.y + extraSpace.y;
- }
- if (!onlyIfSmaller || resolvedStyle.width < width)
- style.width = width;
- if (!onlyIfSmaller || resolvedStyle.height < height)
- style.height = height;
- OnResized();
- }
-
- void UpdateThemeClasses()
- {
- foreach (Theme value in System.Enum.GetValues(typeof(Theme)))
- {
- if (m_Theme != value)
- {
- RemoveFromClassList("theme-" + value.ToString().ToLower());
- }
- else
- {
- AddToClassList("theme-" + value.ToString().ToLower());
- }
- }
- }
-
- void UpdateSizeClasses()
- {
- foreach (TextSize value in System.Enum.GetValues(typeof(TextSize)))
- {
- if (m_TextSize != value)
- {
- RemoveFromClassList("size-" + value.ToString().ToLower());
- }
- else
- {
- AddToClassList("size-" + value.ToString().ToLower());
- }
- }
- }
-
- public static readonly Vector2 defaultSize = new Vector2(200, 160);
-
- public StickyNote(Rect position, GraphData graph) : this("UXML/StickyNote", position, graph)
- {
- styleSheets.Add(Resources.Load<StyleSheet>("Selectable"));
- styleSheets.Add(Resources.Load<StyleSheet>("StickyNote"));
- RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);
- }
-
- public string displayName => $"{m_Title.text} (Sticky Note)";
-
- public StickyNote(string uiFile, Rect position, GraphData graph)
- {
- m_Graph = graph;
- var tpl = Resources.Load<VisualTreeAsset>(uiFile);
-
- tpl.CloneTree(this);
-
- capabilities = Capabilities.Movable | Capabilities.Deletable | Capabilities.Ascendable | Capabilities.Selectable | Capabilities.Copiable | Capabilities.Groupable;
-
- m_Title = this.Q<Label>(name: "title");
- if (m_Title != null)
- {
- m_Title.RegisterCallback<MouseDownEvent>(OnTitleMouseDown);
- }
-
- m_TitleField = this.Q<TextField>(name: "title-field");
- if (m_TitleField != null)
- {
- m_TitleField.style.display = DisplayStyle.None;
- m_TitleField.Q("unity-text-input").RegisterCallback<BlurEvent>(OnTitleBlur, TrickleDown.TrickleDown);
- m_TitleField.RegisterCallback<ChangeEvent<string>>(OnTitleChange);
- }
-
- m_Contents = this.Q<Label>(name: "contents");
- if (m_Contents != null)
- {
- m_ContentsField = m_Contents.Q<TextField>(name: "contents-field");
- if (m_ContentsField != null)
- {
- m_ContentsField.style.display = DisplayStyle.None;
- m_ContentsField.multiline = true;
- m_ContentsField.Q("unity-text-input").RegisterCallback<BlurEvent>(OnContentsBlur, TrickleDown.TrickleDown);
- }
- m_Contents.RegisterCallback<MouseDownEvent>(OnContentsMouseDown);
- }
-
- SetPosition(new Rect(position.x, position.y, defaultSize.x, defaultSize.y));
-
- AddToClassList("sticky-note");
- AddToClassList("selectable");
- UpdateThemeClasses();
- UpdateSizeClasses();
- // Manually set the layer of the sticky note so it's always on top. This used to be in the uss
- // but that causes issues with re-laying out at times that can do weird things to selection.
- this.layer = -100;
-
- this.AddManipulator(new ContextualMenuManipulator(BuildContextualMenu));
- }
-
- public void BuildContextualMenu(ContextualMenuPopulateEvent evt)
- {
- if (evt.target is StickyNote)
- {
- /*foreach (Theme value in System.Enum.GetValues(typeof(Theme)))
- {
- evt.menu.AppendAction("Theme/" + value.ToString(), OnChangeTheme, e => DropdownMenu.MenuAction.StatusFlags.Normal, value);
- }*/
- if (theme == Theme.Black)
- evt.menu.AppendAction("Light Theme", OnChangeTheme, e => DropdownMenuAction.Status.Normal, Theme.Classic);
- else
- evt.menu.AppendAction("Dark Theme", OnChangeTheme, e => DropdownMenuAction.Status.Normal, Theme.Black);
- evt.menu.AppendSeparator();
- foreach (TextSize value in System.Enum.GetValues(typeof(TextSize)))
- {
- evt.menu.AppendAction(value.ToString() + " Text Size", OnChangeSize, e => DropdownMenuAction.Status.Normal, value);
- }
- evt.menu.AppendSeparator();
-
- evt.menu.AppendAction("Fit To Text", OnFitToText, e => DropdownMenuAction.Status.Normal);
- evt.menu.AppendSeparator();
-
- evt.menu.AppendAction("Delete", OnDelete, e => DropdownMenuAction.Status.Normal);
- evt.menu.AppendSeparator();
- }
- }
-
- void OnDelete(DropdownMenuAction menuAction)
- {
- m_Graph.owner.RegisterCompleteObjectUndo("Delete Sticky Note");
- m_Graph.RemoveStickyNote(userData);
- }
-
- void OnTitleChange(EventBase e)
- {
- //m_Graph.owner.RegisterCompleteObjectUndo("Title Changed");
- //title = m_TitleField.value;
- //userData.title = title;
- }
-
- public PropertySheet GetInspectorContent()
- {
- var sheet = new PropertySheet();
- return sheet;
- }
-
- const string fitTextClass = "fit-text";
-
- public override void SetPosition(Rect rect)
- {
- style.left = rect.x;
- style.top = rect.y;
- style.width = rect.width;
- style.height = rect.height;
- }
-
- public override Rect GetPosition()
- {
- return new Rect(resolvedStyle.left, resolvedStyle.top, resolvedStyle.width, resolvedStyle.height);
- }
-
- public string contents
- {
- get { return m_Contents.text; }
- set
- {
- if (m_Contents != null)
- {
- m_Contents.text = value;
- }
- }
- }
- public new string title
- {
- get { return m_Title.text; }
- set
- {
- if (m_Title != null)
- {
- m_Title.text = value;
-
- if (!string.IsNullOrEmpty(m_Title.text))
- {
- m_Title.RemoveFromClassList("empty");
- }
- else
- {
- m_Title.AddToClassList("empty");
- }
- //UpdateTitleHeight();
- }
- }
- }
-
- void OnChangeTheme(DropdownMenuAction action)
- {
- theme = (Theme)action.userData;
- NotifyChange(StickyNodeChangeEvent.Change.theme);
- }
-
- void OnChangeSize(DropdownMenuAction action)
- {
- textSize = (TextSize)action.userData;
- NotifyChange(StickyNodeChangeEvent.Change.textSize);
- //panel.InternalValidateLayout();
-
- FitText(true);
- }
-
- void OnAttachToPanel(AttachToPanelEvent e)
- {
- //UpdateTitleHeight();
- }
-
- void OnTitleBlur(BlurEvent e)
- {
- //bool changed = m_Title.text != m_TitleField.value;
- title = m_TitleField.value;
- m_TitleField.style.display = DisplayStyle.None;
-
- m_Title.UnregisterCallback<GeometryChangedEvent>(OnTitleRelayout);
-
- //Notify change
- //if( changed)
- {
- NotifyChange(StickyNodeChangeEvent.Change.title);
- }
- }
-
- void OnContentsBlur(BlurEvent e)
- {
- bool changed = m_Contents.text != m_ContentsField.value;
- m_Contents.text = m_ContentsField.value;
- m_ContentsField.style.display = DisplayStyle.None;
-
- //Notify change
- if (changed)
- {
- NotifyChange(StickyNodeChangeEvent.Change.contents);
- }
- }
-
- void OnTitleRelayout(GeometryChangedEvent e)
- {
- UpdateTitleFieldRect();
- }
-
- void UpdateTitleFieldRect()
- {
- Rect rect = m_Title.layout;
- m_Title.parent.ChangeCoordinatesTo(m_TitleField.parent, rect);
-
- m_TitleField.style.left = rect.xMin - 1;
- m_TitleField.style.right = rect.yMin + m_Title.resolvedStyle.marginTop;
- m_TitleField.style.width = rect.width - m_Title.resolvedStyle.marginLeft - m_Title.resolvedStyle.marginRight;
- m_TitleField.style.height = rect.height - m_Title.resolvedStyle.marginTop - m_Title.resolvedStyle.marginBottom;
- }
-
- void OnTitleMouseDown(MouseDownEvent e)
- {
- if (e.clickCount == 2)
- {
- m_TitleField.RemoveFromClassList("empty");
- m_TitleField.value = m_Title.text;
- m_TitleField.style.display = DisplayStyle.Flex;
- UpdateTitleFieldRect();
- m_Title.RegisterCallback<GeometryChangedEvent>(OnTitleRelayout);
-
- m_TitleField.Q("unity-text-input").Focus();
- m_TitleField.SelectAll();
-
- e.StopPropagation();
- focusController.IgnoreEvent(e);
- }
- }
-
- void NotifyChange(StickyNodeChangeEvent.Change change)
- {
- m_Graph.owner.RegisterCompleteObjectUndo($"Change Sticky Note {change.ToString()}");
- if (change == StickyNodeChangeEvent.Change.title)
- {
- userData.title = title;
- }
- else if (change == StickyNodeChangeEvent.Change.contents)
- {
- userData.content = contents;
- }
- else if (change == StickyNodeChangeEvent.Change.textSize)
- {
- userData.textSize = (int)textSize;
- }
- else if (change == StickyNodeChangeEvent.Change.theme)
- {
- userData.theme = (int)theme;
- }
- }
-
- public System.Action<StickyNodeChangeEvent.Change> OnChange;
-
- void OnContentsMouseDown(MouseDownEvent e)
- {
- if (e.clickCount == 2)
- {
- m_ContentsField.value = m_Contents.text;
- m_ContentsField.style.display = DisplayStyle.Flex;
- m_ContentsField.Q("unity-text-input").Focus();
- e.StopPropagation();
- focusController.IgnoreEvent(e);
- }
- }
-
- Label m_Title;
- protected TextField m_TitleField;
- Label m_Contents;
- protected TextField m_ContentsField;
- }
- }
|