123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915 |
- using UnityEngine;
- using System.Collections.Generic;
- using System;
- using System.Linq;
-
- namespace UnityEditor.U2D.Sprites
- {
- // We need this so that undo/redo works
- [Serializable]
- internal class SpriteOutline
- {
- [SerializeField]
- public List<Vector2> m_Path = new List<Vector2>();
-
- public void Add(Vector2 point)
- {
- m_Path.Add(point);
- }
-
- public void Insert(int index, Vector2 point)
- {
- m_Path.Insert(index, point);
- }
-
- public void RemoveAt(int index)
- {
- m_Path.RemoveAt(index);
- }
-
- public Vector2 this[int index]
- {
- get { return m_Path[index]; }
- set { m_Path[index] = value; }
- }
-
- public int Count
- {
- get { return m_Path.Count; }
- }
-
- public void AddRange(IEnumerable<Vector2> addRange)
- {
- m_Path.AddRange(addRange);
- }
- }
-
- // Collection of outlines for a single Sprite
- [Serializable]
- internal class SpriteOutlineList
- {
- [SerializeField]
- List<SpriteOutline> m_SpriteOutlines = new List<SpriteOutline>();
- [SerializeField]
- float m_TessellationDetail = 0;
-
- public List<SpriteOutline> spriteOutlines { get { return m_SpriteOutlines; } set { m_SpriteOutlines = value; } }
- public GUID spriteID { get; private set; }
-
- public float tessellationDetail
- {
- get { return m_TessellationDetail; }
- set
- {
- m_TessellationDetail = value;
- m_TessellationDetail = Mathf.Min(1, m_TessellationDetail);
- m_TessellationDetail = Mathf.Max(0, m_TessellationDetail);
- }
- }
-
- public SpriteOutlineList(GUID guid)
- {
- this.spriteID = guid;
- m_SpriteOutlines = new List<SpriteOutline>();
- }
-
- public SpriteOutlineList(GUID guid, List<Vector2[]> list)
- {
- this.spriteID = guid;
-
- m_SpriteOutlines = new List<SpriteOutline>(list.Count);
- for (int i = 0; i < list.Count; ++i)
- {
- var newList = new SpriteOutline();
- newList.m_Path.AddRange(list[i]);
- m_SpriteOutlines.Add(newList);
- }
- }
-
- public SpriteOutlineList(GUID guid, List<SpriteOutline> list)
- {
- this.spriteID = guid;
-
- m_SpriteOutlines = list;
- }
-
- public List<Vector2[]> ToListVector()
- {
- var value = new List<Vector2[]>(m_SpriteOutlines.Count);
- foreach (var s in m_SpriteOutlines)
- {
- value.Add(s.m_Path.ToArray());
- }
- return value;
- }
-
- public List<Vector2[]> ToListVectorCapped(Rect rect)
- {
- var value = ToListVector();
- rect.center = Vector2.zero;
- foreach (var path in value)
- {
- for (int i = 0; i < path.Length; ++i)
- {
- var point = path[i];
- path[i] = SpriteOutlineModule.CapPointToRect(point, rect);;
- }
- }
- return value;
- }
-
- public SpriteOutline this[int index]
- {
- get { return IsValidIndex(index) ? m_SpriteOutlines[index] : null; }
- set
- {
- if (IsValidIndex(index))
- m_SpriteOutlines[index] = value;
- }
- }
-
- public static implicit operator List<SpriteOutline>(SpriteOutlineList list)
- {
- return list != null ? list.m_SpriteOutlines : null;
- }
-
- public int Count { get { return m_SpriteOutlines.Count; } }
-
- bool IsValidIndex(int index)
- {
- return index >= 0 && index < Count;
- }
- }
-
- // Collection of Sprites' outlines
- internal class SpriteOutlineModel : ScriptableObject
- {
- [SerializeField]
- List<SpriteOutlineList> m_SpriteOutlineList = new List<SpriteOutlineList>();
-
- private SpriteOutlineModel()
- {}
-
- public SpriteOutlineList this[int index]
- {
- get { return IsValidIndex(index) ? m_SpriteOutlineList[index] : null; }
- set
- {
- if (IsValidIndex(index))
- m_SpriteOutlineList[index] = value;
- }
- }
-
- public SpriteOutlineList this[GUID guid]
- {
- get { return m_SpriteOutlineList.FirstOrDefault(x => x.spriteID == guid); }
- set
- {
- var index = m_SpriteOutlineList.FindIndex(x => x.spriteID == guid);
- if (index != -1)
- m_SpriteOutlineList[index] = value;
- }
- }
-
- public void AddListVector2(GUID guid, List<Vector2[]> outline)
- {
- m_SpriteOutlineList.Add(new SpriteOutlineList(guid, outline));
- }
-
- public int Count { get { return m_SpriteOutlineList.Count; } }
-
- bool IsValidIndex(int index)
- {
- return index >= 0 && index < Count;
- }
- }
-
- [RequireSpriteDataProvider(typeof(ISpriteOutlineDataProvider), typeof(ITextureDataProvider))]
- internal class SpriteOutlineModule : SpriteEditorModuleBase
- {
- class Styles
- {
- public GUIContent generateOutlineLabel = EditorGUIUtility.TrTextContent("Generate", "Generate new outline based on mesh detail value.");
- public GUIContent outlineTolerance = EditorGUIUtility.TrTextContent("Outline Tolerance", "Sets how tight the outline should be from the sprite.");
- public GUIContent snapButtonLabel = EditorGUIUtility.TrTextContent("Snap", "Snap points to nearest pixel");
-
- public GUIContent copyButtonLabel = EditorGUIUtility.TrTextContent("Copy", "Copy outline from Sprite");
- public GUIContent pasteButtonLabel = EditorGUIUtility.TrTextContent("Paste", "Paste outline to Sprite");
- public GUIContent pasteAllButtonLabel = EditorGUIUtility.TrTextContent("Paste All", "Paste outline to all Sprites");
-
- public GUIContent generatingOutlineDialogTitle = EditorGUIUtility.TrTextContent("Outline");
- public GUIContent generatingOutlineDialogContent = EditorGUIUtility.TrTextContent("Generating outline {0}/{1}");
- public Color spriteBorderColor = new Color(0.25f, 0.5f, 1f, 0.75f);
- }
-
- protected SpriteRect m_Selected;
-
- private const float k_HandleSize = 5f;
- private readonly string k_DeleteCommandName = EventCommandNames.Delete;
- private readonly string k_SoftDeleteCommandName = EventCommandNames.SoftDelete;
-
- private ShapeEditor[] m_ShapeEditors;
- private bool m_RequestRepaint;
- private Matrix4x4 m_HandleMatrix;
- private Vector2 m_MousePosition;
- private bool m_Snap = true;
- private ShapeEditorRectSelectionTool m_ShapeSelectionUI;
- private bool m_WasRectSelecting = false;
- private Rect? m_SelectionRect;
- private ITexture2D m_OutlineTexture;
- private Styles m_Styles;
- protected SpriteOutlineModel m_Outline;
- private SpriteOutlineList m_CopyOutline = null;
- protected ITextureDataProvider m_TextureDataProvider;
-
- public SpriteOutlineModule(ISpriteEditor sem, IEventSystem es, IUndoSystem us, IAssetDatabase ad, IGUIUtility gu, IShapeEditorFactory sef, ITexture2D outlineTexture)
- {
- spriteEditorWindow = sem;
- undoSystem = us;
- eventSystem = es;
- assetDatabase = ad;
- guiUtility = gu;
- shapeEditorFactory = sef;
- m_OutlineTexture = outlineTexture;
-
- m_ShapeSelectionUI = new ShapeEditorRectSelectionTool(gu);
-
- m_ShapeSelectionUI.RectSelect += RectSelect;
- m_ShapeSelectionUI.ClearSelection += ClearSelection;
- }
-
- public override string moduleName
- {
- get { return "Custom Outline"; }
- }
-
- public override bool ApplyRevert(bool apply)
- {
- if (m_Outline != null)
- {
- if (apply)
- {
- var outlineDataProvider = spriteEditorWindow.GetDataProvider<ISpriteOutlineDataProvider>();
- for (int i = 0; i < m_Outline.Count; ++i)
- {
- outlineDataProvider.SetOutlines(m_Outline[i].spriteID, m_Outline[i].ToListVector());
- outlineDataProvider.SetTessellationDetail(m_Outline[i].spriteID, m_Outline[i].tessellationDetail);
- }
- }
-
- ScriptableObject.DestroyImmediate(m_Outline);
- m_Outline = null;
- }
-
- return true;
- }
-
- private Styles styles
- {
- get
- {
- if (m_Styles == null)
- m_Styles = new Styles();
- return m_Styles;
- }
- }
-
- protected virtual List<SpriteOutline> selectedShapeOutline
- {
- get
- {
- return m_Outline[m_Selected.spriteID].spriteOutlines;
- }
- set
- {
- m_Outline[m_Selected.spriteID].spriteOutlines = value;
- }
- }
-
- private bool shapeEditorDirty
- {
- get; set;
- }
-
- private bool editingDisabled
- {
- get { return spriteEditorWindow.editingDisabled; }
- }
-
- private ISpriteEditor spriteEditorWindow
- {
- get; set;
- }
-
- private IUndoSystem undoSystem
- {
- get; set;
- }
-
- private IEventSystem eventSystem
- {
- get; set;
- }
-
- private IAssetDatabase assetDatabase
- {
- get; set;
- }
-
- private IGUIUtility guiUtility
- {
- get; set;
- }
-
- private IShapeEditorFactory shapeEditorFactory
- {
- get; set;
- }
-
- private void RectSelect(Rect r, ShapeEditor.SelectionType selectionType)
- {
- var localRect = EditorGUIExt.FromToRect(ScreenToLocal(r.min), ScreenToLocal(r.max));
- m_SelectionRect = localRect;
- }
-
- private void ClearSelection()
- {
- m_RequestRepaint = true;
- }
-
- protected virtual void LoadOutline()
- {
- m_Outline = ScriptableObject.CreateInstance<SpriteOutlineModel>();
- m_Outline.hideFlags = HideFlags.HideAndDontSave;
- var spriteDataProvider = spriteEditorWindow.GetDataProvider<ISpriteEditorDataProvider>();
- var outlineDataProvider = spriteEditorWindow.GetDataProvider<ISpriteOutlineDataProvider>();
- foreach (var rect in spriteDataProvider.GetSpriteRects())
- {
- var outlines = outlineDataProvider.GetOutlines(rect.spriteID);
- m_Outline.AddListVector2(rect.spriteID, outlines);
- m_Outline[m_Outline.Count - 1].tessellationDetail = outlineDataProvider.GetTessellationDetail(rect.spriteID);
- }
- }
-
- public override void OnModuleActivate()
- {
- m_TextureDataProvider = spriteEditorWindow.GetDataProvider<ITextureDataProvider>();
- LoadOutline();
- GenerateOutlineIfNotExist();
- undoSystem.RegisterUndoCallback(UndoRedoPerformed);
- shapeEditorDirty = true;
- SetupShapeEditor();
- spriteEditorWindow.enableMouseMoveEvent = true;
- }
-
- void GenerateOutlineIfNotExist()
- {
- var rectCache = spriteEditorWindow.GetDataProvider<ISpriteEditorDataProvider>().GetSpriteRects();
- if (rectCache != null)
- {
- bool needApply = false;
- for (int i = 0; i < rectCache.Length; ++i)
- {
- var rect = rectCache[i];
- if (!HasShapeOutline(rect))
- {
- EditorUtility.DisplayProgressBar(styles.generatingOutlineDialogTitle.text,
- string.Format(styles.generatingOutlineDialogContent.text, i + 1 , rectCache.Length),
- (float)(i) / rectCache.Length);
-
- SetupShapeEditorOutline(rect);
- needApply = true;
- }
- }
- if (needApply)
- {
- EditorUtility.ClearProgressBar();
- spriteEditorWindow.ApplyOrRevertModification(true);
- LoadOutline();
- }
- }
- }
-
- public override void OnModuleDeactivate()
- {
- undoSystem.UnregisterUndoCallback(UndoRedoPerformed);
- CleanupShapeEditors();
- m_Selected = null;
- spriteEditorWindow.enableMouseMoveEvent = false;
- if (m_Outline != null)
- {
- undoSystem.ClearUndo(m_Outline);
- ScriptableObject.DestroyImmediate(m_Outline);
- m_Outline = null;
- }
- }
-
- public override void DoMainGUI()
- {
- IEvent evt = eventSystem.current;
-
- m_RequestRepaint = false;
- m_HandleMatrix = Handles.matrix;
-
- m_MousePosition = Handles.inverseMatrix.MultiplyPoint(eventSystem.current.mousePosition);
- if (m_Selected == null || !m_Selected.rect.Contains(m_MousePosition) && !IsMouseOverOutlinePoints() && evt.shift == false)
- spriteEditorWindow.HandleSpriteSelection();
-
- HandleCreateNewOutline();
-
- m_WasRectSelecting = m_ShapeSelectionUI.isSelecting;
-
- UpdateShapeEditors();
-
- m_ShapeSelectionUI.OnGUI();
-
- DrawGizmos();
-
- if (m_RequestRepaint || evt.type == EventType.MouseMove)
- spriteEditorWindow.RequestRepaint();
- }
-
- public override void DoToolbarGUI(Rect drawArea)
- {
- var style = styles;
-
- Rect snapDrawArea = new Rect(drawArea.x, drawArea.y, EditorStyles.toolbarButton.CalcSize(style.snapButtonLabel).x, drawArea.height);
- m_Snap = GUI.Toggle(snapDrawArea, m_Snap, style.snapButtonLabel, EditorStyles.toolbarButton);
-
- using (new EditorGUI.DisabledScope(editingDisabled || m_Selected == null))
- {
- float totalWidth = drawArea.width - snapDrawArea.width;
- drawArea.x = snapDrawArea.xMax;
- drawArea.width = EditorStyles.toolbarButton.CalcSize(style.outlineTolerance).x;
- totalWidth -= drawArea.width;
- if (totalWidth < 0)
- drawArea.width += totalWidth;
- if (drawArea.width > 0)
- GUI.Label(drawArea, style.outlineTolerance, EditorStyles.miniLabel);
- drawArea.x += drawArea.width;
-
- drawArea.width = 100;
- totalWidth -= drawArea.width;
- if (totalWidth < 0)
- drawArea.width += totalWidth;
-
- if (drawArea.width > 0)
- {
- float tesselationValue = m_Selected != null ? m_Outline[m_Selected.spriteID].tessellationDetail : 0;
- EditorGUI.BeginChangeCheck();
- float oldFieldWidth = EditorGUIUtility.fieldWidth;
- float oldLabelWidth = EditorGUIUtility.labelWidth;
- EditorGUIUtility.fieldWidth = 35;
- EditorGUIUtility.labelWidth = 1;
- tesselationValue = EditorGUI.Slider(drawArea, Mathf.Clamp01(tesselationValue), 0, 1);
- if (EditorGUI.EndChangeCheck())
- {
- RecordUndo();
- m_Outline[m_Selected.spriteID].tessellationDetail = tesselationValue;
- }
- EditorGUIUtility.fieldWidth = oldFieldWidth;
- EditorGUIUtility.labelWidth = oldLabelWidth;
- }
-
- drawArea.x += drawArea.width + 2;
- drawArea.width = EditorStyles.toolbarButton.CalcSize(style.generateOutlineLabel).x;
- totalWidth -= drawArea.width;
- if (totalWidth < 0)
- drawArea.width += totalWidth;
-
- if (drawArea.width > 0 && GUI.Button(drawArea, style.generateOutlineLabel, EditorStyles.toolbarButton))
- {
- RecordUndo();
- selectedShapeOutline.Clear();
- SetupShapeEditorOutline(m_Selected);
- spriteEditorWindow.SetDataModified();
- shapeEditorDirty = true;
- }
-
- using (new EditorGUI.DisabledScope(m_Selected == null || !HasShapeOutline(m_Selected)))
- {
- drawArea.x += drawArea.width + 2;
- drawArea.width = EditorStyles.toolbarButton.CalcSize(style.copyButtonLabel).x;
- totalWidth -= drawArea.width;
- if (totalWidth < 0)
- drawArea.width += totalWidth;
-
- if (drawArea.width > 0 && GUI.Button(drawArea, style.copyButtonLabel, EditorStyles.toolbarButton))
- {
- Copy();
- }
- }
-
- using (new EditorGUI.DisabledScope(m_Selected == null || m_CopyOutline == null))
- {
- drawArea.x += drawArea.width;
- drawArea.width = EditorStyles.toolbarButton.CalcSize(style.pasteButtonLabel).x;
- totalWidth -= drawArea.width;
- if (totalWidth < 0)
- drawArea.width += totalWidth;
-
- if (drawArea.width > 0 && GUI.Button(drawArea, style.pasteButtonLabel, EditorStyles.toolbarButton))
- {
- Paste();
- }
- }
-
- using (new EditorGUI.DisabledScope(m_CopyOutline == null))
- {
- drawArea.x += drawArea.width;
- drawArea.width = EditorStyles.toolbarButton.CalcSize(style.pasteAllButtonLabel).x;
- totalWidth -= drawArea.width;
- if (totalWidth < 0)
- drawArea.width += totalWidth;
-
- if (drawArea.width > 0 && GUI.Button(drawArea, style.pasteAllButtonLabel, EditorStyles.toolbarButton))
- {
- PasteAll();
- }
- }
- }
- }
-
- public override void DoPostGUI()
- {}
-
- public override bool CanBeActivated()
- {
- return SpriteFrameModule.GetSpriteImportMode(spriteEditorWindow.GetDataProvider<ISpriteEditorDataProvider>()) != SpriteImportMode.None;
- }
-
- private void RecordUndo()
- {
- undoSystem.RegisterCompleteObjectUndo(m_Outline, "Outline changed");
- }
-
- public void CreateNewOutline(Rect rectOutline)
- {
- Rect rect = m_Selected.rect;
- if (rect.Contains(rectOutline.min) && rect.Contains(rectOutline.max))
- {
- RecordUndo();
- SpriteOutline so = new SpriteOutline();
- Vector2 outlineOffset = new Vector2(0.5f * rect.width + rect.x, 0.5f * rect.height + rect.y);
- Rect selectionRect = new Rect(rectOutline);
- selectionRect.min = SnapPoint(rectOutline.min);
- selectionRect.max = SnapPoint(rectOutline.max);
- so.Add(CapPointToRect(new Vector2(selectionRect.xMin, selectionRect.yMin), rect) - outlineOffset);
- so.Add(CapPointToRect(new Vector2(selectionRect.xMin, selectionRect.yMax), rect) - outlineOffset);
- so.Add(CapPointToRect(new Vector2(selectionRect.xMax, selectionRect.yMax), rect) - outlineOffset);
- so.Add(CapPointToRect(new Vector2(selectionRect.xMax, selectionRect.yMin), rect) - outlineOffset);
- selectedShapeOutline.Add(so);
- spriteEditorWindow.SetDataModified();
- shapeEditorDirty = true;
- }
- }
-
- private void HandleCreateNewOutline()
- {
- if (m_WasRectSelecting && m_ShapeSelectionUI.isSelecting == false && m_SelectionRect != null && m_Selected != null)
- {
- bool createNewOutline = true;
- foreach (var se in m_ShapeEditors)
- {
- if (se.selectedPoints.Count != 0)
- {
- createNewOutline = false;
- break;
- }
- }
-
- if (createNewOutline)
- CreateNewOutline(m_SelectionRect.Value);
- }
- m_SelectionRect = null;
- }
-
- public void UpdateShapeEditors()
- {
- SetupShapeEditor();
-
- if (m_Selected != null)
- {
- IEvent currentEvent = eventSystem.current;
- var wantsDelete = currentEvent.type == EventType.ExecuteCommand && (currentEvent.commandName == k_SoftDeleteCommandName || currentEvent.commandName == k_DeleteCommandName);
-
- for (int i = 0; i < m_ShapeEditors.Length; ++i)
- {
- if (m_ShapeEditors[i].GetPointsCount() == 0)
- continue;
-
- m_ShapeEditors[i].inEditMode = true;
- m_ShapeEditors[i].OnGUI();
- if (shapeEditorDirty)
- break;
- }
-
- if (wantsDelete)
- {
- // remove outline which have lesser than 3 points
- for (int i = selectedShapeOutline.Count - 1; i >= 0; --i)
- {
- if (selectedShapeOutline[i].Count < 3)
- {
- selectedShapeOutline.RemoveAt(i);
- shapeEditorDirty = true;
- }
- }
- }
- }
- }
-
- private bool IsMouseOverOutlinePoints()
- {
- if (m_Selected == null)
- return false;
- Vector2 outlineOffset = new Vector2(0.5f * m_Selected.rect.width + m_Selected.rect.x, 0.5f * m_Selected.rect.height + m_Selected.rect.y);
- float handleSize = GetHandleSize();
- Rect r = new Rect(0, 0, handleSize * 2, handleSize * 2);
- for (int i = 0; i < selectedShapeOutline.Count; ++i)
- {
- var outline = selectedShapeOutline[i];
- for (int j = 0; j < outline.Count; ++j)
- {
- r.center = outline[j] + outlineOffset;
- if (r.Contains(m_MousePosition))
- return true;
- }
- }
- return false;
- }
-
- private float GetHandleSize()
- {
- return k_HandleSize / m_HandleMatrix.m00;
- }
-
- private void CleanupShapeEditors()
- {
- if (m_ShapeEditors != null)
- {
- for (int i = 0; i < m_ShapeEditors.Length; ++i)
- {
- for (int j = 0; j < m_ShapeEditors.Length; ++j)
- {
- if (i != j)
- m_ShapeEditors[j].UnregisterFromShapeEditor(m_ShapeEditors[i]);
- }
- m_ShapeEditors[i].OnDisable();
- }
- }
- m_ShapeEditors = null;
- }
-
- public void SetupShapeEditor()
- {
- if (shapeEditorDirty || m_Selected != spriteEditorWindow.selectedSpriteRect)
- {
- m_Selected = spriteEditorWindow.selectedSpriteRect;
- CleanupShapeEditors();
-
- if (m_Selected != null)
- {
- if (!HasShapeOutline(m_Selected))
- SetupShapeEditorOutline(m_Selected);
- m_ShapeEditors = new ShapeEditor[selectedShapeOutline.Count];
-
- for (int i = 0; i < selectedShapeOutline.Count; ++i)
- {
- int outlineIndex = i;
- m_ShapeEditors[i] = shapeEditorFactory.CreateShapeEditor();
- m_ShapeEditors[i].SetRectSelectionTool(m_ShapeSelectionUI);
- m_ShapeEditors[i].LocalToWorldMatrix = () => m_HandleMatrix;
- m_ShapeEditors[i].LocalToScreen = (point) => Handles.matrix.MultiplyPoint(point);
- m_ShapeEditors[i].ScreenToLocal = ScreenToLocal;
- m_ShapeEditors[i].RecordUndo = RecordUndo;
- m_ShapeEditors[i].GetHandleSize = GetHandleSize;
- m_ShapeEditors[i].lineTexture = m_OutlineTexture;
- m_ShapeEditors[i].Snap = SnapPoint;
- m_ShapeEditors[i].GetPointPosition = (index) => GetPointPosition(outlineIndex, index);
- m_ShapeEditors[i].SetPointPosition = (index, position) => SetPointPosition(outlineIndex, index, position);
- m_ShapeEditors[i].InsertPointAt = (index, position) => InsertPointAt(outlineIndex, index, position);
- m_ShapeEditors[i].RemovePointAt = (index) => RemovePointAt(outlineIndex, index);
- m_ShapeEditors[i].GetPointsCount = () => GetPointsCount(outlineIndex);
- }
- for (int i = 0; i < selectedShapeOutline.Count; ++i)
- {
- for (int j = 0; j < selectedShapeOutline.Count; ++j)
- {
- if (i != j)
- m_ShapeEditors[j].RegisterToShapeEditor(m_ShapeEditors[i]);
- }
- }
- }
- else
- {
- m_ShapeEditors = new ShapeEditor[0];
- }
- }
- shapeEditorDirty = false;
- }
-
- protected virtual bool HasShapeOutline(SpriteRect spriteRect)
- {
- var outline = m_Outline[spriteRect.spriteID] != null ? m_Outline[spriteRect.spriteID].spriteOutlines : null;
- return outline != null;
- }
-
- protected virtual void SetupShapeEditorOutline(SpriteRect spriteRect)
- {
- var outline = m_Outline[spriteRect.spriteID];
- var outlines = GenerateSpriteRectOutline(spriteRect.rect,
- Math.Abs(outline.tessellationDetail - (-1f)) < Mathf.Epsilon ? 0 : outline.tessellationDetail,
- 0, m_TextureDataProvider);
- if (outlines.Count == 0)
- {
- Vector2 halfSize = spriteRect.rect.size * 0.5f;
- outlines = new List<SpriteOutline>()
- {
- new SpriteOutline()
- {
- m_Path = new List<Vector2>()
- {
- new Vector2(-halfSize.x, -halfSize.y),
- new Vector2(-halfSize.x, halfSize.y),
- new Vector2(halfSize.x, halfSize.y),
- new Vector2(halfSize.x, -halfSize.y),
- }
- }
- };
- }
- m_Outline[spriteRect.spriteID].spriteOutlines = outlines;
- }
-
- public Vector3 SnapPoint(Vector3 position)
- {
- if (m_Snap)
- {
- position.x = Mathf.RoundToInt(position.x);
- position.y = Mathf.RoundToInt(position.y);
- }
- return position;
- }
-
- public Vector3 GetPointPosition(int outlineIndex, int pointIndex)
- {
- if (outlineIndex >= 0 && outlineIndex < selectedShapeOutline.Count)
- {
- var outline = selectedShapeOutline[outlineIndex];
- if (pointIndex >= 0 && pointIndex < outline.Count)
- {
- return ConvertSpriteRectSpaceToTextureSpace(outline[pointIndex]);
- }
- }
- return new Vector3(float.NaN, float.NaN, float.NaN);
- }
-
- public void SetPointPosition(int outlineIndex, int pointIndex, Vector3 position)
- {
- selectedShapeOutline[outlineIndex][pointIndex] = ConvertTextureSpaceToSpriteRectSpace(CapPointToRect(position, m_Selected.rect));
- spriteEditorWindow.SetDataModified();
- }
-
- public void InsertPointAt(int outlineIndex, int pointIndex, Vector3 position)
- {
- selectedShapeOutline[outlineIndex].Insert(pointIndex, ConvertTextureSpaceToSpriteRectSpace(CapPointToRect(position, m_Selected.rect)));
- spriteEditorWindow.SetDataModified();
- }
-
- public void RemovePointAt(int outlineIndex, int i)
- {
- selectedShapeOutline[outlineIndex].RemoveAt(i);
- spriteEditorWindow.SetDataModified();
- }
-
- public int GetPointsCount(int outlineIndex)
- {
- return selectedShapeOutline[outlineIndex].Count;
- }
-
- private Vector2 ConvertSpriteRectSpaceToTextureSpace(Vector2 value)
- {
- Vector2 outlineOffset = new Vector2(0.5f * m_Selected.rect.width + m_Selected.rect.x, 0.5f * m_Selected.rect.height + m_Selected.rect.y);
- value += outlineOffset;
- return value;
- }
-
- private Vector2 ConvertTextureSpaceToSpriteRectSpace(Vector2 value)
- {
- Vector2 outlineOffset = new Vector2(0.5f * m_Selected.rect.width + m_Selected.rect.x, 0.5f * m_Selected.rect.height + m_Selected.rect.y);
- value -= outlineOffset;
- return value;
- }
-
- private Vector3 ScreenToLocal(Vector2 point)
- {
- return Handles.inverseMatrix.MultiplyPoint(point);
- }
-
- private void UndoRedoPerformed()
- {
- shapeEditorDirty = true;
- }
-
- private void DrawGizmos()
- {
- if (eventSystem.current.type == EventType.Repaint)
- {
- var selected = spriteEditorWindow.selectedSpriteRect;
- if (selected != null)
- {
- SpriteEditorUtility.BeginLines(styles.spriteBorderColor);
- SpriteEditorUtility.DrawBox(selected.rect);
- SpriteEditorUtility.EndLines();
- }
- }
- }
-
- protected static List<SpriteOutline> GenerateSpriteRectOutline(Rect rect, float detail, byte alphaTolerance, ITextureDataProvider textureProvider)
- {
- List<SpriteOutline> outline = new List<SpriteOutline>();
- var texture = textureProvider.GetReadableTexture2D();
- if (texture != null)
- {
- Vector2[][] paths;
-
- // we might have a texture that is capped because of max size or NPOT.
- // in that case, we need to convert values from capped space to actual texture space and back.
- int actualWidth = 0, actualHeight = 0;
- int cappedWidth, cappedHeight;
- textureProvider.GetTextureActualWidthAndHeight(out actualWidth, out actualHeight);
- cappedWidth = texture.width;
- cappedHeight = texture.height;
-
- Vector2 scale = new Vector2(cappedWidth / (float)actualWidth, cappedHeight / (float)actualHeight);
- Rect spriteRect = rect;
- spriteRect.xMin *= scale.x;
- spriteRect.xMax *= scale.x;
- spriteRect.yMin *= scale.y;
- spriteRect.yMax *= scale.y;
-
- UnityEditor.Sprites.SpriteUtility.GenerateOutline(texture, spriteRect, detail, alphaTolerance, true, out paths);
-
- Rect capRect = new Rect();
- capRect.size = rect.size;
- capRect.center = Vector2.zero;
- for (int j = 0; j < paths.Length; ++j)
- {
- SpriteOutline points = new SpriteOutline();
- foreach (Vector2 v in paths[j])
- points.Add(CapPointToRect(new Vector2(v.x / scale.x, v.y / scale.y), capRect));
-
- outline.Add(points);
- }
- }
- return outline;
- }
-
- public void Copy()
- {
- if (m_Selected == null || !HasShapeOutline(m_Selected))
- return;
-
- m_CopyOutline = new SpriteOutlineList(m_Selected.spriteID, m_Outline[m_Selected.spriteID].ToListVectorCapped(m_Selected.rect));
- }
-
- public void Paste()
- {
- if (m_Selected == null || m_CopyOutline == null)
- return;
-
- RecordUndo();
- m_Outline[m_Selected.spriteID] = new SpriteOutlineList(m_Selected.spriteID, m_CopyOutline.ToListVectorCapped(m_Selected.rect));
- spriteEditorWindow.SetDataModified();
- shapeEditorDirty = true;
- }
-
- public void PasteAll()
- {
- if (m_CopyOutline == null)
- return;
-
- RecordUndo();
- var rectCache = spriteEditorWindow.GetDataProvider<ISpriteEditorDataProvider>().GetSpriteRects();
- if (rectCache != null)
- {
- foreach (var spriteRect in rectCache)
- {
- var outlines = m_CopyOutline.ToListVectorCapped(spriteRect.rect);
- m_Outline[spriteRect.spriteID] = new SpriteOutlineList(spriteRect.spriteID, outlines);
- }
- }
- spriteEditorWindow.SetDataModified();
- shapeEditorDirty = true;
- }
-
- internal static Vector2 CapPointToRect(Vector2 so, Rect r)
- {
- so.x = Mathf.Min(r.xMax, so.x);
- so.x = Mathf.Max(r.xMin, so.x);
- so.y = Mathf.Min(r.yMax, so.y);
- so.y = Mathf.Max(r.yMin, so.y);
- return so;
- }
- }
- }
|