Tim Cooper
9 年前
当前提交
371b3dba
共有 68 个文件被更改,包括 3326 次插入 和 2641 次删除
-
1001UnityProject/Assets/GraphFramework/Canvas2D/Editor/Canvas2D.cs
-
532UnityProject/Assets/GraphFramework/Canvas2D/Editor/QuadTree.cs
-
260UnityProject/Assets/GraphFramework/Canvas2D/Editor/UIHelpers.cs
-
6UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/DrawableMaterialNode.cs
-
6UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/MaterialWindow.cs
-
2UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/NodeAnchor.cs
-
2UnityProject/Assets/UnityShaderEditor/Editor/Source/Drawing/SimpleWidgets.cs
-
121UnityProject/Assets/GraphFramework/Canvas2D/Editor/CanvasAnimation.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/CanvasAnimation.cs.meta
-
586UnityProject/Assets/GraphFramework/Canvas2D/Editor/CanvasElement.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/CanvasElement.cs.meta
-
9UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph.meta
-
9UnityProject/Assets/GraphFramework/Canvas2D/Editor/IBounds.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/IBounds.cs.meta
-
8UnityProject/Assets/GraphFramework/Canvas2D/Editor/ICanvasDataSource.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/ICanvasDataSource.cs.meta
-
9UnityProject/Assets/GraphFramework/Canvas2D/Editor/Layout.meta
-
7UnityProject/Assets/GraphFramework/Canvas2D/Editor/ManipulatorCapability.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/ManipulatorCapability.cs.meta
-
9UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators.meta
-
23UnityProject/Assets/GraphFramework/Canvas2D/Editor/PropertyData.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/PropertyData.cs.meta
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/QuadTreeNode.cs.meta
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/RectUtils.cs.meta
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/UpdateType.cs.meta
-
9UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/Direction.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/Direction.cs.meta
-
192UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/Edge.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/Edge.cs.meta
-
254UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/EdgeConnector.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/EdgeConnector.cs.meta
-
14UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/IConnect.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/IConnect.cs.meta
-
137UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/NodeAdapter.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/NodeAdapter.cs.meta
-
8UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/TypeAdapter.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph/TypeAdapter.cs.meta
-
125UnityProject/Assets/GraphFramework/Canvas2D/Editor/Layout/CanvasLayout.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Layout/CanvasLayout.cs.meta
-
101UnityProject/Assets/GraphFramework/Canvas2D/Editor/Layout/CanvasVerticalLayout.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Layout/CanvasVerticalLayout.cs.meta
-
41UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/ContextualMenu.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/ContextualMenu.cs.meta
-
42UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/DragDrop.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/DragDrop.cs.meta
-
98UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/Draggable.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/Draggable.cs.meta
-
98UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/Frame.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/Frame.cs.meta
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/IManipulate.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/IManipulate.cs.meta
-
29UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/ImguiContainer.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/ImguiContainer.cs.meta
-
135UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/RectangleSelect.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/RectangleSelect.cs.meta
-
84UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/Resizable.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/Resizable.cs.meta
-
157UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/ScreenSpaceGrid.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/ScreenSpaceGrid.cs.meta
-
113UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/Zoomable.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators/Zoomable.cs.meta
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph.cs.meta
-
795UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators.cs
-
12UnityProject/Assets/GraphFramework/Canvas2D/Editor/Manipulators.cs.meta
-
585UnityProject/Assets/GraphFramework/Canvas2D/Editor/Graph.cs
1001
UnityProject/Assets/GraphFramework/Canvas2D/Editor/Canvas2D.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Linq.Expressions; |
|||
using UnityEditor; |
|||
using Object = UnityEngine.Object; |
|||
namespace UnityEditorInternal |
|||
namespace UnityEditorInternal.Experimental |
|||
internal class RectUtils |
|||
{ |
|||
public static bool Contains(Rect a, Rect b) |
|||
{ |
|||
if (a.xMin > b.xMin) |
|||
return false; |
|||
if (a.xMax < b.xMax) |
|||
return false; |
|||
|
|||
if (a.yMin > b.yMin) |
|||
return false; |
|||
if (a.yMax < b.yMax) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public static Rect Encompass(Rect a, Rect b) |
|||
{ |
|||
Rect newRect = a; |
|||
newRect.xMin = Math.Min(a.xMin, b.xMin); |
|||
newRect.yMin = Math.Min(a.yMin, b.yMin); |
|||
newRect.xMax = Math.Max(a.xMax, b.xMax); |
|||
newRect.yMax = Math.Max(a.yMax, b.yMax); |
|||
return newRect; |
|||
} |
|||
|
|||
public static Rect Inflate(Rect a, float factor) |
|||
{ |
|||
return Inflate(a, factor, factor); |
|||
} |
|||
|
|||
public static Rect Inflate(Rect a, float factorX, float factorY) |
|||
{ |
|||
float newWidth = a.width * factorX; |
|||
float newHeight = a.height * factorY; |
|||
|
|||
float offsetWidth = (newWidth - a.width) / 2.0f; |
|||
float offsetHeight = (newHeight - a.height) / 2.0f; |
|||
|
|||
Rect r = a; |
|||
r.xMin -= offsetWidth; |
|||
r.yMin -= offsetHeight; |
|||
r.xMax += offsetWidth; |
|||
r.yMax += offsetHeight; |
|||
return r; |
|||
} |
|||
|
|||
public static bool Intersects(Rect r1, Rect r2) |
|||
{ |
|||
if (!r1.Overlaps(r2) && !r2.Overlaps(r1)) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
public static bool Intersection(Rect r1, Rect r2, out Rect intersection) |
|||
{ |
|||
if (!r1.Overlaps(r2) && !r2.Overlaps(r1)) |
|||
{ |
|||
intersection = new Rect(0, 0, 0, 0); |
|||
return false; |
|||
} |
|||
|
|||
float left = Mathf.Max(r1.xMin, r2.xMin); |
|||
float top = Mathf.Max(r1.yMin, r2.yMin); |
|||
|
|||
float right = Mathf.Min(r1.xMax, r2.xMax); |
|||
float bottom = Mathf.Min(r1.yMax, r2.yMax); |
|||
|
|||
intersection = new Rect(left, top, right - left, bottom - top); |
|||
return true; |
|||
} |
|||
|
|||
public static bool IntersectsSegment(Rect rect, Vector2 p1, Vector2 p2) |
|||
{ |
|||
float minX = Mathf.Min(p1.x, p2.x); |
|||
float maxX = Mathf.Max(p1.x, p2.x); |
|||
|
|||
if (maxX > rect.xMax) |
|||
{ |
|||
maxX = rect.xMax; |
|||
} |
|||
|
|||
if (minX < rect.xMin) |
|||
{ |
|||
minX = rect.xMin; |
|||
} |
|||
|
|||
if (minX > maxX) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
float minY = Mathf.Min(p1.y, p2.y); |
|||
float maxY = Mathf.Max(p1.y, p2.y); |
|||
|
|||
float dx = p2.x - p1.x; |
|||
|
|||
if (Mathf.Abs(dx) > 0.0000001f) |
|||
{ |
|||
float a = (p2.y - p1.y) / dx; |
|||
float b = p1.y - a * p1.x; |
|||
minY = a * minX + b; |
|||
maxY = a * maxX + b; |
|||
} |
|||
|
|||
if (minY > maxY) |
|||
{ |
|||
float tmp = maxY; |
|||
maxY = minY; |
|||
minY = tmp; |
|||
} |
|||
|
|||
if (maxY > rect.yMax) |
|||
{ |
|||
maxY = rect.yMax; |
|||
} |
|||
|
|||
if (minY < rect.yMin) |
|||
{ |
|||
minY = rect.yMin; |
|||
} |
|||
|
|||
if (minY > maxY) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public static Rect OffsetX(Rect r, float offsetX) |
|||
{ |
|||
return Offset(r, offsetX, 0.0f); |
|||
} |
|||
|
|||
public static Rect Offset(Rect r, float offsetX, float offsetY) |
|||
{ |
|||
Rect nr = r; |
|||
nr.xMin += offsetX; |
|||
nr.yMin += offsetY; |
|||
return nr; |
|||
} |
|||
|
|||
public static Rect Offset(Rect a, Rect b) |
|||
{ |
|||
Rect nr = a; |
|||
nr.xMin += b.xMin; |
|||
nr.yMin += b.yMin; |
|||
return nr; |
|||
} |
|||
|
|||
public static Rect Move(Rect r, Vector2 delta) |
|||
{ |
|||
Rect nr = r; |
|||
nr.xMin += delta.x; |
|||
nr.yMin += delta.y; |
|||
nr.xMax += delta.x; |
|||
nr.yMax += delta.y; |
|||
return nr; |
|||
} |
|||
} |
|||
|
|||
internal interface IBounds |
|||
{ |
|||
Rect boundingRect { get; } |
|||
} |
|||
|
|||
internal class QuadTreeNode<T> where T : IBounds |
|||
{ |
|||
private Rect m_BoundingRect; |
|||
private static Color m_DebugFillColor = new Color(1.0f, 1.0f, 1.0f, 0.01f); |
|||
private static Color m_DebugWireColor = new Color(1.0f, 0.0f, 0.0f, 0.5f); |
|||
private static Color m_DebugBoxFillColor = new Color(1.0f, 0.0f, 0.0f, 0.01f); |
|||
private const float kSmallestAreaForQuadTreeNode = 10.0f; |
|||
|
|||
List<T> m_Elements = new List<T>(); |
|||
List<QuadTreeNode<T>> m_ChildrenNodes = new List<QuadTreeNode<T>>(4); |
|||
|
|||
public QuadTreeNode(Rect r) |
|||
{ |
|||
m_BoundingRect = r; |
|||
} |
|||
|
|||
public bool IsEmpty { get { return (m_BoundingRect.width == 0 && m_BoundingRect.height == 0) || m_ChildrenNodes.Count == 0; } } |
|||
public Rect BoundingRect { get { return m_BoundingRect; } } |
|||
|
|||
public int CountItemsIncludingChildren() |
|||
{ |
|||
return Count (true); |
|||
} |
|||
|
|||
public int CountLocalItems() |
|||
{ |
|||
return Count(false); |
|||
} |
|||
|
|||
private int Count(bool recursive) |
|||
{ |
|||
int count = m_Elements.Count; |
|||
|
|||
if (recursive) |
|||
{ |
|||
foreach (QuadTreeNode<T> node in m_ChildrenNodes) |
|||
count += node.Count(recursive); |
|||
} |
|||
return count; |
|||
} |
|||
|
|||
public List<T> GetElementsIncludingChildren() |
|||
{ |
|||
return Elements (true); |
|||
} |
|||
|
|||
public List<T> GetElements() |
|||
{ |
|||
return Elements(false); |
|||
} |
|||
|
|||
private List<T> Elements(bool recursive) |
|||
{ |
|||
List<T> results = new List<T>(); |
|||
|
|||
if (recursive) |
|||
{ |
|||
foreach (QuadTreeNode<T> node in m_ChildrenNodes) |
|||
results.AddRange(node.Elements(recursive)); |
|||
} |
|||
|
|||
results.AddRange(m_Elements); |
|||
return results; |
|||
} |
|||
|
|||
public List<T> IntersectsWith(Rect queryArea) |
|||
{ |
|||
List<T> results = new List<T>(); |
|||
|
|||
foreach (T item in m_Elements) |
|||
{ |
|||
if (RectUtils.Intersects(item.boundingRect, queryArea)) |
|||
{ |
|||
results.Add(item); |
|||
} |
|||
} |
|||
|
|||
foreach (QuadTreeNode<T> node in m_ChildrenNodes) |
|||
{ |
|||
if (node.IsEmpty) |
|||
continue; |
|||
|
|||
if (RectUtils.Intersects(node.BoundingRect, queryArea)) |
|||
{ |
|||
// the node completely contains the queryArea
|
|||
// recurse down and stop
|
|||
results.AddRange(node.IntersectsWith(queryArea)); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return results; |
|||
|
|||
} |
|||
|
|||
|
|||
public List<T> ContainedBy(Rect queryArea) |
|||
{ |
|||
List<T> results = new List<T>(); |
|||
|
|||
foreach (T item in m_Elements) |
|||
{ |
|||
if (RectUtils.Contains(item.boundingRect, queryArea)) |
|||
{ |
|||
results.Add(item); |
|||
} |
|||
else if (queryArea.Overlaps(item.boundingRect)) |
|||
{ |
|||
results.Add(item); |
|||
} |
|||
} |
|||
|
|||
foreach (QuadTreeNode<T> node in m_ChildrenNodes) |
|||
{ |
|||
if (node.IsEmpty) |
|||
continue; |
|||
|
|||
if (RectUtils.Contains(node.BoundingRect, queryArea)) |
|||
{ |
|||
// the node completely contains the queryArea
|
|||
// recurse down and stop
|
|||
results.AddRange(node.ContainedBy(queryArea)); |
|||
break; |
|||
} |
|||
|
|||
if (RectUtils.Contains(queryArea, node.BoundingRect)) |
|||
{ |
|||
// the queryArea completely contains this node
|
|||
// just add everything under this node, recursively
|
|||
results.AddRange(node.Elements(true)); |
|||
continue; |
|||
} |
|||
|
|||
if (node.BoundingRect.Overlaps(queryArea)) |
|||
{ |
|||
// the node intesects
|
|||
// recurse and continue iterating siblings
|
|||
results.AddRange(node.ContainedBy(queryArea)); |
|||
} |
|||
} |
|||
|
|||
return results; |
|||
} |
|||
|
|||
public void Remove(T item) |
|||
{ |
|||
m_Elements.Remove(item); |
|||
foreach (QuadTreeNode<T> node in m_ChildrenNodes) |
|||
{ |
|||
node.Remove(item); |
|||
} |
|||
} |
|||
|
|||
public void Insert(T item) |
|||
{ |
|||
if (!RectUtils.Contains(m_BoundingRect, item.boundingRect)) |
|||
{ |
|||
Rect intersection = new Rect(); |
|||
if (!RectUtils.Intersection(item.boundingRect, m_BoundingRect, out intersection)) |
|||
{ |
|||
// Ignore elements completely outside the quad tree
|
|||
return; |
|||
} |
|||
} |
|||
|
|||
if (m_ChildrenNodes.Count == 0) |
|||
Subdivide(); |
|||
|
|||
// insert into children nodes
|
|||
foreach (QuadTreeNode<T> node in m_ChildrenNodes) |
|||
{ |
|||
if (RectUtils.Contains(node.BoundingRect, item.boundingRect)) |
|||
{ |
|||
node.Insert(item); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
// item is not completely contained in any of the children nodes
|
|||
// insert here
|
|||
this.m_Elements.Add(item); |
|||
} |
|||
|
|||
private void Subdivide() |
|||
{ |
|||
if ((m_BoundingRect.height * m_BoundingRect.width) <= kSmallestAreaForQuadTreeNode) |
|||
return; |
|||
|
|||
float halfWidth = (m_BoundingRect.width / 2f); |
|||
float halfHeight = (m_BoundingRect.height / 2f); |
|||
|
|||
m_ChildrenNodes.Add(new QuadTreeNode<T>(new Rect(m_BoundingRect.position.x, m_BoundingRect.position.y, halfWidth, halfHeight))); |
|||
m_ChildrenNodes.Add(new QuadTreeNode<T>(new Rect(m_BoundingRect.xMin, m_BoundingRect.yMin + halfHeight, halfWidth, halfHeight))); |
|||
m_ChildrenNodes.Add(new QuadTreeNode<T>(new Rect(m_BoundingRect.xMin + halfWidth, m_BoundingRect.yMin, halfWidth, halfHeight))); |
|||
m_ChildrenNodes.Add(new QuadTreeNode<T>(new Rect(m_BoundingRect.xMin + halfWidth, m_BoundingRect.yMin + halfHeight, halfWidth, halfHeight))); |
|||
} |
|||
|
|||
public void DebugDraw(Vector2 offset) |
|||
{ |
|||
UnityEditor.Experimental.UIHelpers.ApplyWireMaterial(); |
|||
Rect screenSpaceRect = m_BoundingRect; |
|||
screenSpaceRect.x += offset.x; |
|||
screenSpaceRect.y += offset.y; |
|||
|
|||
Handles.DrawSolidRectangleWithOutline(screenSpaceRect, m_DebugFillColor, m_DebugWireColor); |
|||
foreach (QuadTreeNode<T> node in m_ChildrenNodes) |
|||
{ |
|||
node.DebugDraw(offset); |
|||
} |
|||
|
|||
foreach (IBounds i in Elements(false)) |
|||
{ |
|||
Rect o = i.boundingRect; |
|||
o.x += offset.x; |
|||
o.y += offset.y; |
|||
Handles.DrawSolidRectangleWithOutline(o, m_DebugBoxFillColor, Color.yellow); |
|||
} |
|||
|
|||
} |
|||
}; |
|||
internal class QuadTree<T> where T : IBounds |
|||
{ |
|||
private QuadTreeNode<T> m_Root; |
|||
private Rect m_Rectangle; |
|||
private Vector2 m_ScreenSpaceOffset = Vector2.zero; |
|||
internal class QuadTree<T> where T : IBounds |
|||
{ |
|||
private QuadTreeNode<T> m_Root = null; |
|||
private Rect m_Rectangle; |
|||
private Vector2 m_ScreenSpaceOffset = Vector2.zero; |
|||
|
|||
public QuadTree() |
|||
{ |
|||
Clear(); |
|||
} |
|||
public QuadTree() |
|||
{ |
|||
Clear(); |
|||
} |
|||
public Vector2 screenSpaceOffset |
|||
{ |
|||
get { return m_ScreenSpaceOffset; } |
|||
set |
|||
{ |
|||
m_ScreenSpaceOffset = value; |
|||
} |
|||
} |
|||
public Vector2 screenSpaceOffset |
|||
{ |
|||
get { return m_ScreenSpaceOffset; } |
|||
set |
|||
{ |
|||
m_ScreenSpaceOffset = value; |
|||
} |
|||
} |
|||
public Rect rectangle |
|||
{ |
|||
get { return m_Rectangle; } |
|||
} |
|||
public Rect rectangle |
|||
{ |
|||
get { return m_Rectangle; } |
|||
} |
|||
public void Clear() |
|||
{ |
|||
SetSize(new Rect(0, 0, 1, 1)); |
|||
} |
|||
public void Clear() |
|||
{ |
|||
SetSize(new Rect(0, 0, 1, 1)); |
|||
} |
|||
public void SetSize(Rect rectangle) |
|||
{ |
|||
m_Root = null; |
|||
m_Rectangle = rectangle; |
|||
m_Root = new QuadTreeNode<T>(m_Rectangle); |
|||
} |
|||
public void SetSize(Rect rectangle) |
|||
{ |
|||
m_Root = null; |
|||
m_Rectangle = rectangle; |
|||
m_Root = new QuadTreeNode<T>(m_Rectangle); |
|||
} |
|||
public int Count { get { return m_Root.CountItemsIncludingChildren(); } } |
|||
public int count { get { return m_Root.CountItemsIncludingChildren(); } } |
|||
public void Insert(List<T> items) |
|||
{ |
|||
foreach (T i in items) |
|||
{ |
|||
Insert(i); |
|||
} |
|||
} |
|||
public void Insert(List<T> items) |
|||
{ |
|||
foreach (T i in items) |
|||
{ |
|||
Insert(i); |
|||
} |
|||
} |
|||
public void Insert(T item) |
|||
{ |
|||
m_Root.Insert(item); |
|||
} |
|||
public void Insert(T item) |
|||
{ |
|||
m_Root.Insert(item); |
|||
} |
|||
public void Remove(T item) |
|||
{ |
|||
m_Root.Remove(item); |
|||
} |
|||
public void Remove(T item) |
|||
{ |
|||
m_Root.Remove(item); |
|||
} |
|||
public List<T> IntersectsWith(Rect area) |
|||
{ |
|||
area.x -= m_ScreenSpaceOffset.x; |
|||
area.y -= m_ScreenSpaceOffset.y; |
|||
return m_Root.IntersectsWith(area); |
|||
} |
|||
public List<T> IntersectsWith(Rect area) |
|||
{ |
|||
area.x -= m_ScreenSpaceOffset.x; |
|||
area.y -= m_ScreenSpaceOffset.y; |
|||
return m_Root.IntersectsWith(area); |
|||
} |
|||
public List<T> ContainedBy(Rect area) |
|||
{ |
|||
area.x -= m_ScreenSpaceOffset.x; |
|||
area.y -= m_ScreenSpaceOffset.y; |
|||
return m_Root.ContainedBy(area); |
|||
} |
|||
public List<T> ContainedBy(Rect area) |
|||
{ |
|||
area.x -= m_ScreenSpaceOffset.x; |
|||
area.y -= m_ScreenSpaceOffset.y; |
|||
return m_Root.ContainedBy(area); |
|||
} |
|||
public List<T> Elements() |
|||
{ |
|||
return m_Root.GetElementsIncludingChildren(); |
|||
} |
|||
public List<T> Elements() |
|||
{ |
|||
return m_Root.GetElementsIncludingChildren(); |
|||
} |
|||
public void DebugDraw() |
|||
{ |
|||
m_Root.DebugDraw(m_ScreenSpaceOffset); |
|||
} |
|||
} |
|||
public void DebugDraw() |
|||
{ |
|||
m_Root.DebugDraw(m_ScreenSpaceOffset); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Expressions; |
|||
using UnityEngine; |
|||
using UnityEditorInternal; |
|||
using Object = UnityEngine.Object; |
|||
namespace UnityEditor |
|||
namespace UnityEditor.Experimental |
|||
namespace Experimental |
|||
{ |
|||
/// <summary>
|
|||
/// CanvasLayout : the base class for vertical and horizontal layouts
|
|||
/// WARNING: these layout classes have pretty limited usage.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Do not use this class directly. Use on of the specializations or derive your own
|
|||
/// </remarks>
|
|||
internal class CanvasLayout |
|||
{ |
|||
protected CanvasElement m_Owner = null; |
|||
protected CanvasLayout m_Parent = null; |
|||
protected Vector4 m_Padding = Vector4.zero; |
|||
protected float m_Left = 0; |
|||
protected float m_Height = 0; |
|||
protected float m_Width = 0; |
|||
protected List<CanvasLayout> m_Children = new List<CanvasLayout>(); |
|||
protected List<CanvasElement> m_Elements = new List<CanvasElement>(); |
|||
|
|||
public float Height |
|||
{ |
|||
get |
|||
{ |
|||
float maxHeight = m_Height; |
|||
foreach (CanvasLayout l in m_Children) |
|||
{ |
|||
maxHeight = Mathf.Max(maxHeight, l.Height); |
|||
} |
|||
return maxHeight + PaddingTop + PaddingBottom; |
|||
} |
|||
} |
|||
|
|||
public float Width |
|||
{ |
|||
get |
|||
{ |
|||
float maxWidth = m_Width; |
|||
foreach (CanvasLayout l in m_Children) |
|||
{ |
|||
maxWidth = Mathf.Max(maxWidth, l.Width); |
|||
} |
|||
return maxWidth + PaddingLeft + PaddingRight; |
|||
} |
|||
} |
|||
|
|||
public CanvasLayout(CanvasElement e) |
|||
{ |
|||
m_Owner = e; |
|||
} |
|||
|
|||
public CanvasLayout(CanvasLayout p) |
|||
{ |
|||
m_Parent = p; |
|||
m_Owner = p.Owner(); |
|||
} |
|||
|
|||
public CanvasElement Owner() |
|||
{ |
|||
if (m_Owner != null) |
|||
return m_Owner; |
|||
|
|||
if (m_Parent != null) |
|||
return m_Parent.Owner(); |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public float Left |
|||
{ |
|||
get { return m_Left; } |
|||
set { m_Left = value; } |
|||
} |
|||
|
|||
public float PaddingLeft |
|||
{ |
|||
get { return m_Padding.w; } |
|||
set { m_Padding.w = value; } |
|||
} |
|||
|
|||
public float PaddingRight |
|||
{ |
|||
get { return m_Padding.y; } |
|||
set { m_Padding.y = value; } |
|||
} |
|||
|
|||
public float PaddingTop |
|||
{ |
|||
get { return m_Padding.x; } |
|||
set { m_Padding.x = value; } |
|||
} |
|||
|
|||
public float PaddingBottom |
|||
{ |
|||
get { return m_Padding.z; } |
|||
set { m_Padding.z = value; } |
|||
} |
|||
|
|||
public virtual void LayoutElement(CanvasElement c) |
|||
{ |
|||
m_Elements.Add(c); |
|||
} |
|||
|
|||
public virtual void LayoutElements(CanvasElement[] arrayOfElements) |
|||
{ |
|||
for (int a = 0; a < arrayOfElements.Length; a++) |
|||
{ |
|||
m_Elements.Add(arrayOfElements[a]); |
|||
} |
|||
} |
|||
|
|||
public void AddSpacer(int pixels) |
|||
{ |
|||
float collapsedFactor = m_Owner.IsCollapsed() ? 0.0f : 1.0f; |
|||
m_Height += pixels*collapsedFactor; |
|||
} |
|||
|
|||
public virtual void DebugDraw() |
|||
{ |
|||
|
|||
} |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// CanvasVerticalLayout : Helps layouting a group of canvas elements vertically
|
|||
/// </summary>
|
|||
internal class CanvasVerticalLayout : CanvasLayout |
|||
{ |
|||
public CanvasVerticalLayout(CanvasElement e) |
|||
: base(e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public override void LayoutElements(CanvasElement[] arrayOfElements) |
|||
{ |
|||
for (int a = 0; a < arrayOfElements.Length; a++) |
|||
{ |
|||
LayoutElement(arrayOfElements[a]); |
|||
} |
|||
base.LayoutElements(arrayOfElements); |
|||
} |
|||
|
|||
public override void LayoutElement(CanvasElement c) |
|||
{ |
|||
float collapsedFactor = m_Owner.IsCollapsed() ? 0.0f : 1.0f; |
|||
if ((c.Caps & CanvasElement.Capabilities.DoesNotCollapse) == CanvasElement.Capabilities.DoesNotCollapse) |
|||
{ |
|||
collapsedFactor = 1.0f; |
|||
} |
|||
|
|||
m_Height += m_Padding.x*collapsedFactor; |
|||
//c.translation = new Vector3(m_Padding.y + c.translation.x, Height*collapsedFactor, 0.0f);
|
|||
c.translation = new Vector3(c.translation.x, Height * collapsedFactor, 0.0f); |
|||
c.scale = new Vector3(c.scale.x, c.scale.y*collapsedFactor, 1.0f); |
|||
m_Height += (c.scale.y + m_Padding.z)*collapsedFactor; |
|||
m_Width = Mathf.Max(m_Width, c.scale.x); |
|||
Owner().AddChild(c); |
|||
base.LayoutElement(c); |
|||
} |
|||
|
|||
public override void DebugDraw() |
|||
{ |
|||
if (m_Elements.Count() == 0) |
|||
return; |
|||
|
|||
Rect encompassingRect = m_Elements[0].canvasBoundingRect; |
|||
List<Rect> elementRects = new List<Rect>(); |
|||
foreach (CanvasElement e in m_Elements) |
|||
{ |
|||
elementRects.Add(e.canvasBoundingRect); |
|||
encompassingRect = RectUtils.Encompass(encompassingRect, e.canvasBoundingRect); |
|||
} |
|||
|
|||
Vector3[] points = |
|||
{ |
|||
new Vector3(encompassingRect.xMin, encompassingRect.yMin, 0.0f), |
|||
new Vector3(encompassingRect.xMax, encompassingRect.yMin, 0.0f), |
|||
new Vector3(encompassingRect.xMax, encompassingRect.yMax, 0.0f), |
|||
new Vector3(encompassingRect.xMin, encompassingRect.yMax, 0.0f) |
|||
}; |
|||
|
|||
Color prevColor = GUI.color; |
|||
GUI.color = new Color(1.0f, 0.6f, 0.0f, 1.0f); |
|||
Handles.DrawDottedLine(points[0], points[1], 5.0f); |
|||
Handles.DrawDottedLine(points[1], points[2], 5.0f); |
|||
Handles.DrawDottedLine(points[2], points[3], 5.0f); |
|||
Handles.DrawDottedLine(points[3], points[0], 5.0f); |
|||
GUI.color = prevColor; |
|||
internal class UIHelpers |
|||
{ |
|||
static MethodInfo s_ApplyWireMaterialMi; |
|||
foreach (Rect r in elementRects) |
|||
{ |
|||
Vector2 from = new Vector2(r.xMin, r.yMax); |
|||
Vector2 to = new Vector2(encompassingRect.xMax, r.yMax); |
|||
public static void ApplyWireMaterial() |
|||
{ |
|||
if (s_ApplyWireMaterialMi == null) |
|||
{ |
|||
s_ApplyWireMaterialMi = typeof(HandleUtility).GetMethod("ApplyWireMaterial", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); |
|||
} |
|||
DrawDottedLine(from, to, 5.0f, new Color(1.0f, 0.6f, 0.0f, 1.0f)); |
|||
} |
|||
} |
|||
|
|||
private void DrawDottedLine(Vector3 p1, Vector3 p2, float segmentsLength, Color col) |
|||
{ |
|||
UIHelpers.ApplyWireMaterial(); |
|||
|
|||
GL.Begin(GL.LINES); |
|||
GL.Color(col); |
|||
|
|||
float length = Vector3.Distance(p1, p2); // ignore z component
|
|||
int count = Mathf.CeilToInt(length/segmentsLength); |
|||
for (int i = 0; i < count; i += 2) |
|||
{ |
|||
GL.Vertex((Vector3.Lerp(p1, p2, i*segmentsLength/length))); |
|||
GL.Vertex((Vector3.Lerp(p1, p2, (i + 1)*segmentsLength/length))); |
|||
} |
|||
|
|||
GL.End(); |
|||
} |
|||
|
|||
}; |
|||
|
|||
|
|||
internal class UIHelpers |
|||
{ |
|||
static MethodInfo ApplyWireMaterialMI = null; |
|||
|
|||
public static void ApplyWireMaterial() |
|||
{ |
|||
if (ApplyWireMaterialMI == null) |
|||
{ |
|||
ApplyWireMaterialMI = typeof(HandleUtility).GetMethod("ApplyWireMaterial", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); |
|||
} |
|||
|
|||
if (ApplyWireMaterialMI != null) |
|||
{ |
|||
ApplyWireMaterialMI.Invoke(null, null); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (s_ApplyWireMaterialMi != null) |
|||
{ |
|||
s_ApplyWireMaterialMi.Invoke(null, null); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
public class CanvasAnimation |
|||
{ |
|||
CanvasElement m_ElementBeingAnimated; |
|||
Stack<CanvasAnimationCallback> m_Callbacks = new Stack<CanvasAnimationCallback>(); |
|||
Stack<PropertyData> m_UserData = new Stack<PropertyData>(); |
|||
|
|||
CanvasAnimationCallback m_CurrentCallback; |
|||
PropertyData m_CurrentData; |
|||
|
|||
public CanvasAnimation(CanvasElement e) |
|||
{ |
|||
m_ElementBeingAnimated = e; |
|||
} |
|||
|
|||
public void Tick() |
|||
{ |
|||
if (m_CurrentCallback == null) |
|||
return; |
|||
|
|||
m_CurrentCallback(m_ElementBeingAnimated, this, m_CurrentData); |
|||
m_ElementBeingAnimated.Invalidate(); |
|||
} |
|||
|
|||
public CanvasAnimation Lerp(string prop, object from, object to) |
|||
{ |
|||
FieldInfo fi = GetFieldBeingAnimated(prop); |
|||
if (fi.FieldType != from.GetType()) |
|||
{ |
|||
Debug.LogError("Cannot set a " + from.GetType() + " to " + prop + " because it is a " + fi.FieldType); |
|||
return this; |
|||
} |
|||
|
|||
var propData = new PropertyData(fi, from, to); |
|||
|
|||
switch (fi.FieldType.Name) |
|||
{ |
|||
case "Single": |
|||
AddCallback(LerpFloat, propData); |
|||
break; |
|||
case "Vector3": |
|||
AddCallback(LerpVector3, propData); |
|||
break; |
|||
default: |
|||
Debug.LogError("No handler found to lerp " + fi.FieldType.Name); |
|||
break; |
|||
} |
|||
|
|||
return this; |
|||
} |
|||
|
|||
private void LerpFloat(CanvasElement element, CanvasAnimation owner, object userData) |
|||
{ |
|||
var pData = userData as PropertyData; |
|||
float result = Mathf.Lerp((float)pData.data0, (float)pData.data1, pData.curve.Evaluate(pData.time)); |
|||
pData.field.SetValue(m_ElementBeingAnimated, result); |
|||
pData.time += 0.08f; |
|||
if (pData.time > 1.0f) |
|||
{ |
|||
pData.field.SetValue(m_ElementBeingAnimated, (float)pData.data1); |
|||
owner.Done(); |
|||
} |
|||
} |
|||
|
|||
private void LerpVector3(CanvasElement element, CanvasAnimation owner, object userData) |
|||
{ |
|||
var pData = userData as PropertyData; |
|||
Vector3 result = Vector3.Lerp((Vector3)pData.data0, (Vector3)pData.data1, pData.curve.Evaluate(pData.time)); |
|||
pData.field.SetValue(m_ElementBeingAnimated, result); |
|||
pData.time += 0.08f; |
|||
if (pData.time > 1.0f) |
|||
{ |
|||
pData.field.SetValue(m_ElementBeingAnimated, (Vector3)pData.data1); |
|||
owner.Done(); |
|||
} |
|||
} |
|||
|
|||
public CanvasAnimation Then(CanvasAnimationCallback callback) |
|||
{ |
|||
AddCallback(callback, null); |
|||
return this; |
|||
} |
|||
|
|||
public void Done() |
|||
{ |
|||
if (m_Callbacks.Count == 0) |
|||
{ |
|||
m_ElementBeingAnimated.ParentCanvas().EndAnimation(this); |
|||
return; |
|||
} |
|||
|
|||
m_CurrentData = m_UserData.Pop(); |
|||
m_CurrentCallback = m_Callbacks.Pop(); |
|||
} |
|||
|
|||
private void AddCallback(CanvasAnimationCallback callback, PropertyData userdata) |
|||
{ |
|||
m_UserData.Push(userdata); |
|||
m_Callbacks.Push(callback); |
|||
|
|||
if (m_Callbacks.Count == 1 && m_CurrentCallback == null) |
|||
Done(); |
|||
} |
|||
|
|||
private FieldInfo GetFieldBeingAnimated(string fieldName) |
|||
{ |
|||
foreach (FieldInfo fieldInfo in m_ElementBeingAnimated.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) |
|||
{ |
|||
if (fieldInfo.Name == fieldName) |
|||
return fieldInfo; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: bee58334711c80d429f6c5821a563159 |
|||
timeCreated: 1453889579 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditorInternal; |
|||
using UnityEditorInternal.Experimental; |
|||
using UnityEngine; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
public class CanvasElement : IBounds |
|||
{ |
|||
[Flags] |
|||
public enum Capabilities |
|||
{ |
|||
Normal, |
|||
Unselectable, |
|||
DoesNotCollapse |
|||
} |
|||
|
|||
protected int m_ZIndex; |
|||
protected List<CanvasElement> m_Children = new List<CanvasElement>(); |
|||
protected List<CanvasElement> m_Dependencies = new List<CanvasElement>(); |
|||
protected Vector3 m_Translation = Vector3.zero; |
|||
protected Vector3 m_Scale = Vector3.one; |
|||
protected bool m_Selected; |
|||
protected bool m_Collapsed; |
|||
protected RenderTexture m_Texture; |
|||
protected CanvasElement m_Parent; |
|||
protected Object m_Target; |
|||
protected bool m_SupportsRenderToTexture = true; |
|||
private bool m_Dirty = true; |
|||
protected Capabilities m_Caps = Capabilities.Normal; |
|||
|
|||
public event CanvasEvent MouseDown; |
|||
public event CanvasEvent MouseDrag; |
|||
public event CanvasEvent MouseUp; |
|||
public event CanvasEvent DoubleClick; |
|||
public event CanvasEvent ScrollWheel; |
|||
public event CanvasEvent KeyDown; |
|||
public event CanvasEvent OnWidget; |
|||
public event CanvasEvent ContextClick; |
|||
public event CanvasEvent DragPerform; |
|||
public event CanvasEvent DragExited; |
|||
public event CanvasEvent DragUpdated; |
|||
public event CanvasEvent AllEvents; |
|||
|
|||
private struct AnimationData |
|||
{ |
|||
public Vector2 scaleFrom; |
|||
public Vector2 scaleTo; |
|||
public float scaleTime; |
|||
} |
|||
|
|||
private AnimationData m_Animationdata; |
|||
|
|||
public Capabilities caps |
|||
{ |
|||
get { return m_Caps; } |
|||
set { m_Caps = value; } |
|||
} |
|||
|
|||
public CanvasElement parent |
|||
{ |
|||
get { return m_Parent; } |
|||
set { m_Parent = value; } |
|||
} |
|||
|
|||
public Object target |
|||
{ |
|||
get { return m_Target; } |
|||
set { m_Target = value; } |
|||
} |
|||
|
|||
public bool selected |
|||
{ |
|||
get { return m_Selected; } |
|||
set |
|||
{ |
|||
if ((caps & Capabilities.Unselectable) == Capabilities.Unselectable) |
|||
value = false; |
|||
m_Selected = value; |
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
e.selected = value; |
|||
} |
|||
Invalidate(); |
|||
} |
|||
} |
|||
|
|||
public bool collapsed |
|||
{ |
|||
get { return m_Collapsed; } |
|||
set |
|||
{ |
|||
m_Collapsed = value; |
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
e.collapsed = value; |
|||
} |
|||
UpdateModel(UpdateType.Update); |
|||
} |
|||
} |
|||
|
|||
public T FindParent<T>() where T : class |
|||
{ |
|||
if (m_Parent == null) |
|||
return default(T); |
|||
|
|||
T casted = m_Parent as T; |
|||
|
|||
if (casted != null) |
|||
{ |
|||
return casted; |
|||
} |
|||
|
|||
return m_Parent.FindParent<T>(); |
|||
} |
|||
|
|||
public Canvas2D ParentCanvas() |
|||
{ |
|||
CanvasElement e = FindTopMostParent(); |
|||
if (e is Canvas2D) |
|||
return e as Canvas2D; |
|||
|
|||
return e.parent as Canvas2D; |
|||
} |
|||
|
|||
public CanvasElement FindTopMostParent() |
|||
{ |
|||
if (m_Parent == null) |
|||
return null; |
|||
|
|||
if (m_Parent is Canvas2D) |
|||
return this; |
|||
|
|||
return m_Parent.FindTopMostParent(); |
|||
} |
|||
|
|||
public void ZSort() |
|||
{ |
|||
m_Children = m_Children.OrderBy(c => c.zIndex).ToList(); |
|||
} |
|||
|
|||
public bool IsCollapsed() |
|||
{ |
|||
if ((caps & Capabilities.DoesNotCollapse) == Capabilities.DoesNotCollapse) |
|||
return false; |
|||
|
|||
return collapsed; |
|||
} |
|||
|
|||
public Rect elementRect |
|||
{ |
|||
get |
|||
{ |
|||
Rect rect = new Rect |
|||
{ |
|||
xMin = m_Translation.x, |
|||
yMin = m_Translation.y |
|||
}; |
|||
rect.xMax = rect.xMin + m_Scale.x; |
|||
rect.yMax = rect.yMin + m_Scale.y; |
|||
return rect; |
|||
} |
|||
} |
|||
|
|||
public virtual Rect boundingRect |
|||
{ |
|||
get |
|||
{ |
|||
Rect rect = new Rect |
|||
{ |
|||
xMin = m_Translation.x, |
|||
yMin = m_Translation.y |
|||
}; |
|||
rect.xMax = rect.xMin + m_Scale.x; |
|||
rect.yMax = rect.yMin + m_Scale.y; |
|||
|
|||
for (int i = 0; i < m_Children.Count; i++) |
|||
{ |
|||
CanvasElement e = m_Children[i]; |
|||
Rect childRect = e.boundingRect; |
|||
childRect.x += rect.x; |
|||
childRect.y += rect.y; |
|||
rect = RectUtils.Encompass(rect, childRect); |
|||
} |
|||
|
|||
return rect; |
|||
} |
|||
} |
|||
|
|||
public Rect canvasBoundingRect |
|||
{ |
|||
get |
|||
{ |
|||
Rect currentRect = boundingRect; |
|||
CanvasElement p = parent; |
|||
while (p != null) |
|||
{ |
|||
if (p is Canvas2D) |
|||
break; |
|||
|
|||
currentRect.x += p.boundingRect.x; |
|||
currentRect.y += p.boundingRect.y; |
|||
p = p.parent; |
|||
} |
|||
return currentRect; |
|||
} |
|||
} |
|||
|
|||
public int zIndex |
|||
{ |
|||
get { return m_ZIndex; } |
|||
set { m_ZIndex = value; } |
|||
} |
|||
|
|||
public Texture texture |
|||
{ |
|||
get { return m_Texture; } |
|||
} |
|||
|
|||
public Vector3 translation |
|||
{ |
|||
get { return m_Translation; } |
|||
set { m_Translation = value; } |
|||
} |
|||
|
|||
public Vector3 scale |
|||
{ |
|||
get { return m_Scale; } |
|||
set { m_Scale = value; } |
|||
} |
|||
|
|||
public virtual bool Contains(Vector2 point) |
|||
{ |
|||
return canvasBoundingRect.Contains(point); |
|||
} |
|||
|
|||
public virtual bool Intersects(Rect rect) |
|||
{ |
|||
if (RectUtils.Contains(rect, canvasBoundingRect)) |
|||
{ |
|||
return true; |
|||
} |
|||
else if (canvasBoundingRect.Overlaps(rect)) |
|||
{ |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public virtual void DeepInvalidate() |
|||
{ |
|||
m_Dirty = true; |
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
e.DeepInvalidate(); |
|||
} |
|||
|
|||
foreach (CanvasElement d in m_Dependencies) |
|||
{ |
|||
d.DeepInvalidate(); |
|||
} |
|||
} |
|||
|
|||
public void Invalidate() |
|||
{ |
|||
m_Dirty = true; |
|||
|
|||
foreach (CanvasElement d in m_Dependencies) |
|||
{ |
|||
d.Invalidate(); |
|||
} |
|||
|
|||
CanvasElement theParent = parent; |
|||
|
|||
if (theParent == null || (theParent is Canvas2D)) |
|||
return; |
|||
|
|||
while (theParent.parent != null && !(theParent.parent is Canvas2D)) |
|||
{ |
|||
theParent = theParent.parent; |
|||
} |
|||
|
|||
theParent.DeepInvalidate(); |
|||
} |
|||
|
|||
public void AddManipulator(IManipulate m) |
|||
{ |
|||
m.AttachTo(this); |
|||
} |
|||
|
|||
private void CreateTexture() |
|||
{ |
|||
Rect textureRect = boundingRect; |
|||
m_Texture = new RenderTexture((int)textureRect.width, (int)textureRect.height, 0, RenderTextureFormat.ARGB32); |
|||
} |
|||
|
|||
private RenderTexture m_OldActive; |
|||
|
|||
public bool PrepareRender() |
|||
{ |
|||
if (Event.current.type != EventType.Repaint) |
|||
return false; |
|||
|
|||
if (!m_Dirty || !m_SupportsRenderToTexture) |
|||
return false; |
|||
|
|||
// if null create
|
|||
// if size is differnt destroy / create
|
|||
if (m_Texture == null) |
|||
CreateTexture(); |
|||
else if ((int)boundingRect.width != m_Texture.width || (int)boundingRect.height != m_Texture.height) |
|||
{ |
|||
Object.DestroyImmediate(m_Texture); |
|||
CreateTexture(); |
|||
} |
|||
|
|||
m_OldActive = RenderTexture.active; |
|||
RenderTexture.active = m_Texture; |
|||
|
|||
Layout(); |
|||
m_Dirty = false; |
|||
return true; |
|||
} |
|||
|
|||
public void EndRender(float renderTextureHeight) |
|||
{ |
|||
RenderTexture.active = m_OldActive; |
|||
} |
|||
|
|||
bool Collide(Vector2 p) |
|||
{ |
|||
return boundingRect.Contains(p); |
|||
} |
|||
|
|||
public CanvasElement[] Children() |
|||
{ |
|||
return m_Children.ToArray(); |
|||
} |
|||
|
|||
public bool HasDependency<T>() |
|||
{ |
|||
foreach (CanvasElement d in m_Dependencies) |
|||
{ |
|||
if (d is T) |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public void AddDependency(CanvasElement e) |
|||
{ |
|||
m_Dependencies.Add(e); |
|||
} |
|||
|
|||
public CanvasElement[] FindChildren<T>() |
|||
{ |
|||
List<CanvasElement> filtered = new List<CanvasElement>(); |
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
CanvasElement[] inner = e.FindChildren<T>(); |
|||
filtered.AddRange(inner); |
|||
|
|||
if (e is T) |
|||
{ |
|||
filtered.Add(e); |
|||
} |
|||
} |
|||
|
|||
return filtered.ToArray(); |
|||
} |
|||
|
|||
public virtual void DebugDraw() |
|||
{ |
|||
Handles.DrawSolidRectangleWithOutline(canvasBoundingRect, new Color(1.0f, 0.0f, 0.0f, 0.2f), new Color(1.0f, 0.0f, 0.0f, 0.4f)); |
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
e.DebugDraw(); |
|||
} |
|||
} |
|||
|
|||
public virtual void Clear() |
|||
{ |
|||
m_Texture = null; |
|||
m_Children.Clear(); |
|||
} |
|||
|
|||
public virtual void UpdateModel(UpdateType t) |
|||
{ |
|||
foreach (CanvasElement c in m_Children) |
|||
{ |
|||
c.UpdateModel(t); |
|||
} |
|||
foreach (CanvasElement e in m_Dependencies) |
|||
{ |
|||
e.UpdateModel(t); |
|||
} |
|||
} |
|||
|
|||
public virtual void AddChild(CanvasElement e) |
|||
{ |
|||
e.parent = this; |
|||
if (!(e.parent is Canvas2D)) |
|||
{ |
|||
e.collapsed = collapsed; |
|||
} |
|||
m_Children.Add(e); |
|||
} |
|||
|
|||
public virtual void Layout() |
|||
{ |
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
e.Layout(); |
|||
} |
|||
} |
|||
|
|||
public virtual void OnRenderList(List<CanvasElement> visibleList, Canvas2D parent) |
|||
{ |
|||
Rect screenRect = new Rect |
|||
{ |
|||
min = parent.MouseToCanvas(parent.clientRect.min), |
|||
max = parent.MouseToCanvas(new Vector2(Screen.width, Screen.height)) |
|||
}; |
|||
Rect thisRect = boundingRect; |
|||
for (int i = 0; i < visibleList.Count; i++) |
|||
{ |
|||
CanvasElement e = visibleList[i]; |
|||
if (e.texture != null) |
|||
{ |
|||
float ratio = 1.0f; |
|||
Rect r = new Rect(e.translation.x, e.translation.y, e.texture.width, e.texture.height); |
|||
if (r.y < screenRect.y) |
|||
{ |
|||
float overlap = (screenRect.y - r.y); |
|||
r.y = screenRect.y; |
|||
r.height -= overlap; |
|||
if (r.height < 0.0f) |
|||
r.height = 0.0f; |
|||
ratio = r.height / e.texture.height; |
|||
} |
|||
|
|||
Graphics.DrawTexture(r, e.texture, new Rect(0, 0, 1.0f, ratio), 0, 0, 0, 0); |
|||
} |
|||
else |
|||
e.Render(thisRect, parent); |
|||
|
|||
e.RenderWidgets(parent); |
|||
} |
|||
|
|||
if (OnWidget != null) |
|||
OnWidget(this, Event.current, parent); |
|||
} |
|||
|
|||
private void RenderWidgets(Canvas2D parent) |
|||
{ |
|||
if (OnWidget != null) |
|||
{ |
|||
OnWidget(this, Event.current, parent); |
|||
} |
|||
|
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
e.RenderWidgets(parent); |
|||
} |
|||
} |
|||
|
|||
public virtual bool DispatchEvents(Event evt, Canvas2D parent) |
|||
{ |
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
if (e.DispatchEvents(evt, parent)) |
|||
return true; |
|||
} |
|||
|
|||
return FireEvents(evt, parent, this); |
|||
} |
|||
|
|||
public bool FireEvents(Event evt, Canvas2D parent, CanvasElement target) |
|||
{ |
|||
if (parent != this && (evt.type == EventType.MouseDown)) |
|||
{ |
|||
if (!Contains(parent.MouseToCanvas(evt.mousePosition))) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
if (target == null) |
|||
{ |
|||
target = this; |
|||
} |
|||
|
|||
bool handled = false; |
|||
if (AllEvents != null) |
|||
{ |
|||
bool wasNotUsed = evt.type != EventType.Used; |
|||
|
|||
AllEvents(target, evt, parent); |
|||
if (wasNotUsed && evt.type == EventType.Used) |
|||
{ |
|||
parent.LogInfo("AllEvent handler on " + target); |
|||
} |
|||
} |
|||
|
|||
switch (evt.type) |
|||
{ |
|||
case EventType.MouseUp: |
|||
handled = MouseUp == null ? false : MouseUp(target, evt, parent); |
|||
break; |
|||
case EventType.MouseDown: |
|||
{ |
|||
if (evt.clickCount < 2) |
|||
{ |
|||
handled = MouseDown == null ? false : MouseDown(target, evt, parent); |
|||
break; |
|||
} |
|||
else |
|||
{ |
|||
handled = DoubleClick == null ? false : DoubleClick(target, evt, parent); |
|||
break; |
|||
} |
|||
} |
|||
case EventType.MouseDrag: |
|||
handled = MouseDrag == null ? false : MouseDrag(target, evt, parent); |
|||
break; |
|||
case EventType.DragPerform: |
|||
handled = DragPerform == null ? false : DragPerform(target, evt, parent); |
|||
break; |
|||
case EventType.DragExited: |
|||
handled = DragExited == null ? false : DragExited(target, evt, parent); |
|||
break; |
|||
case EventType.DragUpdated: |
|||
handled = DragUpdated == null ? false : DragUpdated(target, evt, parent); |
|||
break; |
|||
case EventType.ScrollWheel: |
|||
handled = ScrollWheel == null ? false : ScrollWheel(target, evt, parent); |
|||
break; |
|||
case EventType.KeyDown: |
|||
handled = KeyDown == null ? false : KeyDown(target, evt, parent); |
|||
break; |
|||
case EventType.ContextClick: |
|||
handled = ContextClick == null ? false : ContextClick(target, evt, parent); |
|||
break; |
|||
} |
|||
|
|||
return handled; |
|||
} |
|||
|
|||
public virtual void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
foreach (CanvasElement e in m_Children) |
|||
{ |
|||
e.Render(parentRect, canvas); |
|||
} |
|||
|
|||
if (OnWidget != null) |
|||
OnWidget(this, Event.current, canvas); |
|||
} |
|||
|
|||
public void AnimateScale(Vector2 from, Vector2 to) |
|||
{ |
|||
var canvas = ParentCanvas(); |
|||
m_Animationdata.scaleFrom = from; |
|||
m_Animationdata.scaleTo = to; |
|||
m_Animationdata.scaleTime = 0.0f; |
|||
canvas.OnLayout += OnAnimateScaleDelegate; |
|||
canvas.Invalidate(); |
|||
} |
|||
|
|||
private bool OnAnimateScaleDelegate(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
parent.Invalidate(); |
|||
Invalidate(); |
|||
scale = Vector2.Lerp(m_Animationdata.scaleFrom, m_Animationdata.scaleTo, m_Animationdata.scaleTime); |
|||
m_Animationdata.scaleTime += 0.01f; |
|||
if (m_Animationdata.scaleTime > 1.0f) |
|||
{ |
|||
parent.OnLayout -= OnAnimateScaleDelegate; |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 016cb4334319c3046aa191536ed1d06f |
|||
timeCreated: 1453892275 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: e5c459aeda2a58847acfe3ab3f00c61a |
|||
folderAsset: yes |
|||
timeCreated: 1453892275 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditorInternal.Experimental |
|||
{ |
|||
internal interface IBounds |
|||
{ |
|||
Rect boundingRect { get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 85d0a26797a67cb42be4361f3ac91ec3 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
public interface ICanvasDataSource |
|||
{ |
|||
CanvasElement[] FetchElements(); |
|||
void DeleteElement(CanvasElement e); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f082dcc2e07553348bab3e72bdf3c039 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: b66aa6e87ee581345a628ff2d8953060 |
|||
folderAsset: yes |
|||
timeCreated: 1453895629 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
public enum ManipulatorCapability |
|||
{ |
|||
MultiSelection = 0 |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b89f573c3f958e24aab00b09498e2ee3 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 242823048dd61f5478256c084e25322e |
|||
folderAsset: yes |
|||
timeCreated: 1453892275 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Reflection; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class PropertyData |
|||
{ |
|||
public PropertyData(FieldInfo f, object o1, object o2) |
|||
{ |
|||
field = f; |
|||
data0 = o1; |
|||
data1 = o2; |
|||
time = 0.0f; |
|||
curve = AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, 1.0f); //@todo replace this by google material curve
|
|||
} |
|||
|
|||
public FieldInfo field; |
|||
public object data0; |
|||
public object data1; |
|||
public float time; |
|||
public AnimationCurve curve; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 11d78ae739d7a894caaefd76a376daee |
|||
timeCreated: 1453892275 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 8f3113b42ac92ae4ba7535cadeef6e55 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 8a49e0bb9b3e3a74fb7c3e438a5d4c8a |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: f8f4625a3548686428af50801afdf80d |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace UnityEditor.Experimental.Graph |
|||
{ |
|||
public enum Direction |
|||
{ |
|||
Input = 0, |
|||
Output = 1, |
|||
Bidirectional = 2 |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2e1aeb12df361764784ba6664216731f |
|||
timeCreated: 1453892275 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine; |
|||
using UnityEditorInternal; |
|||
using UnityEditorInternal.Experimental; |
|||
|
|||
//#pragma warning disable 0414
|
|||
//#pragma warning disable 0219
|
|||
|
|||
namespace UnityEditor.Experimental.Graph |
|||
{ |
|||
internal class Edge<T> : CanvasElement where T : CanvasElement, IConnect |
|||
{ |
|||
private T m_Left; |
|||
private T m_Right; |
|||
private ICanvasDataSource m_Data; |
|||
|
|||
public Edge(ICanvasDataSource data, T left, T right) |
|||
{ |
|||
m_Data = data; |
|||
zIndex = 9999; |
|||
m_SupportsRenderToTexture = false; |
|||
left.AddDependency(this); |
|||
right.AddDependency(this); |
|||
m_Left = left; |
|||
m_Right = right; |
|||
|
|||
UpdateModel(UpdateType.Update); |
|||
|
|||
KeyDown += OnDeleteEdge; |
|||
} |
|||
|
|||
public T Left |
|||
{ |
|||
get { return m_Left; } |
|||
} |
|||
|
|||
public T Right |
|||
{ |
|||
get { return m_Right; } |
|||
} |
|||
|
|||
private bool OnDeleteEdge(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.keyCode == KeyCode.Delete) |
|||
{ |
|||
m_Data.DeleteElement(this); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public override bool Intersects(Rect rect) |
|||
{ |
|||
// first check coarse bounding box
|
|||
if (!base.Intersects(rect)) |
|||
return false; |
|||
|
|||
// bounding box check succeeded, do more fine grained check by checking intersection between the rectangles' diagonal
|
|||
// and the line segments
|
|||
|
|||
Vector3 from = m_Left.ConnectPosition(); |
|||
Vector3 to = m_Right.ConnectPosition(); |
|||
|
|||
if (to.x < from.x) |
|||
{ |
|||
Vector3 t = from; |
|||
from = to; |
|||
to = t; |
|||
} |
|||
|
|||
Vector3[] points, tangents; |
|||
EdgeConnector<T>.GetTangents(from, to, out points, out tangents); |
|||
Vector3[] allPoints = Handles.MakeBezierPoints(points[0], points[1], tangents[0], tangents[1], 20); |
|||
|
|||
for (int a = 0; a < allPoints.Length; a++) |
|||
{ |
|||
if (a >= allPoints.Length - 1) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
Vector2 segmentA = new Vector2(allPoints[a].x, allPoints[a].y); |
|||
Vector2 segmentB = new Vector2(allPoints[a + 1].x, allPoints[a + 1].y); |
|||
|
|||
if (RectUtils.IntersectsSegment(rect, segmentA, segmentB)) |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public override bool Contains(Vector2 canvasPosition) |
|||
{ |
|||
// first check coarse bounding box
|
|||
if (!base.Contains(canvasPosition)) |
|||
return false; |
|||
|
|||
// bounding box check succeeded, do more fine grained check by measuring distance to bezier points
|
|||
|
|||
Vector3 from = m_Left.ConnectPosition(); |
|||
Vector3 to = m_Right.ConnectPosition(); |
|||
|
|||
if (to.x < from.x) |
|||
{ |
|||
Vector3 t = from; |
|||
from = to; |
|||
to = t; |
|||
} |
|||
|
|||
Vector3[] points, tangents; |
|||
EdgeConnector<T>.GetTangents(from, to, out points, out tangents); |
|||
Vector3[] allPoints = Handles.MakeBezierPoints(points[0], points[1], tangents[0], tangents[1], 20); |
|||
|
|||
float minDistance = Mathf.Infinity; |
|||
foreach (Vector3 currentPoint in allPoints) |
|||
{ |
|||
float distance = Vector3.Distance(currentPoint, canvasPosition); |
|||
minDistance = Mathf.Min(minDistance, distance); |
|||
if (minDistance < 15.0f) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public override void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
Color edgeColor = selected ? Color.yellow : Color.white; |
|||
|
|||
Vector3 from = m_Left.ConnectPosition(); |
|||
Vector3 to = m_Right.ConnectPosition(); |
|||
|
|||
if (to.x < from.x) |
|||
{ |
|||
Vector3 t = from; |
|||
from = to; |
|||
to = t; |
|||
} |
|||
|
|||
Vector3[] points, tangents; |
|||
EdgeConnector<T>.GetTangents(from, to, out points, out tangents); |
|||
Handles.DrawBezier(points[0], points[1], tangents[0], tangents[1], edgeColor, null, 5f); |
|||
|
|||
// little widget on the middle of the edge
|
|||
Vector3[] allPoints = Handles.MakeBezierPoints(points[0], points[1], tangents[0], tangents[1], 20); |
|||
Color oldColor = Handles.color; |
|||
Handles.color = Color.blue; |
|||
Handles.DrawSolidDisc(allPoints[10], new Vector3(0.0f, 0.0f, -1.0f), 6f); |
|||
Handles.color = edgeColor; |
|||
Handles.DrawWireDisc(allPoints[10], new Vector3(0.0f, 0.0f, -1.0f), 6f); |
|||
Handles.DrawWireDisc(allPoints[10], new Vector3(0.0f, 0.0f, -1.0f), 5f); |
|||
|
|||
// dot on top of anchor showing it's connected
|
|||
Handles.color = new Color(0.3f, 0.4f, 1.0f, 1.0f); |
|||
Handles.DrawSolidDisc(from, new Vector3(0.0f, 0.0f, -1.0f), 4f); |
|||
Handles.DrawSolidDisc(to, new Vector3(0.0f, 0.0f, -1.0f), 4f); |
|||
|
|||
/*if (EditorApplication.isPlaying) |
|||
{ |
|||
Handles.color = Color.red; |
|||
Handles.DrawSolidDisc(allPoints[m_RealtimeFeedbackPointIndex], new Vector3(0.0f, 0.0f, -1.0f), 6f); |
|||
|
|||
m_RealtimeFeedbackPointIndex++; |
|||
if (m_RealtimeFeedbackPointIndex >= 20) |
|||
{ |
|||
m_RealtimeFeedbackPointIndex = 0; |
|||
} |
|||
}*/ |
|||
Handles.color = oldColor; |
|||
} |
|||
|
|||
public override void UpdateModel(UpdateType t) |
|||
{ |
|||
Vector3 from = m_Left.ConnectPosition(); |
|||
Vector3 to = m_Right.ConnectPosition(); |
|||
|
|||
Rect r = new Rect(); |
|||
r.min = new Vector2(Math.Min(from.x, to.x), Math.Min(from.y, to.y)); |
|||
r.max = new Vector2(Math.Max(from.x, to.x), Math.Max(from.y, to.y)); |
|||
|
|||
translation = r.min; |
|||
scale = new Vector3(r.width, r.height, 1.0f); |
|||
|
|||
base.UpdateModel(t); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 42ac60ec8ea24294c84de6e2c39b675f |
|||
timeCreated: 1453892275 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental.Graph |
|||
{ |
|||
internal class EdgeConnector<T> : IManipulate where T : IConnect |
|||
{ |
|||
private static readonly Color s_EdgeColor = new Color(1.0f, 1.0f, 1.0f, 0.8f); |
|||
private static readonly Color s_ActiveEdgeColor = new Color(0.2f, 0.4f, 1.0f, 0.8f); |
|||
|
|||
private Vector2 m_Start = Vector2.zero; |
|||
private Vector2 m_End = Vector2.zero; |
|||
private Color m_Color = s_EdgeColor; |
|||
private IConnect m_SnappedTarget; |
|||
private IConnect m_SnappedSource; |
|||
|
|||
private List<IConnect> m_CompatibleAnchors = new List<IConnect>(); |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.MouseUp += EndDrag; |
|||
element.MouseDown += StartDrag; |
|||
element.MouseDrag += MouseDrag; |
|||
} |
|||
|
|||
private bool StartDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (e.button != 0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
element.OnWidget += DrawEdge; |
|||
|
|||
if (element.collapsed) |
|||
return false; |
|||
|
|||
canvas.StartCapture(this, element); |
|||
m_Start = m_End = element.canvasBoundingRect.center; |
|||
|
|||
e.Use(); |
|||
|
|||
IConnect cnx = element as IConnect; |
|||
if (cnx != null) |
|||
{ |
|||
cnx.Highlight(true); |
|||
} |
|||
EndSnap(); |
|||
|
|||
// find compatible anchors
|
|||
m_CompatibleAnchors.Clear(); |
|||
|
|||
Rect screenRect = new Rect |
|||
{ |
|||
min = canvas.MouseToCanvas(new Vector2(0.0f, 0.0f)), |
|||
max = canvas.MouseToCanvas(new Vector2(Screen.width, Screen.height)) |
|||
}; |
|||
|
|||
CanvasElement[] visibleAnchors = canvas.Pick<T>(screenRect); |
|||
NodeAdapter nodeAdapter = new NodeAdapter(); |
|||
foreach (CanvasElement anchor in visibleAnchors) |
|||
{ |
|||
IConnect toCnx = anchor as IConnect; |
|||
if (toCnx == null) |
|||
continue; |
|||
|
|||
bool isBidirectional = ((cnx.GetDirection() == Direction.Bidirectional) || |
|||
(toCnx.GetDirection() == Direction.Bidirectional)); |
|||
|
|||
if (cnx.GetDirection() != toCnx.GetDirection() || isBidirectional) |
|||
{ |
|||
if (nodeAdapter.GetAdapter(cnx.Source(), toCnx.Source()) != null) |
|||
{ |
|||
m_CompatibleAnchors.Add(toCnx); |
|||
} |
|||
} |
|||
} |
|||
|
|||
canvas.OnOverlay += HighlightCompatibleAnchors; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private bool EndDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
element.OnWidget -= DrawEdge; |
|||
|
|||
canvas.EndCapture(); |
|||
IConnect cnx = element as IConnect; |
|||
if (cnx != null) |
|||
{ |
|||
cnx.Highlight(false); |
|||
} |
|||
|
|||
if (m_SnappedSource == null && m_SnappedTarget == null) |
|||
{ |
|||
cnx.OnConnect(null); |
|||
} |
|||
else if (m_SnappedSource != null && m_SnappedTarget != null) |
|||
{ |
|||
NodeAdapter nodeAdapter = new NodeAdapter(); |
|||
if (nodeAdapter.CanAdapt(m_SnappedSource.Source(), m_SnappedTarget.Source())) |
|||
{ |
|||
nodeAdapter.Connect(m_SnappedSource.Source(), m_SnappedTarget.Source()); |
|||
cnx.OnConnect(m_SnappedTarget); |
|||
} |
|||
} |
|||
|
|||
EndSnap(); |
|||
e.Use(); |
|||
canvas.OnOverlay -= HighlightCompatibleAnchors; |
|||
return true; |
|||
} |
|||
|
|||
private bool MouseDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
m_End = canvas.MouseToCanvas(e.mousePosition); |
|||
e.Use(); |
|||
|
|||
m_Color = s_EdgeColor; |
|||
|
|||
IConnect thisCnx = element as IConnect; |
|||
// find target anchor under us
|
|||
CanvasElement elementUnderMouse = canvas.PickSingle<T>(e.mousePosition); |
|||
if (elementUnderMouse != null) |
|||
{ |
|||
IConnect cnx = elementUnderMouse as IConnect; |
|||
if (cnx == null) |
|||
{ |
|||
Debug.LogError("PickSingle returned an incompatible element: does not support IConnect interface"); |
|||
return true; |
|||
} |
|||
|
|||
if (m_CompatibleAnchors.Exists(ic => ic == cnx)) |
|||
{ |
|||
StartSnap(thisCnx, cnx); |
|||
m_Color = s_ActiveEdgeColor; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
EndSnap(); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private void StartSnap(IConnect from, IConnect to) |
|||
{ |
|||
EndSnap(); |
|||
m_SnappedTarget = to; |
|||
m_SnappedSource = from; |
|||
m_SnappedTarget.Highlight(true); |
|||
} |
|||
|
|||
private void EndSnap() |
|||
{ |
|||
if (m_SnappedTarget != null) |
|||
{ |
|||
m_SnappedTarget.Highlight(false); |
|||
m_SnappedTarget = null; |
|||
} |
|||
} |
|||
|
|||
private bool DrawEdge(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
bool invert = m_End.x < m_Start.x; |
|||
Vector3[] points, tangents; |
|||
GetTangents(invert ? m_End : m_Start, invert ? m_Start : m_End, out points, out tangents); |
|||
Handles.DrawBezier(points[0], points[1], tangents[0], tangents[1], m_Color, null, 5f); |
|||
|
|||
// little widget on the middle of the edge
|
|||
Vector3[] allPoints = Handles.MakeBezierPoints(points[0], points[1], tangents[0], tangents[1], 20); |
|||
Color oldColor = Handles.color; |
|||
Handles.color = m_Color; |
|||
Handles.DrawSolidDisc(allPoints[10], new Vector3(0.0f, 0.0f, -1.0f), 6f); |
|||
Handles.color = oldColor; |
|||
return true; |
|||
} |
|||
|
|||
private bool HighlightCompatibleAnchors(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
foreach (IConnect visible in m_CompatibleAnchors) |
|||
{ |
|||
visible.RenderOverlay(canvas); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public static void GetTangents(Vector2 start, Vector2 end, out Vector3[] points, out Vector3[] tangents) |
|||
{ |
|||
points = new Vector3[] {start, end}; |
|||
tangents = new Vector3[2]; |
|||
|
|||
const float minTangent = 30; |
|||
|
|||
float weight = (start.y < end.y) ? .3f : .7f; |
|||
weight = .5f; |
|||
float weight2 = 1 - weight; |
|||
float y = 0; |
|||
|
|||
if (start.x > end.x) |
|||
{ |
|||
weight2 = weight = -.25f; |
|||
float aspect = (start.x - end.x) / (start.y - end.y); |
|||
if (Mathf.Abs(aspect) > .5f) |
|||
{ |
|||
float asp = (Mathf.Abs(aspect) - .5f) / 8; |
|||
asp = Mathf.Sqrt(asp); |
|||
y = Mathf.Min(asp * 80, 80); |
|||
if (start.y > end.y) |
|||
y = -y; |
|||
} |
|||
} |
|||
float cleverness = Mathf.Clamp01(((start - end).magnitude - 10) / 50); |
|||
|
|||
tangents[0] = start + new Vector2((end.x - start.x) * weight + minTangent, y) * cleverness; |
|||
tangents[1] = end + new Vector2((end.x - start.x) * -weight2 - minTangent, -y) * cleverness; |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 98b87db3ab002454da9107d8afb934c6 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental.Graph |
|||
{ |
|||
public interface IConnect |
|||
{ |
|||
Direction GetDirection(); |
|||
void Highlight(bool highlighted); |
|||
void RenderOverlay(Canvas2D canvas); |
|||
object Source(); |
|||
Vector3 ConnectPosition(); |
|||
void OnConnect(IConnect other); |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6cdef18ffc897474ebbe69aec78479df |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Runtime.CompilerServices; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental.Graph |
|||
{ |
|||
public class NodeAdapter |
|||
{ |
|||
private static List<MethodInfo> s_TypeAdapters; |
|||
private static Dictionary<int, MethodInfo> s_NodeAdapterDictionary; |
|||
|
|||
public bool CanAdapt(object a, object b) |
|||
{ |
|||
if (a == b) |
|||
return false; // self connections are not permitted
|
|||
|
|||
if (a == null || b == null) |
|||
return false; |
|||
|
|||
MethodInfo mi = GetAdapter(a, b); |
|||
if (mi == null) |
|||
{ |
|||
Debug.Log("adapter node not found for: " + a.GetType() + " -> " + b.GetType()); |
|||
} |
|||
return mi != null; |
|||
} |
|||
|
|||
public bool Connect(object a, object b) |
|||
{ |
|||
MethodInfo mi = GetAdapter(a, b); |
|||
if (mi == null) |
|||
{ |
|||
Debug.LogError("Attempt to connect 2 unadaptable types: " + a.GetType() + " -> " + b.GetType()); |
|||
return false; |
|||
} |
|||
object retVal = mi.Invoke(this, new[] {this, a, b}); |
|||
return (bool)retVal; |
|||
} |
|||
|
|||
IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly, Type extendedType) |
|||
{ |
|||
var query = from type in assembly.GetTypes() |
|||
where type.IsSealed && !type.IsGenericType && !type.IsNested |
|||
from method in type.GetMethods(BindingFlags.Static |
|||
| BindingFlags.Public | BindingFlags.NonPublic) |
|||
where method.IsDefined(typeof(ExtensionAttribute), false) |
|||
where method.GetParameters()[0].ParameterType == extendedType |
|||
select method; |
|||
return query; |
|||
} |
|||
|
|||
public MethodInfo GetAdapter(object a, object b) |
|||
{ |
|||
if (a == null || b == null) |
|||
return null; |
|||
|
|||
if (s_NodeAdapterDictionary == null) |
|||
{ |
|||
s_NodeAdapterDictionary = new Dictionary<int, MethodInfo>(); |
|||
|
|||
// add extension methods
|
|||
AppDomain currentDomain = AppDomain.CurrentDomain; |
|||
foreach (Assembly assembly in currentDomain.GetAssemblies()) |
|||
{ |
|||
foreach (MethodInfo method in GetExtensionMethods(assembly, typeof(NodeAdapter))) |
|||
{ |
|||
var methodParams = method.GetParameters(); |
|||
if (methodParams.Count() == 3) |
|||
{ |
|||
string pa = methodParams[1].ParameterType + methodParams[2].ParameterType.ToString(); |
|||
s_NodeAdapterDictionary.Add(pa.GetHashCode(), method); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
string s = a.GetType().ToString() + b.GetType(); |
|||
|
|||
try |
|||
{ |
|||
return s_NodeAdapterDictionary[s.GetHashCode()]; |
|||
} |
|||
catch (Exception) |
|||
{} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public MethodInfo GetTypeAdapter(Type from, Type to) |
|||
{ |
|||
if (s_TypeAdapters == null) |
|||
{ |
|||
s_TypeAdapters = new List<MethodInfo>(); |
|||
AppDomain currentDomain = AppDomain.CurrentDomain; |
|||
foreach (Assembly assembly in currentDomain.GetAssemblies()) |
|||
{ |
|||
try |
|||
{ |
|||
foreach (Type temptype in assembly.GetTypes()) |
|||
{ |
|||
MethodInfo[] methodInfos = temptype.GetMethods(BindingFlags.Public | BindingFlags.Static); |
|||
foreach (MethodInfo i in methodInfos) |
|||
{ |
|||
object[] allAttrs = i.GetCustomAttributes(typeof(TypeAdapter), false); |
|||
if (allAttrs.Count() > 0) |
|||
{ |
|||
s_TypeAdapters.Add(i); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Debug.Log(ex); |
|||
} |
|||
} |
|||
} |
|||
|
|||
foreach (MethodInfo i in s_TypeAdapters) |
|||
{ |
|||
if (i.ReturnType == to) |
|||
{ |
|||
ParameterInfo[] allParams = i.GetParameters(); |
|||
if (allParams.Count() == 1) |
|||
{ |
|||
if (allParams[0].ParameterType == from) |
|||
return i; |
|||
} |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f0a0f4ce97dd9884399ae31a0cb6c24a |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
|
|||
namespace UnityEditor.Experimental.Graph |
|||
{ |
|||
class TypeAdapter : Attribute |
|||
{ |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: cc8a308462cd8f84aa87b1c735a99800 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
/// <summary>
|
|||
/// CanvasLayout : the base class for vertical and horizontal layouts
|
|||
/// WARNING: these layout classes have pretty limited usage.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Do not use this class directly. Use on of the specializations or derive your own
|
|||
/// </remarks>
|
|||
internal class CanvasLayout |
|||
{ |
|||
protected CanvasElement m_Owner; |
|||
protected CanvasLayout m_Parent; |
|||
protected Vector4 m_Padding = Vector4.zero; |
|||
protected float m_Left; |
|||
protected float m_Height; |
|||
protected float m_Width; |
|||
protected List<CanvasLayout> m_Children = new List<CanvasLayout>(); |
|||
protected List<CanvasElement> m_Elements = new List<CanvasElement>(); |
|||
|
|||
public float height |
|||
{ |
|||
get |
|||
{ |
|||
float maxHeight = m_Height; |
|||
foreach (CanvasLayout l in m_Children) |
|||
{ |
|||
maxHeight = Mathf.Max(maxHeight, l.height); |
|||
} |
|||
return maxHeight + paddingTop + paddingBottom; |
|||
} |
|||
} |
|||
|
|||
public float width |
|||
{ |
|||
get |
|||
{ |
|||
float maxWidth = m_Width; |
|||
foreach (CanvasLayout l in m_Children) |
|||
{ |
|||
maxWidth = Mathf.Max(maxWidth, l.width); |
|||
} |
|||
return maxWidth + paddingLeft + paddingRight; |
|||
} |
|||
} |
|||
|
|||
public CanvasLayout(CanvasElement e) |
|||
{ |
|||
m_Owner = e; |
|||
} |
|||
|
|||
public CanvasLayout(CanvasLayout p) |
|||
{ |
|||
m_Parent = p; |
|||
m_Owner = p.Owner(); |
|||
} |
|||
|
|||
public CanvasElement Owner() |
|||
{ |
|||
if (m_Owner != null) |
|||
return m_Owner; |
|||
|
|||
if (m_Parent != null) |
|||
return m_Parent.Owner(); |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public float left |
|||
{ |
|||
get { return m_Left; } |
|||
set { m_Left = value; } |
|||
} |
|||
|
|||
public float paddingLeft |
|||
{ |
|||
get { return m_Padding.w; } |
|||
set { m_Padding.w = value; } |
|||
} |
|||
|
|||
public float paddingRight |
|||
{ |
|||
get { return m_Padding.y; } |
|||
set { m_Padding.y = value; } |
|||
} |
|||
|
|||
public float paddingTop |
|||
{ |
|||
get { return m_Padding.x; } |
|||
set { m_Padding.x = value; } |
|||
} |
|||
|
|||
public float paddingBottom |
|||
{ |
|||
get { return m_Padding.z; } |
|||
set { m_Padding.z = value; } |
|||
} |
|||
|
|||
public virtual void LayoutElement(CanvasElement c) |
|||
{ |
|||
m_Elements.Add(c); |
|||
} |
|||
|
|||
public virtual void LayoutElements(CanvasElement[] arrayOfElements) |
|||
{ |
|||
for (int a = 0; a < arrayOfElements.Length; a++) |
|||
{ |
|||
m_Elements.Add(arrayOfElements[a]); |
|||
} |
|||
} |
|||
|
|||
public void AddSpacer(int pixels) |
|||
{ |
|||
float collapsedFactor = m_Owner.IsCollapsed() ? 0.0f : 1.0f; |
|||
m_Height += pixels * collapsedFactor; |
|||
} |
|||
|
|||
public virtual void DebugDraw() |
|||
{ |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6962f04c3435c0e4a99a7361ff10ba32 |
|||
timeCreated: 1453895629 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditorInternal.Experimental; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
/// <summary>
|
|||
/// CanvasVerticalLayout : Helps layouting a group of canvas elements vertically
|
|||
/// </summary>
|
|||
internal class CanvasVerticalLayout : CanvasLayout |
|||
{ |
|||
public CanvasVerticalLayout(CanvasElement e) |
|||
: base(e) |
|||
{ |
|||
} |
|||
|
|||
public override void LayoutElements(CanvasElement[] arrayOfElements) |
|||
{ |
|||
for (int a = 0; a < arrayOfElements.Length; a++) |
|||
{ |
|||
LayoutElement(arrayOfElements[a]); |
|||
} |
|||
base.LayoutElements(arrayOfElements); |
|||
} |
|||
|
|||
public override void LayoutElement(CanvasElement c) |
|||
{ |
|||
float collapsedFactor = m_Owner.IsCollapsed() ? 0.0f : 1.0f; |
|||
if ((c.caps & CanvasElement.Capabilities.DoesNotCollapse) == CanvasElement.Capabilities.DoesNotCollapse) |
|||
{ |
|||
collapsedFactor = 1.0f; |
|||
} |
|||
|
|||
m_Height += m_Padding.x * collapsedFactor; |
|||
//c.translation = new Vector3(m_Padding.y + c.translation.x, height*collapsedFactor, 0.0f);
|
|||
c.translation = new Vector3(c.translation.x, height * collapsedFactor, 0.0f); |
|||
c.scale = new Vector3(c.scale.x, c.scale.y * collapsedFactor, 1.0f); |
|||
m_Height += (c.scale.y + m_Padding.z) * collapsedFactor; |
|||
m_Width = Mathf.Max(m_Width, c.scale.x); |
|||
Owner().AddChild(c); |
|||
base.LayoutElement(c); |
|||
} |
|||
|
|||
public override void DebugDraw() |
|||
{ |
|||
if (m_Elements.Count() == 0) |
|||
return; |
|||
|
|||
Rect encompassingRect = m_Elements[0].canvasBoundingRect; |
|||
List<Rect> elementRects = new List<Rect>(); |
|||
foreach (CanvasElement e in m_Elements) |
|||
{ |
|||
elementRects.Add(e.canvasBoundingRect); |
|||
encompassingRect = RectUtils.Encompass(encompassingRect, e.canvasBoundingRect); |
|||
} |
|||
|
|||
Vector3[] points = |
|||
{ |
|||
new Vector3(encompassingRect.xMin, encompassingRect.yMin, 0.0f), |
|||
new Vector3(encompassingRect.xMax, encompassingRect.yMin, 0.0f), |
|||
new Vector3(encompassingRect.xMax, encompassingRect.yMax, 0.0f), |
|||
new Vector3(encompassingRect.xMin, encompassingRect.yMax, 0.0f) |
|||
}; |
|||
|
|||
Color prevColor = GUI.color; |
|||
GUI.color = new Color(1.0f, 0.6f, 0.0f, 1.0f); |
|||
Handles.DrawDottedLine(points[0], points[1], 5.0f); |
|||
Handles.DrawDottedLine(points[1], points[2], 5.0f); |
|||
Handles.DrawDottedLine(points[2], points[3], 5.0f); |
|||
Handles.DrawDottedLine(points[3], points[0], 5.0f); |
|||
GUI.color = prevColor; |
|||
|
|||
foreach (Rect r in elementRects) |
|||
{ |
|||
Vector2 from = new Vector2(r.xMin, r.yMax); |
|||
Vector2 to = new Vector2(encompassingRect.xMax, r.yMax); |
|||
|
|||
DrawDottedLine(from, to, 5.0f, new Color(1.0f, 0.6f, 0.0f, 1.0f)); |
|||
} |
|||
} |
|||
|
|||
private void DrawDottedLine(Vector3 p1, Vector3 p2, float segmentsLength, Color col) |
|||
{ |
|||
UIHelpers.ApplyWireMaterial(); |
|||
|
|||
GL.Begin(GL.LINES); |
|||
GL.Color(col); |
|||
|
|||
float length = Vector3.Distance(p1, p2); // ignore z component
|
|||
int count = Mathf.CeilToInt(length / segmentsLength); |
|||
for (int i = 0; i < count; i += 2) |
|||
{ |
|||
GL.Vertex((Vector3.Lerp(p1, p2, i * segmentsLength / length))); |
|||
GL.Vertex((Vector3.Lerp(p1, p2, (i + 1) * segmentsLength / length))); |
|||
} |
|||
|
|||
GL.End(); |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4af706ffecc72fc4187eda927b3e1569 |
|||
timeCreated: 1453895629 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class ContextualMenu : IManipulate |
|||
{ |
|||
private ManipulateDelegate m_Callback; |
|||
private Object m_CustomData; |
|||
|
|||
public ContextualMenu(ManipulateDelegate callback) |
|||
{ |
|||
m_Callback = callback; |
|||
m_CustomData = null; |
|||
} |
|||
|
|||
public ContextualMenu(ManipulateDelegate callback, Object customData) |
|||
{ |
|||
m_Callback = callback; |
|||
m_CustomData = customData; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.ContextClick += OnContextMenu; |
|||
} |
|||
|
|||
private bool OnContextMenu(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
e.Use(); |
|||
return m_Callback(e, parent, m_CustomData); |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e2e1bae53903e844482874e96c6e516d |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class DragDrop : IManipulate |
|||
{ |
|||
private ManipulateDelegate m_Callback; |
|||
private Object m_CustomData; |
|||
|
|||
public DragDrop(ManipulateDelegate callback) |
|||
{ |
|||
m_Callback = callback; |
|||
m_CustomData = null; |
|||
} |
|||
|
|||
public DragDrop(ManipulateDelegate callback, Object customData) |
|||
{ |
|||
m_Callback = callback; |
|||
m_CustomData = customData; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.DragPerform += OnDragAndDropEvent; |
|||
element.DragUpdated += OnDragAndDropEvent; |
|||
element.DragExited += OnDragAndDropEvent; |
|||
} |
|||
|
|||
private bool OnDragAndDropEvent(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
return m_Callback(e, parent, m_CustomData); |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fdad93a3bca265848844a5a8fb14e4f0 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class Draggable : IManipulate |
|||
{ |
|||
private EventModifiers m_ActivatorModifiers; |
|||
private int m_ActivatorButton; |
|||
|
|||
public Draggable() |
|||
{ |
|||
m_ActivatorButton = 0; |
|||
m_ActivatorModifiers = EventModifiers.None; |
|||
} |
|||
|
|||
public Draggable(int button, EventModifiers activator) |
|||
{ |
|||
m_ActivatorButton = button; |
|||
m_ActivatorModifiers = activator; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
if (cap == ManipulatorCapability.MultiSelection) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.MouseDrag += MouseDrag; |
|||
element.MouseUp += EndDrag; |
|||
element.MouseDown += StartDrag; |
|||
} |
|||
|
|||
private bool StartDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.button != m_ActivatorButton || m_ActivatorModifiers != e.modifiers) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
canvas.StartCapture(this, element); |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool EndDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
canvas.EndCapture(); |
|||
|
|||
if (canvas.selection.Count == 0) |
|||
{ |
|||
canvas.AddToSelection(element); |
|||
} |
|||
|
|||
element.UpdateModel(UpdateType.Update); |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool MouseDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
float scaleFactorX = element == canvas ? 1.0f : 1.0f / canvas.scale.x; |
|||
float scaleFactorY = element == canvas ? 1.0f : 1.0f / canvas.scale.y; |
|||
|
|||
Vector3 tx = element.translation; |
|||
tx.x += e.delta.x * scaleFactorX; |
|||
tx.y += e.delta.y * scaleFactorY; |
|||
element.translation = tx; |
|||
element.UpdateModel(UpdateType.Candidate); |
|||
e.Use(); |
|||
|
|||
return true; |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5685891fb9245eb4b9ef42e2f2f0015a |
|||
timeCreated: 1453892275 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEditorInternal; |
|||
using UnityEditorInternal.Experimental; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class Frame : IManipulate |
|||
{ |
|||
public enum FrameType |
|||
{ |
|||
All = 0, |
|||
Selection = 1 |
|||
}; |
|||
|
|||
private readonly FrameType m_Type; |
|||
|
|||
public Frame(FrameType type) |
|||
{ |
|||
m_Type = type; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.KeyDown += KeyDown; |
|||
} |
|||
|
|||
private bool KeyDown(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if ((m_Type == FrameType.All && e.keyCode == KeyCode.A) || |
|||
(m_Type == FrameType.Selection && e.keyCode == KeyCode.F)) |
|||
{ |
|||
Rect rectToFit = parent.canvasRect; |
|||
if (m_Type == FrameType.Selection) |
|||
{ |
|||
List<CanvasElement> s = parent.selection; |
|||
if (s.Count == 0) |
|||
return false; |
|||
rectToFit = s[0].boundingRect; |
|||
foreach (CanvasElement c in s) |
|||
{ |
|||
rectToFit = RectUtils.Encompass(rectToFit, c.boundingRect); |
|||
} |
|||
} |
|||
|
|||
// bring slightly smaller screen rect into GUI space
|
|||
Rect screenRect = new Rect(); |
|||
screenRect.xMin = 50; |
|||
screenRect.xMax = Screen.width - 50; |
|||
screenRect.yMin = 50; |
|||
screenRect.yMax = Screen.height - 50; |
|||
|
|||
Matrix4x4 m = GUI.matrix; |
|||
GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one); |
|||
Rect identity = GUIUtility.ScreenToGUIRect(screenRect); |
|||
|
|||
// measure zoom level necessary to fit the canvas rect into the screen rect
|
|||
float zoomLevel = Math.Min(identity.width / rectToFit.width, identity.height / rectToFit.height); |
|||
|
|||
// clamp
|
|||
zoomLevel = Mathf.Clamp(zoomLevel, 0.08f, 1.0f); |
|||
|
|||
parent.scale = new Vector3(zoomLevel, zoomLevel, 1.0f); |
|||
parent.translation = Vector3.zero; |
|||
|
|||
|
|||
// make a rect of the screen in GUI space and measure the distance between that rect
|
|||
// and the canvas rect. Multiply this by the scale level to get the offset to center the view
|
|||
Vector2 edge = parent.MouseToCanvas(new Vector2(Screen.width, Screen.height)); |
|||
Vector2 origin = parent.MouseToCanvas(new Vector2(0.0f, 0.0f)); |
|||
|
|||
Rect r = new Rect(); |
|||
r.min = origin; |
|||
r.max = edge; |
|||
|
|||
Vector2 offset = (r.center - rectToFit.center) * parent.scale.x; |
|||
parent.translation = new Vector3(offset.x, offset.y, 0.0f); |
|||
|
|||
GUI.matrix = m; |
|||
|
|||
e.Use(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f5453a724fc0be544946c0ecb64cc25b |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal delegate bool ManipulateDelegate(Event e, Canvas2D parent, Object customData); |
|||
|
|||
public interface IManipulate |
|||
{ |
|||
bool GetCaps(ManipulatorCapability cap); |
|||
void AttachTo(CanvasElement e); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 22f1bb3e8368efd479f91ba29ca05311 |
|||
timeCreated: 1453892275 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class ImguiContainer : IManipulate |
|||
{ |
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.AllEvents += (target, evt, canvas) => |
|||
{ |
|||
Vector2 canvasPos = canvas.MouseToCanvas(evt.mousePosition); |
|||
Rect rect = canvas.CanvasToScreen(element.boundingRect); |
|||
GUI.BeginGroup(rect); |
|||
element.Render(canvas.boundingRect, canvas); |
|||
GUI.EndGroup(); |
|||
|
|||
canvas.Repaint(); |
|||
element.Invalidate(); |
|||
|
|||
return false; |
|||
}; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e506eeb20a0e91742b2fcfee043500fe |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class RectangleSelect : IManipulate |
|||
{ |
|||
private Vector2 m_Start = Vector2.zero; |
|||
private Vector2 m_End = Vector2.zero; |
|||
private bool m_SelectionActive; |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.MouseDown += MouseDown; |
|||
element.MouseUp += MouseUp; |
|||
element.MouseDrag += MouseDrag; |
|||
} |
|||
|
|||
private bool MouseDown(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
parent.ClearSelection(); |
|||
if (e.button == 0) |
|||
{ |
|||
element.OnWidget += DrawSelection; |
|||
m_Start = parent.MouseToCanvas(e.mousePosition); |
|||
m_End = m_Start; |
|||
m_SelectionActive = true; |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private bool MouseUp(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
bool handled = false; |
|||
|
|||
if (m_SelectionActive) |
|||
{ |
|||
element.OnWidget -= DrawSelection; |
|||
m_End = parent.MouseToCanvas(e.mousePosition); |
|||
|
|||
Rect selection = new Rect(); |
|||
selection.min = new Vector2(Math.Min(m_Start.x, m_End.x), Math.Min(m_Start.y, m_End.y)); |
|||
selection.max = new Vector2(Math.Max(m_Start.x, m_End.x), Math.Max(m_Start.y, m_End.y)); |
|||
|
|||
selection.width = Mathf.Max(selection.width, 5.0f); |
|||
selection.height = Mathf.Max(selection.height, 5.0f); |
|||
|
|||
foreach (CanvasElement child in parent.elements) |
|||
{ |
|||
if (child.Intersects(selection)) |
|||
{ |
|||
parent.AddToSelection(child); |
|||
} |
|||
} |
|||
|
|||
handled = true; |
|||
e.Use(); |
|||
} |
|||
m_SelectionActive = false; |
|||
|
|||
return handled; |
|||
} |
|||
|
|||
private bool MouseDrag(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.button == 0) |
|||
{ |
|||
m_End = parent.MouseToCanvas(e.mousePosition); |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
private bool DrawSelection(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (!m_SelectionActive) |
|||
return false; |
|||
|
|||
Rect r = new Rect(); |
|||
r.min = new Vector2(Math.Min(m_Start.x, m_End.x), Math.Min(m_Start.y, m_End.y)); |
|||
r.max = new Vector2(Math.Max(m_Start.x, m_End.x), Math.Max(m_Start.y, m_End.y)); |
|||
|
|||
Color lineColor = new Color(1.0f, 0.6f, 0.0f, 1.0f); |
|||
float segmentSize = 5f; |
|||
|
|||
Vector3[] points = |
|||
{ |
|||
new Vector3(r.xMin, r.yMin, 0.0f), |
|||
new Vector3(r.xMax, r.yMin, 0.0f), |
|||
new Vector3(r.xMax, r.yMax, 0.0f), |
|||
new Vector3(r.xMin, r.yMax, 0.0f) |
|||
}; |
|||
|
|||
DrawDottedLine(points[0], points[1], segmentSize, lineColor); |
|||
DrawDottedLine(points[1], points[2], segmentSize, lineColor); |
|||
DrawDottedLine(points[2], points[3], segmentSize, lineColor); |
|||
DrawDottedLine(points[3], points[0], segmentSize, lineColor); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private void DrawDottedLine(Vector3 p1, Vector3 p2, float segmentsLength, Color col) |
|||
{ |
|||
UIHelpers.ApplyWireMaterial(); |
|||
|
|||
GL.Begin(GL.LINES); |
|||
GL.Color(col); |
|||
|
|||
float length = Vector3.Distance(p1, p2); // ignore z component
|
|||
int count = Mathf.CeilToInt(length / segmentsLength); |
|||
for (int i = 0; i < count; i += 2) |
|||
{ |
|||
GL.Vertex((Vector3.Lerp(p1, p2, i * segmentsLength / length))); |
|||
GL.Vertex((Vector3.Lerp(p1, p2, (i + 1) * segmentsLength / length))); |
|||
} |
|||
|
|||
GL.End(); |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a58257dc242be394084635b5e4375312 |
|||
timeCreated: 1453895629 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class Resizable : IManipulate |
|||
{ |
|||
private bool m_Active; |
|||
private Vector2 m_Start; |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.MouseDown += OnMouseDown; |
|||
element.MouseDrag += OnMouseDrag; |
|||
element.MouseUp += OnMouseUp; |
|||
element.OnWidget += DrawResizeWidget; |
|||
} |
|||
|
|||
private bool OnMouseDown(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
Rect r = element.boundingRect; |
|||
Rect widget = r; |
|||
widget.min = new Vector2(r.max.x - 30.0f, r.max.y - 30.0f); |
|||
|
|||
if (widget.Contains(parent.MouseToCanvas(e.mousePosition))) |
|||
{ |
|||
parent.StartCapture(this, element); |
|||
parent.ClearSelection(); |
|||
m_Active = true; |
|||
m_Start = parent.MouseToCanvas(e.mousePosition); |
|||
e.Use(); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private bool OnMouseDrag(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (!m_Active || e.type != EventType.MouseDrag) |
|||
return false; |
|||
|
|||
Vector2 newPosition = parent.MouseToCanvas(e.mousePosition); |
|||
Vector2 diff = newPosition - m_Start; |
|||
m_Start = newPosition; |
|||
Vector3 newScale = element.scale; |
|||
newScale.x = Mathf.Max(0.1f, newScale.x + diff.x); |
|||
newScale.y = Mathf.Max(0.1f, newScale.y + diff.y); |
|||
|
|||
element.scale = newScale; |
|||
|
|||
element.DeepInvalidate(); |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool OnMouseUp(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (m_Active) |
|||
{ |
|||
parent.EndCapture(); |
|||
parent.RebuildQuadTree(); |
|||
} |
|||
m_Active = false; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private bool DrawResizeWidget(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
GUIStyle style = new GUIStyle("WindowBottomResize"); |
|||
|
|||
Rect r = element.boundingRect; |
|||
Rect widget = r; |
|||
widget.min = new Vector2(r.max.x - 10.0f, r.max.y - 7.0f); |
|||
GUI.Label(widget, GUIContent.none, style); |
|||
return true; |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9e5f064dae2113b4f82ff0ec77fe94a5 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class ScreenSpaceGrid : IManipulate |
|||
{ |
|||
private readonly float m_Spacing = 50f; |
|||
private readonly int m_ThickLines = 10; |
|||
private readonly Color m_LineColor = new Color(0f, 0f, 0f, 0.18f); |
|||
private readonly Color m_ThickLineColor = new Color(0f, 0f, 0f, 0.38f); |
|||
private readonly Color m_Background = new Color(0.17f, 0.17f, 0.17f, 1.0f); |
|||
//private Color m_Background = new Color(1.0f, 1.0f, 1.0f, 1.0f);
|
|||
|
|||
public ScreenSpaceGrid() |
|||
{} |
|||
|
|||
public ScreenSpaceGrid(float spacing, int thickLineFrequency, Color lineColor, Color thickLineColor, Color background) |
|||
{ |
|||
m_Spacing = spacing; |
|||
m_ThickLines = thickLineFrequency; |
|||
m_LineColor = lineColor; |
|||
m_ThickLineColor = thickLineColor; |
|||
m_Background = background; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
if (element is Canvas2D) |
|||
{ |
|||
(element as Canvas2D).OnBackground += DrawGrid; |
|||
} |
|||
} |
|||
|
|||
public static bool NearlyEqual(float a, float b, float epsilon) |
|||
{ |
|||
if ((Math.Abs(a) - Math.Abs(b)) > epsilon) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
private Vector3 Clip(Rect clipRect, Vector3 _in) |
|||
{ |
|||
if (_in.x < clipRect.xMin) |
|||
_in.x = clipRect.xMin; |
|||
if (_in.x > clipRect.xMax) |
|||
_in.x = clipRect.xMax; |
|||
|
|||
if (_in.y < clipRect.yMin) |
|||
_in.y = clipRect.yMin; |
|||
if (_in.y > clipRect.yMax) |
|||
_in.y = clipRect.yMax; |
|||
|
|||
return _in; |
|||
} |
|||
|
|||
private bool DrawGrid(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
Rect clientRect = new Rect(0, canvas.clientRect.y, Screen.width, Screen.height); |
|||
|
|||
// background
|
|||
UIHelpers.ApplyWireMaterial(); |
|||
|
|||
GL.Begin(GL.QUADS); |
|||
GL.Color(m_Background); |
|||
GL.Vertex(Clip(clientRect, new Vector3(clientRect.x, clientRect.y + canvas.viewOffset.y, 0.0f))); |
|||
GL.Vertex(Clip(clientRect, new Vector3(clientRect.x + clientRect.width, clientRect.y + canvas.viewOffset.y, 0.0f))); |
|||
GL.Vertex(Clip(clientRect, new Vector3(clientRect.x + clientRect.width, clientRect.y + clientRect.height, 0.0f))); |
|||
GL.Vertex(Clip(clientRect, new Vector3(clientRect.x, clientRect.y + clientRect.height, 0.0f))); |
|||
GL.End(); |
|||
|
|||
Vector3 from = new Vector3(0.0f, 0.0f, 0.0f); |
|||
Vector3 to = new Vector3(0.0f, clientRect.height, 0.0f); |
|||
|
|||
Matrix4x4 tx = Matrix4x4.TRS(canvas.translation, Quaternion.identity, Vector3.one); |
|||
|
|||
// vertical lines
|
|||
from = tx.MultiplyPoint(from); |
|||
to = tx.MultiplyPoint(to); |
|||
|
|||
float thickGridLineX = from.x; |
|||
float thickGridLineY = from.y; |
|||
|
|||
from.x = (from.x % (m_Spacing * (canvas.scale.x)) - (m_Spacing * (canvas.scale.x))); |
|||
to.x = from.x; |
|||
|
|||
from.y = 0.0f; |
|||
to.y = clientRect.y + clientRect.height; |
|||
|
|||
while (from.x < clientRect.width) |
|||
{ |
|||
from.x += m_Spacing * (canvas.scale.x); |
|||
to.x += m_Spacing * (canvas.scale.x); |
|||
GL.Begin(GL.LINES); |
|||
GL.Color(m_LineColor); |
|||
GL.Vertex(Clip(clientRect, from)); |
|||
GL.Vertex(Clip(clientRect, to)); |
|||
GL.End(); |
|||
} |
|||
|
|||
float thickLineSpacing = (m_Spacing * m_ThickLines); |
|||
from.x = to.x = (thickGridLineX % (thickLineSpacing * (canvas.scale.x)) - (thickLineSpacing * (canvas.scale.x))); |
|||
while (from.x < clientRect.width) |
|||
{ |
|||
GL.Begin(GL.LINES); |
|||
GL.Color(m_ThickLineColor); |
|||
GL.Vertex(Clip(clientRect, from)); |
|||
GL.Vertex(Clip(clientRect, to)); |
|||
GL.End(); |
|||
from.x += (m_Spacing * (canvas.scale.x) * m_ThickLines); |
|||
to.x += (m_Spacing * (canvas.scale.x) * m_ThickLines); |
|||
} |
|||
|
|||
// horizontal lines
|
|||
from = new Vector3(0.0f, 0.0f, 0.0f); |
|||
to = new Vector3(clientRect.width, 0.0f, 0.0f); |
|||
|
|||
from = tx.MultiplyPoint(from); |
|||
to = tx.MultiplyPoint(to); |
|||
|
|||
from.y = (from.y % (m_Spacing * (canvas.scale.y)) - (m_Spacing * (canvas.scale.y))); |
|||
to.y = from.y; |
|||
from.x = 0.0f; |
|||
to.x = clientRect.width; |
|||
|
|||
while (from.y < clientRect.height) |
|||
{ |
|||
from.y += m_Spacing * (canvas.scale.y); |
|||
to.y += m_Spacing * (canvas.scale.y); |
|||
GL.Begin(GL.LINES); |
|||
GL.Color(m_LineColor); |
|||
GL.Vertex(Clip(clientRect, from)); |
|||
GL.Vertex(Clip(clientRect, to)); |
|||
GL.End(); |
|||
} |
|||
|
|||
thickLineSpacing = (m_Spacing * m_ThickLines); |
|||
from.y = to.y = (thickGridLineY % (thickLineSpacing * (canvas.scale.y)) - (thickLineSpacing * (canvas.scale.y))); |
|||
while (from.y < clientRect.height) |
|||
{ |
|||
GL.Begin(GL.LINES); |
|||
GL.Color(m_ThickLineColor); |
|||
GL.Vertex(Clip(clientRect, from)); |
|||
GL.Vertex(Clip(clientRect, to)); |
|||
GL.End(); |
|||
from.y += (m_Spacing * (canvas.scale.y) * m_ThickLines); |
|||
to.y += (m_Spacing * (canvas.scale.y) * m_ThickLines); |
|||
} |
|||
return true; |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f480bc73f3ad10a4abde4d0eab51060d |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental |
|||
{ |
|||
internal class Zoomable : IManipulate |
|||
{ |
|||
public enum ZoomType |
|||
{ |
|||
AroundMouse = 0, |
|||
LastClick = 1 |
|||
}; |
|||
|
|||
public Zoomable() |
|||
{ |
|||
m_Type = ZoomType.AroundMouse; |
|||
} |
|||
|
|||
public Zoomable(ZoomType type) |
|||
{ |
|||
m_Type = type; |
|||
} |
|||
|
|||
private Vector2 m_ZoomLocation = Vector2.zero; |
|||
private ZoomType m_Type; |
|||
private float m_MinimumZoom = 0.08f; |
|||
private float m_MaximumZoom = 1.0f; |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.ScrollWheel += OnZoom; |
|||
element.KeyDown += OnKeyDown; |
|||
|
|||
if (m_Type == ZoomType.LastClick) |
|||
{ |
|||
element.MouseDown += OnMouseDown; |
|||
} |
|||
} |
|||
|
|||
private bool OnMouseDown(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
m_ZoomLocation = e.mousePosition; |
|||
m_ZoomLocation.x -= element.translation.x; |
|||
m_ZoomLocation.y -= element.translation.y; |
|||
return true; |
|||
} |
|||
|
|||
private bool OnKeyDown(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.keyCode == KeyCode.R) |
|||
{ |
|||
element.scale = Vector3.one; |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private bool OnZoom(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (m_Type == ZoomType.AroundMouse) |
|||
{ |
|||
m_ZoomLocation = e.mousePosition; |
|||
m_ZoomLocation.x -= element.translation.x; |
|||
m_ZoomLocation.y -= element.translation.y; |
|||
} |
|||
|
|||
float delta = 0; |
|||
delta += Event.current.delta.y; |
|||
delta += Event.current.delta.x; |
|||
delta = -delta; |
|||
|
|||
Vector3 currentScale = element.scale; |
|||
Vector3 currentTranslation = element.translation; |
|||
|
|||
// Scale multiplier. Don't allow scale of zero or below!
|
|||
float scale = Mathf.Max(0.01F, 1 + delta * 0.01F); |
|||
|
|||
currentTranslation.x -= m_ZoomLocation.x * (scale - 1) * currentScale.x; |
|||
currentScale.x *= scale; |
|||
|
|||
currentTranslation.y -= m_ZoomLocation.y * (scale - 1) * currentScale.y; |
|||
currentScale.y *= scale; |
|||
currentScale.z = 1.0f; |
|||
|
|||
bool outOfZoomBounds = false; |
|||
if (((currentScale.x < m_MinimumZoom) || (currentScale.x > m_MaximumZoom)) || |
|||
((currentScale.y < m_MinimumZoom) || (currentScale.y > m_MaximumZoom))) |
|||
{ |
|||
outOfZoomBounds = true; |
|||
} |
|||
|
|||
currentScale.x = Mathf.Clamp(currentScale.x, m_MinimumZoom, m_MaximumZoom); |
|||
currentScale.y = Mathf.Clamp(currentScale.y, m_MinimumZoom, m_MaximumZoom); |
|||
|
|||
element.scale = currentScale; |
|||
if (!outOfZoomBounds) |
|||
{ |
|||
element.translation = currentTranslation; |
|||
} |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
}; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5c80fbd8d4c68324089e1a0a8f0ac823 |
|||
timeCreated: 1453892276 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: b38b5846fc01eb6428cd956646e8f9ca |
|||
timeCreated: 1430064400 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Expressions; |
|||
using System.Text; |
|||
using System.IO; |
|||
using System.Reflection; |
|||
using UnityEngine; |
|||
using UnityEditorInternal; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
#pragma warning disable 0414
|
|||
#pragma warning disable 0219
|
|||
|
|||
namespace UnityEditor |
|||
{ |
|||
namespace Experimental |
|||
{ |
|||
public enum ManipulatorCapability |
|||
{ |
|||
eMultiSelection = 0 |
|||
}; |
|||
|
|||
public interface IManipulate |
|||
{ |
|||
bool GetCaps(ManipulatorCapability cap); |
|||
void AttachTo(CanvasElement e); |
|||
} |
|||
|
|||
internal delegate bool ManipulateDelegate(Event e, Canvas2D parent, Object customData); |
|||
|
|||
internal class Draggable : IManipulate |
|||
{ |
|||
private EventModifiers m_ActivatorModifiers; |
|||
private int m_ActivatorButton = 0; |
|||
|
|||
public Draggable() |
|||
{ |
|||
m_ActivatorButton = 0; |
|||
m_ActivatorModifiers = EventModifiers.None; |
|||
} |
|||
|
|||
public Draggable(int button, EventModifiers activator) |
|||
{ |
|||
m_ActivatorButton = button; |
|||
m_ActivatorModifiers = activator; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
if (cap == ManipulatorCapability.eMultiSelection) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.MouseDrag += MouseDrag; |
|||
element.MouseUp += EndDrag; |
|||
element.MouseDown += StartDrag; |
|||
} |
|||
|
|||
private bool StartDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.button != m_ActivatorButton || m_ActivatorModifiers != e.modifiers) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
canvas.StartCapture(this, element); |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool EndDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
canvas.EndCapture(); |
|||
|
|||
if (canvas.Selection.Count == 0) |
|||
{ |
|||
canvas.AddToSelection(element); |
|||
} |
|||
|
|||
element.UpdateModel(UpdateType.eUpdate); |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool MouseDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
float scaleFactorX = element == canvas ? 1.0f : 1.0f/canvas.scale.x; |
|||
float scaleFactorY = element == canvas ? 1.0f : 1.0f/canvas.scale.y; |
|||
|
|||
Vector3 tx = element.translation; |
|||
tx.x += e.delta.x*scaleFactorX; |
|||
tx.y += e.delta.y*scaleFactorY; |
|||
element.translation = tx; |
|||
element.UpdateModel(UpdateType.eCandidate); |
|||
e.Use(); |
|||
|
|||
return true; |
|||
} |
|||
}; |
|||
|
|||
internal class Zoomable : IManipulate |
|||
{ |
|||
public enum ZoomType |
|||
{ |
|||
eAroundMouse = 0, |
|||
eLastClick = 1 |
|||
}; |
|||
|
|||
public Zoomable() |
|||
{ |
|||
m_Type = ZoomType.eAroundMouse; |
|||
} |
|||
|
|||
public Zoomable(ZoomType type) |
|||
{ |
|||
m_Type = type; |
|||
} |
|||
|
|||
private Vector2 m_ZoomLocation = Vector2.zero; |
|||
private ZoomType m_Type = ZoomType.eAroundMouse; |
|||
private float m_MinimumZoom = 0.08f; |
|||
private float m_MaximumZoom = 1.0f; |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.ScrollWheel += OnZoom; |
|||
element.KeyDown += OnKeyDown; |
|||
|
|||
if (m_Type == ZoomType.eLastClick) |
|||
{ |
|||
element.MouseDown += OnMouseDown; |
|||
} |
|||
} |
|||
|
|||
private bool OnMouseDown(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
m_ZoomLocation = e.mousePosition; |
|||
m_ZoomLocation.x -= element.translation.x; |
|||
m_ZoomLocation.y -= element.translation.y; |
|||
return true; |
|||
} |
|||
|
|||
private bool OnKeyDown(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.keyCode == KeyCode.R) |
|||
{ |
|||
element.scale = Vector3.one; |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private bool OnZoom(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (m_Type == ZoomType.eAroundMouse) |
|||
{ |
|||
m_ZoomLocation = e.mousePosition; |
|||
m_ZoomLocation.x -= element.translation.x; |
|||
m_ZoomLocation.y -= element.translation.y; |
|||
} |
|||
|
|||
float delta = 0; |
|||
delta += Event.current.delta.y; |
|||
delta += Event.current.delta.x; |
|||
delta = -delta; |
|||
|
|||
Vector3 currentScale = element.scale; |
|||
Vector3 currentTranslation = element.translation; |
|||
|
|||
// Scale multiplier. Don't allow scale of zero or below!
|
|||
float scale = Mathf.Max(0.01F, 1 + delta*0.01F); |
|||
|
|||
currentTranslation.x -= m_ZoomLocation.x*(scale - 1)*currentScale.x; |
|||
currentScale.x *= scale; |
|||
|
|||
currentTranslation.y -= m_ZoomLocation.y*(scale - 1)*currentScale.y; |
|||
currentScale.y *= scale; |
|||
currentScale.z = 1.0f; |
|||
|
|||
bool outOfZoomBounds = false; |
|||
if (((currentScale.x < m_MinimumZoom) || (currentScale.x > m_MaximumZoom)) || |
|||
((currentScale.y < m_MinimumZoom) || (currentScale.y > m_MaximumZoom))) |
|||
{ |
|||
outOfZoomBounds = true; |
|||
} |
|||
|
|||
currentScale.x = Mathf.Clamp(currentScale.x, m_MinimumZoom, m_MaximumZoom); |
|||
currentScale.y = Mathf.Clamp(currentScale.y, m_MinimumZoom, m_MaximumZoom); |
|||
|
|||
element.scale = currentScale; |
|||
if (!outOfZoomBounds) |
|||
{ |
|||
element.translation = currentTranslation; |
|||
} |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
}; |
|||
|
|||
internal class Resizable : IManipulate |
|||
{ |
|||
private bool m_Active = false; |
|||
private Vector2 m_Start = new Vector2(); |
|||
|
|||
public Resizable() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.MouseDown += OnMouseDown; |
|||
element.MouseDrag += OnMouseDrag; |
|||
element.MouseUp += OnMouseUp; |
|||
element.OnWidget += DrawResizeWidget; |
|||
} |
|||
|
|||
private bool OnMouseDown(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
Rect r = element.boundingRect; |
|||
Rect widget = r; |
|||
widget.min = new Vector2(r.max.x - 30.0f, r.max.y - 30.0f); |
|||
|
|||
if (widget.Contains(parent.MouseToCanvas(e.mousePosition))) |
|||
{ |
|||
parent.StartCapture(this, element); |
|||
parent.ClearSelection(); |
|||
m_Active = true; |
|||
m_Start = parent.MouseToCanvas(e.mousePosition); |
|||
e.Use(); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private bool OnMouseDrag(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (!m_Active || e.type != EventType.MouseDrag) |
|||
return false; |
|||
|
|||
Vector2 newPosition = parent.MouseToCanvas(e.mousePosition); |
|||
Vector2 diff = newPosition - m_Start; |
|||
m_Start = newPosition; |
|||
Vector3 newScale = element.scale; |
|||
newScale.x = Mathf.Max(0.1f, newScale.x + diff.x); |
|||
newScale.y = Mathf.Max(0.1f, newScale.y + diff.y); |
|||
|
|||
element.scale = newScale; |
|||
|
|||
element.DeepInvalidate(); |
|||
|
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
private bool OnMouseUp(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (m_Active == true) |
|||
{ |
|||
parent.EndCapture(); |
|||
parent.RebuildQuadTree(); |
|||
} |
|||
m_Active = false; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private bool DrawResizeWidget(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
GUIStyle style = new GUIStyle("WindowBottomResize"); |
|||
|
|||
Rect r = element.boundingRect; |
|||
Rect widget = r; |
|||
widget.min = new Vector2(r.max.x - 10.0f, r.max.y - 7.0f); |
|||
GUI.Label(widget, GUIContent.none, style); |
|||
return true; |
|||
} |
|||
}; |
|||
|
|||
internal class RectangleSelect : IManipulate |
|||
{ |
|||
private Vector2 m_Start = Vector2.zero; |
|||
private Vector2 m_End = Vector2.zero; |
|||
private bool m_SelectionActive = false; |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.MouseDown += MouseDown; |
|||
element.MouseUp += MouseUp; |
|||
element.MouseDrag += MouseDrag; |
|||
} |
|||
|
|||
private bool MouseDown(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
parent.ClearSelection(); |
|||
if (e.button == 0) |
|||
{ |
|||
element.OnWidget += DrawSelection; |
|||
m_Start = parent.MouseToCanvas(e.mousePosition); |
|||
m_End = m_Start; |
|||
m_SelectionActive = true; |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private bool MouseUp(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
bool handled = false; |
|||
|
|||
if (m_SelectionActive) |
|||
{ |
|||
element.OnWidget -= DrawSelection; |
|||
m_End = parent.MouseToCanvas(e.mousePosition); |
|||
|
|||
Rect selection = new Rect(); |
|||
selection.min = new Vector2(Math.Min(m_Start.x, m_End.x), Math.Min(m_Start.y, m_End.y)); |
|||
selection.max = new Vector2(Math.Max(m_Start.x, m_End.x), Math.Max(m_Start.y, m_End.y)); |
|||
|
|||
selection.width = Mathf.Max(selection.width, 5.0f); |
|||
selection.height = Mathf.Max(selection.height, 5.0f); |
|||
|
|||
foreach (CanvasElement child in parent.Elements) |
|||
{ |
|||
if (child.Intersects(selection)) |
|||
{ |
|||
parent.AddToSelection(child); |
|||
} |
|||
} |
|||
|
|||
handled = true; |
|||
e.Use(); |
|||
} |
|||
m_SelectionActive = false; |
|||
|
|||
return handled; |
|||
} |
|||
|
|||
private bool MouseDrag(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.button == 0) |
|||
{ |
|||
m_End = parent.MouseToCanvas(e.mousePosition); |
|||
e.Use(); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
private bool DrawSelection(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (!m_SelectionActive) |
|||
return false; |
|||
|
|||
Rect r = new Rect(); |
|||
r.min = new Vector2(Math.Min(m_Start.x, m_End.x), Math.Min(m_Start.y, m_End.y)); |
|||
r.max = new Vector2(Math.Max(m_Start.x, m_End.x), Math.Max(m_Start.y, m_End.y)); |
|||
|
|||
Color lineColor = new Color(1.0f, 0.6f, 0.0f, 1.0f); |
|||
float segmentSize = 5f; |
|||
|
|||
Vector3[] points = |
|||
{ |
|||
new Vector3(r.xMin, r.yMin, 0.0f), |
|||
new Vector3(r.xMax, r.yMin, 0.0f), |
|||
new Vector3(r.xMax, r.yMax, 0.0f), |
|||
new Vector3(r.xMin, r.yMax, 0.0f) |
|||
}; |
|||
|
|||
DrawDottedLine(points[0], points[1], segmentSize, lineColor); |
|||
DrawDottedLine(points[1], points[2], segmentSize, lineColor); |
|||
DrawDottedLine(points[2], points[3], segmentSize, lineColor); |
|||
DrawDottedLine(points[3], points[0], segmentSize, lineColor); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private void DrawDottedLine(Vector3 p1, Vector3 p2, float segmentsLength, Color col) |
|||
{ |
|||
UIHelpers.ApplyWireMaterial(); |
|||
|
|||
GL.Begin(GL.LINES); |
|||
GL.Color(col); |
|||
|
|||
float length = Vector3.Distance(p1, p2); // ignore z component
|
|||
int count = Mathf.CeilToInt(length/segmentsLength); |
|||
for (int i = 0; i < count; i += 2) |
|||
{ |
|||
GL.Vertex((Vector3.Lerp(p1, p2, i*segmentsLength/length))); |
|||
GL.Vertex((Vector3.Lerp(p1, p2, (i + 1)*segmentsLength/length))); |
|||
} |
|||
|
|||
GL.End(); |
|||
} |
|||
}; |
|||
|
|||
internal class Frame : IManipulate |
|||
{ |
|||
public enum FrameType |
|||
{ |
|||
eAll = 0, |
|||
eSelection = 1 |
|||
}; |
|||
|
|||
private FrameType m_Type = FrameType.eAll; |
|||
|
|||
public Frame(FrameType type) |
|||
{ |
|||
m_Type = type; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.KeyDown += KeyDown; |
|||
} |
|||
|
|||
private bool KeyDown(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if ((m_Type == FrameType.eAll && e.keyCode == KeyCode.A) || |
|||
(m_Type == FrameType.eSelection && e.keyCode == KeyCode.F)) |
|||
{ |
|||
Rect rectToFit = parent.CanvasRect; |
|||
if (m_Type == FrameType.eSelection) |
|||
{ |
|||
List<CanvasElement> s = parent.Selection; |
|||
if (s.Count == 0) |
|||
return false; |
|||
rectToFit = s[0].boundingRect; |
|||
foreach (CanvasElement c in s) |
|||
{ |
|||
rectToFit = RectUtils.Encompass(rectToFit, c.boundingRect); |
|||
} |
|||
} |
|||
|
|||
// bring slightly smaller screen rect into GUI space
|
|||
Rect screenRect = new Rect(); |
|||
screenRect.xMin = 50; |
|||
screenRect.xMax = Screen.width - 50; |
|||
screenRect.yMin = 50; |
|||
screenRect.yMax = Screen.height - 50; |
|||
|
|||
Matrix4x4 m = GUI.matrix; |
|||
GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one); |
|||
Rect identity = GUIUtility.ScreenToGUIRect(screenRect); |
|||
|
|||
// measure zoom level necessary to fit the canvas rect into the screen rect
|
|||
float zoomLevel = Math.Min(identity.width/rectToFit.width, identity.height/rectToFit.height); |
|||
|
|||
// clamp
|
|||
zoomLevel = Mathf.Clamp(zoomLevel, 0.08f, 1.0f); |
|||
|
|||
parent.scale = new Vector3(zoomLevel, zoomLevel, 1.0f); |
|||
parent.translation = Vector3.zero; |
|||
|
|||
|
|||
// make a rect of the screen in GUI space and measure the distance between that rect
|
|||
// and the canvas rect. Multiply this by the scale level to get the offset to center the view
|
|||
Vector2 edge = parent.MouseToCanvas(new Vector2(Screen.width, Screen.height)); |
|||
Vector2 origin = parent.MouseToCanvas(new Vector2(0.0f, 0.0f)); |
|||
|
|||
Rect r = new Rect(); |
|||
r.min = origin; |
|||
r.max = edge; |
|||
|
|||
Vector2 offset = (r.center - rectToFit.center)*parent.scale.x; |
|||
parent.translation = new Vector3(offset.x, offset.y, 0.0f); |
|||
|
|||
GUI.matrix = m; |
|||
|
|||
e.Use(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
}; |
|||
|
|||
internal class ContextualMenu : IManipulate |
|||
{ |
|||
private ManipulateDelegate m_Callback = null; |
|||
private Object m_CustomData = null; |
|||
|
|||
public ContextualMenu(ManipulateDelegate callback) |
|||
{ |
|||
m_Callback = callback; |
|||
m_CustomData = null; |
|||
} |
|||
|
|||
public ContextualMenu(ManipulateDelegate callback, Object customData) |
|||
{ |
|||
m_Callback = callback; |
|||
m_CustomData = customData; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.ContextClick += OnContextMenu; |
|||
} |
|||
|
|||
private bool OnContextMenu(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
e.Use(); |
|||
return m_Callback(e, parent, m_CustomData); |
|||
} |
|||
}; |
|||
|
|||
internal class DragDrop : IManipulate |
|||
{ |
|||
private ManipulateDelegate m_Callback = null; |
|||
private Object m_CustomData = null; |
|||
|
|||
public DragDrop(ManipulateDelegate callback) |
|||
{ |
|||
m_Callback = callback; |
|||
m_CustomData = null; |
|||
} |
|||
|
|||
public DragDrop(ManipulateDelegate callback, Object customData) |
|||
{ |
|||
m_Callback = callback; |
|||
m_CustomData = customData; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.DragPerform += OnDragAndDropEvent; |
|||
element.DragUpdated += OnDragAndDropEvent; |
|||
element.DragExited += OnDragAndDropEvent; |
|||
} |
|||
|
|||
private bool OnDragAndDropEvent(CanvasElement element, Event e, Canvas2D parent) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
return m_Callback(e, parent, m_CustomData); |
|||
} |
|||
}; |
|||
|
|||
internal class ScreenSpaceGrid : IManipulate |
|||
{ |
|||
private float m_Spacing = 50f; |
|||
private int m_ThickLines = 10; |
|||
private Color m_LineColor = new Color(0f, 0f, 0f, 0.18f); |
|||
private Color m_ThickLineColor = new Color(0f, 0f, 0f, 0.38f); |
|||
private Color m_Background = new Color(0.17f, 0.17f, 0.17f, 1.0f); |
|||
//private Color m_Background = new Color(1.0f, 1.0f, 1.0f, 1.0f);
|
|||
|
|||
public ScreenSpaceGrid() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public ScreenSpaceGrid(float spacing, int thickLineFrequency, Color lineColor, Color thickLineColor, Color background) |
|||
{ |
|||
m_Spacing = spacing; |
|||
m_ThickLines = thickLineFrequency; |
|||
m_LineColor = lineColor; |
|||
m_ThickLineColor = thickLineColor; |
|||
m_Background = background; |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
if (element is Canvas2D) |
|||
{ |
|||
(element as Canvas2D).OnBackground += DrawGrid; |
|||
} |
|||
} |
|||
|
|||
public static bool nearlyEqual(float a, float b, float epsilon) |
|||
{ |
|||
if ((Math.Abs(a) - Math.Abs(b)) > epsilon) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
private Vector3 Clip(Rect clipRect, Vector3 _in) |
|||
{ |
|||
if (_in.x < clipRect.xMin) |
|||
_in.x = clipRect.xMin; |
|||
if (_in.x > clipRect.xMax) |
|||
_in.x = clipRect.xMax; |
|||
|
|||
if (_in.y < clipRect.yMin) |
|||
_in.y = clipRect.yMin; |
|||
if (_in.y > clipRect.yMax) |
|||
_in.y = clipRect.yMax; |
|||
|
|||
return _in; |
|||
} |
|||
|
|||
private bool DrawGrid(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
Rect clientRect = new Rect(0, canvas.clientRect.y, Screen.width, Screen.height); |
|||
|
|||
// background
|
|||
UIHelpers.ApplyWireMaterial(); |
|||
|
|||
GL.Begin(GL.QUADS); |
|||
GL.Color(m_Background); |
|||
GL.Vertex(Clip(clientRect, new Vector3(clientRect.x, clientRect.y + canvas.viewOffset.y, 0.0f))); |
|||
GL.Vertex(Clip(clientRect, new Vector3(clientRect.x + clientRect.width, clientRect.y + canvas.viewOffset.y, 0.0f))); |
|||
GL.Vertex(Clip(clientRect, new Vector3(clientRect.x + clientRect.width, clientRect.y + clientRect.height, 0.0f))); |
|||
GL.Vertex(Clip(clientRect, new Vector3(clientRect.x, clientRect.y + clientRect.height, 0.0f))); |
|||
GL.End(); |
|||
|
|||
Vector3 from = new Vector3(0.0f, 0.0f, 0.0f); |
|||
Vector3 to = new Vector3(0.0f, clientRect.height, 0.0f); |
|||
|
|||
Matrix4x4 tx = Matrix4x4.TRS(canvas.translation, Quaternion.identity, Vector3.one); |
|||
|
|||
// vertical lines
|
|||
from = tx.MultiplyPoint(from); |
|||
to = tx.MultiplyPoint(to); |
|||
|
|||
float thickGridLineX = from.x; |
|||
float thickGridLineY = from.y; |
|||
|
|||
from.x = (from.x%(m_Spacing*(canvas.scale.x)) - (m_Spacing*(canvas.scale.x))); |
|||
to.x = from.x; |
|||
|
|||
from.y = 0.0f; |
|||
to.y = clientRect.y + clientRect.height; |
|||
|
|||
while (from.x < clientRect.width) |
|||
{ |
|||
from.x += m_Spacing*(canvas.scale.x); |
|||
to.x += m_Spacing*(canvas.scale.x); |
|||
GL.Begin(GL.LINES); |
|||
GL.Color(m_LineColor); |
|||
GL.Vertex(Clip(clientRect,from)); |
|||
GL.Vertex(Clip(clientRect, to)); |
|||
GL.End(); |
|||
} |
|||
|
|||
float thickLineSpacing = (m_Spacing*m_ThickLines); |
|||
from.x = to.x = (thickGridLineX%(thickLineSpacing*(canvas.scale.x)) - (thickLineSpacing*(canvas.scale.x))); |
|||
while (from.x < clientRect.width) |
|||
{ |
|||
GL.Begin(GL.LINES); |
|||
GL.Color(m_ThickLineColor); |
|||
GL.Vertex(Clip(clientRect, from)); |
|||
GL.Vertex(Clip(clientRect, to)); |
|||
GL.End(); |
|||
from.x += (m_Spacing*(canvas.scale.x)*m_ThickLines); |
|||
to.x += (m_Spacing*(canvas.scale.x)*m_ThickLines); |
|||
} |
|||
|
|||
// horizontal lines
|
|||
from = new Vector3(0.0f, 0.0f, 0.0f); |
|||
to = new Vector3(clientRect.width, 0.0f, 0.0f); |
|||
|
|||
from = tx.MultiplyPoint(from); |
|||
to = tx.MultiplyPoint(to); |
|||
|
|||
from.y = (from.y%(m_Spacing*(canvas.scale.y)) - (m_Spacing*(canvas.scale.y))); |
|||
to.y = from.y; |
|||
from.x = 0.0f; |
|||
to.x = clientRect.width; |
|||
|
|||
while (from.y < clientRect.height) |
|||
{ |
|||
from.y += m_Spacing*(canvas.scale.y); |
|||
to.y += m_Spacing*(canvas.scale.y); |
|||
GL.Begin(GL.LINES); |
|||
GL.Color(m_LineColor); |
|||
GL.Vertex(Clip(clientRect, from)); |
|||
GL.Vertex(Clip(clientRect, to)); |
|||
GL.End(); |
|||
} |
|||
|
|||
thickLineSpacing = (m_Spacing*m_ThickLines); |
|||
from.y = to.y = (thickGridLineY%(thickLineSpacing*(canvas.scale.y)) - (thickLineSpacing*(canvas.scale.y))); |
|||
while (from.y < clientRect.height) |
|||
{ |
|||
GL.Begin(GL.LINES); |
|||
GL.Color(m_ThickLineColor); |
|||
GL.Vertex(Clip(clientRect, from)); |
|||
GL.Vertex(Clip(clientRect, to)); |
|||
GL.End(); |
|||
from.y += (m_Spacing*(canvas.scale.y)*m_ThickLines); |
|||
to.y += (m_Spacing*(canvas.scale.y)*m_ThickLines); |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
}; |
|||
|
|||
internal class IMGUIContainer : IManipulate |
|||
{ |
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.AllEvents += (target, evt, canvas) => |
|||
{ |
|||
Vector2 canvasPos = canvas.MouseToCanvas(evt.mousePosition); |
|||
Rect rect = canvas.CanvasToScreen(element.boundingRect); |
|||
GUI.BeginGroup(rect); |
|||
element.Render(canvas.boundingRect, canvas); |
|||
GUI.EndGroup(); |
|||
|
|||
canvas.Repaint(); |
|||
element.Invalidate(); |
|||
|
|||
return false; |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7dcc2b6a82194dc4cb371cc18fad3b73 |
|||
timeCreated: 1430064400 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Expressions; |
|||
using System.Text; |
|||
using System.IO; |
|||
using System.Reflection; |
|||
using System.Runtime.CompilerServices; |
|||
using UnityEngine; |
|||
using UnityEditorInternal; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
//#pragma warning disable 0414
|
|||
//#pragma warning disable 0219
|
|||
|
|||
namespace UnityEditor |
|||
{ |
|||
namespace Experimental |
|||
{ |
|||
namespace Graph |
|||
{ |
|||
class TypeAdapter : Attribute |
|||
{ |
|||
|
|||
} |
|||
|
|||
public enum Direction |
|||
{ |
|||
eInput = 0, |
|||
eOutput = 1, |
|||
eBidirectional = 2 |
|||
}; |
|||
|
|||
public interface IConnect |
|||
{ |
|||
Direction GetDirection(); |
|||
void Highlight(bool highlighted); |
|||
void RenderOverlay(Canvas2D canvas); |
|||
object Source(); |
|||
Vector3 ConnectPosition(); |
|||
void OnConnect(IConnect other); |
|||
}; |
|||
|
|||
public class NodeAdapter |
|||
{ |
|||
private static List<MethodInfo> m_TypeAdapters = null; |
|||
private static Dictionary<int, System.Reflection.MethodInfo> m_NodeAdapterDictionary; |
|||
|
|||
public bool CanAdapt(object a, object b) |
|||
{ |
|||
if (a == b) |
|||
return false; // self connections are not permitted
|
|||
|
|||
if (a == null || b == null) |
|||
return false; |
|||
|
|||
MethodInfo mi = GetAdapter(a, b); |
|||
if (mi == null) |
|||
{ |
|||
Debug.Log("adapter node not found for: " + a.GetType().ToString() + " -> " + b.GetType().ToString()); |
|||
} |
|||
return mi != null ? true : false; |
|||
} |
|||
|
|||
public bool Connect(object a, object b) |
|||
{ |
|||
MethodInfo mi = GetAdapter(a, b); |
|||
if (mi == null) |
|||
{ |
|||
Debug.LogError("Attempt to connect 2 unadaptable types: " + a.GetType().ToString() + " -> " + b.GetType().ToString()); |
|||
return false; |
|||
} |
|||
object retVal = mi.Invoke(this, new object[] { this, a, b }); |
|||
return (bool)retVal; |
|||
} |
|||
|
|||
IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly, Type extendedType) |
|||
{ |
|||
var query = from type in assembly.GetTypes() |
|||
where type.IsSealed && !type.IsGenericType && !type.IsNested |
|||
from method in type.GetMethods(BindingFlags.Static |
|||
| BindingFlags.Public | BindingFlags.NonPublic) |
|||
where method.IsDefined(typeof(ExtensionAttribute), false) |
|||
where method.GetParameters()[0].ParameterType == extendedType |
|||
select method; |
|||
return query; |
|||
} |
|||
|
|||
public MethodInfo GetAdapter(object a, object b) |
|||
{ |
|||
if (a == null || b == null) |
|||
return null; |
|||
|
|||
if (m_NodeAdapterDictionary == null) |
|||
{ |
|||
m_NodeAdapterDictionary = new Dictionary<int, System.Reflection.MethodInfo>(); |
|||
|
|||
// add extension methods
|
|||
AppDomain currentDomain = AppDomain.CurrentDomain; |
|||
foreach (System.Reflection.Assembly assembly in currentDomain.GetAssemblies()) |
|||
{ |
|||
foreach (MethodInfo method in GetExtensionMethods(assembly, typeof(NodeAdapter))) |
|||
{ |
|||
System.Reflection.ParameterInfo[] methodParams = method.GetParameters(); |
|||
if (methodParams.Count() == 3) |
|||
{ |
|||
string pa = methodParams[1].ParameterType.ToString() + methodParams[2].ParameterType.ToString(); |
|||
m_NodeAdapterDictionary.Add(pa.GetHashCode(), method); |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
string s = a.GetType().ToString() + b.GetType().ToString(); |
|||
|
|||
try |
|||
{ |
|||
return m_NodeAdapterDictionary[s.GetHashCode()]; |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public MethodInfo GetTypeAdapter(Type from, Type to) |
|||
{ |
|||
if (m_TypeAdapters == null) |
|||
{ |
|||
m_TypeAdapters = new List<MethodInfo>(); |
|||
AppDomain currentDomain = AppDomain.CurrentDomain; |
|||
foreach (System.Reflection.Assembly assembly in currentDomain.GetAssemblies()) |
|||
{ |
|||
try |
|||
{ |
|||
foreach (Type temptype in assembly.GetTypes()) |
|||
{ |
|||
MethodInfo[] methodInfos = temptype.GetMethods(BindingFlags.Public | BindingFlags.Static); |
|||
foreach (MethodInfo i in methodInfos) |
|||
{ |
|||
object[] allAttrs = i.GetCustomAttributes(typeof(TypeAdapter), false); |
|||
if (allAttrs.Count() > 0) |
|||
{ |
|||
m_TypeAdapters.Add(i); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Debug.Log(ex); |
|||
} |
|||
} |
|||
} |
|||
|
|||
foreach (MethodInfo i in m_TypeAdapters) |
|||
{ |
|||
if (i.ReturnType == to) |
|||
{ |
|||
ParameterInfo[] allParams = i.GetParameters(); |
|||
if (allParams.Count() == 1) |
|||
{ |
|||
if (allParams[0].ParameterType == from) |
|||
return i; |
|||
} |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
}; |
|||
|
|||
internal class EdgeConnector<T> : IManipulate where T : IConnect |
|||
{ |
|||
private static Color s_EdgeColor = new Color(1.0f, 1.0f, 1.0f, 0.8f); |
|||
private static Color s_ActiveEdgeColor = new Color(0.2f, 0.4f, 1.0f, 0.8f); |
|||
|
|||
private Vector2 m_Start = Vector2.zero; |
|||
private Vector2 m_End = Vector2.zero; |
|||
private Color m_Color = s_EdgeColor; |
|||
private IConnect m_SnappedTarget = null; |
|||
private IConnect m_SnappedSource = null; |
|||
|
|||
List<IConnect> m_CompatibleAnchors = new List<IConnect>(); |
|||
|
|||
public EdgeConnector() |
|||
{ |
|||
} |
|||
|
|||
public bool GetCaps(ManipulatorCapability cap) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
public void AttachTo(CanvasElement element) |
|||
{ |
|||
element.MouseUp += EndDrag; |
|||
element.MouseDown += StartDrag; |
|||
element.MouseDrag += MouseDrag; |
|||
} |
|||
|
|||
private bool StartDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (e.button != 0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
element.OnWidget += DrawEdge; |
|||
|
|||
IConnect cnx = element as IConnect; |
|||
|
|||
if (element.collapsed) |
|||
return false; |
|||
|
|||
canvas.StartCapture(this, element); |
|||
m_Start = m_End = element.canvasBoundingRect.center; |
|||
|
|||
e.Use(); |
|||
|
|||
|
|||
if (cnx != null) |
|||
{ |
|||
cnx.Highlight(true); |
|||
} |
|||
EndSnap(); |
|||
|
|||
// find compatible anchors
|
|||
m_CompatibleAnchors.Clear(); |
|||
|
|||
Rect screenRect = new Rect(); |
|||
screenRect.min = canvas.MouseToCanvas(new Vector2(0.0f, 0.0f)); |
|||
screenRect.max = canvas.MouseToCanvas(new Vector2(Screen.width, Screen.height)); |
|||
|
|||
CanvasElement[] visibleAnchors = canvas.Pick<T>(screenRect); |
|||
NodeAdapter nodeAdapter = new NodeAdapter(); |
|||
foreach (CanvasElement anchor in visibleAnchors) |
|||
{ |
|||
IConnect toCnx = anchor as IConnect; |
|||
if (toCnx == null) |
|||
continue; |
|||
|
|||
bool isBidirectional = ((cnx.GetDirection() == Direction.eBidirectional) || |
|||
(toCnx.GetDirection() == Direction.eBidirectional)); |
|||
|
|||
if (cnx.GetDirection() != toCnx.GetDirection() || isBidirectional) |
|||
{ |
|||
if (nodeAdapter.GetAdapter(cnx.Source(), toCnx.Source()) != null) |
|||
{ |
|||
m_CompatibleAnchors.Add(toCnx); |
|||
} |
|||
} |
|||
} |
|||
|
|||
canvas.OnOverlay += HighlightCompatibleAnchors; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private bool EndDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
element.OnWidget -= DrawEdge; |
|||
|
|||
canvas.EndCapture(); |
|||
IConnect cnx = element as IConnect; |
|||
if (cnx != null) |
|||
{ |
|||
cnx.Highlight(false); |
|||
} |
|||
|
|||
if (m_SnappedSource == null && m_SnappedTarget == null) |
|||
{ |
|||
cnx.OnConnect(null); |
|||
} |
|||
else if (m_SnappedSource != null && m_SnappedTarget != null) |
|||
{ |
|||
NodeAdapter nodeAdapter = new NodeAdapter(); |
|||
if (nodeAdapter.CanAdapt(m_SnappedSource.Source(), m_SnappedTarget.Source())) |
|||
{ |
|||
nodeAdapter.Connect(m_SnappedSource.Source(), m_SnappedTarget.Source()); |
|||
cnx.OnConnect(m_SnappedTarget); |
|||
} |
|||
} |
|||
|
|||
EndSnap(); |
|||
e.Use(); |
|||
canvas.OnOverlay -= HighlightCompatibleAnchors; |
|||
return true; |
|||
} |
|||
|
|||
private bool MouseDrag(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
m_End = canvas.MouseToCanvas(e.mousePosition); |
|||
e.Use(); |
|||
|
|||
m_Color = s_EdgeColor; |
|||
|
|||
IConnect thisCnx = (element as IConnect); |
|||
// find target anchor under us
|
|||
CanvasElement elementUnderMouse = canvas.PickSingle<T>(e.mousePosition); |
|||
if (elementUnderMouse != null) |
|||
{ |
|||
IConnect cnx = elementUnderMouse as IConnect; |
|||
if (cnx == null) |
|||
{ |
|||
Debug.LogError("PickSingle returned an incompatible element: does not support IConnect interface"); |
|||
return true; |
|||
} |
|||
|
|||
if (m_CompatibleAnchors.Exists(ic => ic == cnx)) |
|||
{ |
|||
StartSnap(thisCnx, cnx); |
|||
m_Color = s_ActiveEdgeColor; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
EndSnap(); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private void StartSnap(IConnect from, IConnect to) |
|||
{ |
|||
EndSnap(); |
|||
m_SnappedTarget = to; |
|||
m_SnappedSource = from; |
|||
m_SnappedTarget.Highlight(true); |
|||
} |
|||
|
|||
private void EndSnap() |
|||
{ |
|||
if (m_SnappedTarget != null) |
|||
{ |
|||
m_SnappedTarget.Highlight(false); |
|||
m_SnappedTarget = null; |
|||
} |
|||
} |
|||
|
|||
private bool DrawEdge(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (!canvas.IsCaptured(this)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
bool invert = false; |
|||
if (m_End.x < m_Start.x) |
|||
invert = true; |
|||
Vector3[] points, tangents; |
|||
GetTangents(invert ? m_End : m_Start, invert ? m_Start : m_End, out points, out tangents); |
|||
Handles.DrawBezier(points[0], points[1], tangents[0], tangents[1], m_Color, null, 5f); |
|||
|
|||
// little widget on the middle of the edge
|
|||
Vector3[] allPoints = Handles.MakeBezierPoints(points[0], points[1], tangents[0], tangents[1], 20); |
|||
Color oldColor = Handles.color; |
|||
Handles.color = m_Color; |
|||
Handles.DrawSolidDisc(allPoints[10], new Vector3(0.0f, 0.0f, -1.0f), 6f); |
|||
Handles.color = oldColor; |
|||
return true; |
|||
} |
|||
|
|||
private bool HighlightCompatibleAnchors(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
foreach (IConnect visible in m_CompatibleAnchors) |
|||
{ |
|||
visible.RenderOverlay(canvas); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public static void GetTangents(Vector2 start, Vector2 end, out Vector3[] points, out Vector3[] tangents) |
|||
{ |
|||
points = new Vector3[] { start, end }; |
|||
tangents = new Vector3[2]; |
|||
|
|||
const float minTangent = 30; |
|||
|
|||
float weight = (start.y < end.y) ? .3f : .7f; |
|||
weight = .5f; |
|||
float weight2 = 1 - weight; |
|||
float y = 0; |
|||
|
|||
if (start.x > end.x) |
|||
{ |
|||
weight2 = weight = -.25f; |
|||
float aspect = (start.x - end.x) / (start.y - end.y); |
|||
if (Mathf.Abs(aspect) > .5f) |
|||
{ |
|||
float asp = (Mathf.Abs(aspect) - .5f) / 8; |
|||
asp = Mathf.Sqrt(asp); |
|||
y = Mathf.Min(asp * 80, 80); |
|||
if (start.y > end.y) |
|||
y = -y; |
|||
} |
|||
} |
|||
float cleverness = Mathf.Clamp01(((start - end).magnitude - 10) / 50); |
|||
|
|||
tangents[0] = start + new Vector2((end.x - start.x) * weight + minTangent, y) * cleverness; |
|||
tangents[1] = end + new Vector2((end.x - start.x) * -weight2 - minTangent, -y) * cleverness; |
|||
} |
|||
}; |
|||
|
|||
|
|||
internal class Edge<T> : CanvasElement where T : CanvasElement, IConnect |
|||
{ |
|||
private T m_Left = null; |
|||
private T m_Right = null; |
|||
private ICanvasDataSource m_Data; |
|||
public Edge(ICanvasDataSource data, T left, T right) |
|||
{ |
|||
m_Data = data; |
|||
zIndex = 9999; |
|||
m_SupportsRenderToTexture = false; |
|||
left.AddDependency(this); |
|||
right.AddDependency(this); |
|||
m_Left = left; |
|||
m_Right = right; |
|||
|
|||
UpdateModel(UpdateType.eUpdate); |
|||
|
|||
KeyDown += OnDeleteEdge; |
|||
} |
|||
|
|||
public T Left |
|||
{ |
|||
get { return m_Left; } |
|||
} |
|||
|
|||
public T Right |
|||
{ |
|||
get { return m_Right; } |
|||
} |
|||
|
|||
private bool OnDeleteEdge(CanvasElement element, Event e, Canvas2D canvas) |
|||
{ |
|||
if (e.type == EventType.Used) |
|||
return false; |
|||
|
|||
if (e.keyCode == KeyCode.Delete) |
|||
{ |
|||
m_Data.DeleteElement(this); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public override bool Intersects(Rect rect) |
|||
{ |
|||
// first check coarse bounding box
|
|||
if (!base.Intersects(rect)) |
|||
return false; |
|||
|
|||
// bounding box check succeeded, do more fine grained check by checking intersection between the rectangles' diagonal
|
|||
// and the line segments
|
|||
|
|||
Vector3 from = m_Left.ConnectPosition(); |
|||
Vector3 to = m_Right.ConnectPosition(); |
|||
|
|||
if (to.x < from.x) |
|||
{ |
|||
Vector3 t = from; |
|||
from = to; |
|||
to = t; |
|||
} |
|||
|
|||
Vector3[] points, tangents; |
|||
EdgeConnector<T>.GetTangents(from, to, out points, out tangents); |
|||
Vector3[] allPoints = Handles.MakeBezierPoints(points[0], points[1], tangents[0], tangents[1], 20); |
|||
|
|||
for (int a = 0; a < allPoints.Length; a++) |
|||
{ |
|||
if (a >= allPoints.Length - 1) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
Vector2 segmentA = new Vector2(allPoints[a].x, allPoints[a].y); |
|||
Vector2 segmentB = new Vector2(allPoints[a + 1].x, allPoints[a + 1].y); |
|||
|
|||
if (RectUtils.IntersectsSegment(rect, segmentA, segmentB)) |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public override bool Contains(Vector2 canvasPosition) |
|||
{ |
|||
// first check coarse bounding box
|
|||
if (!base.Contains(canvasPosition)) |
|||
return false; |
|||
|
|||
// bounding box check succeeded, do more fine grained check by measuring distance to bezier points
|
|||
|
|||
Vector3 from = m_Left.ConnectPosition(); |
|||
Vector3 to = m_Right.ConnectPosition(); |
|||
|
|||
if (to.x < from.x) |
|||
{ |
|||
Vector3 t = from; |
|||
from = to; |
|||
to = t; |
|||
} |
|||
|
|||
Vector3[] points, tangents; |
|||
EdgeConnector<T>.GetTangents(from, to, out points, out tangents); |
|||
Vector3[] allPoints = Handles.MakeBezierPoints(points[0], points[1], tangents[0], tangents[1], 20); |
|||
|
|||
float minDistance = Mathf.Infinity; |
|||
foreach (Vector3 currentPoint in allPoints) |
|||
{ |
|||
float distance = Vector3.Distance(currentPoint, canvasPosition); |
|||
minDistance = Mathf.Min(minDistance, distance); |
|||
if (minDistance < 15.0f) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public override void Render(Rect parentRect, Canvas2D canvas) |
|||
{ |
|||
Color edgeColor = selected ? Color.yellow : Color.white; |
|||
|
|||
Vector3 from = m_Left.ConnectPosition(); |
|||
Vector3 to = m_Right.ConnectPosition(); |
|||
|
|||
if (to.x < from.x) |
|||
{ |
|||
Vector3 t = from; |
|||
from = to; |
|||
to = t; |
|||
} |
|||
|
|||
Vector3[] points, tangents; |
|||
EdgeConnector<T>.GetTangents(from, to, out points, out tangents); |
|||
Handles.DrawBezier(points[0], points[1], tangents[0], tangents[1], edgeColor, null, 5f); |
|||
} |
|||
|
|||
public override void UpdateModel(UpdateType t) |
|||
{ |
|||
Vector3 from = m_Left.ConnectPosition(); |
|||
Vector3 to = m_Right.ConnectPosition(); |
|||
|
|||
Rect r = new Rect(); |
|||
r.min = new Vector2(Math.Min(from.x, to.x), Math.Min(from.y, to.y)); |
|||
r.max = new Vector2(Math.Max(from.x, to.x), Math.Max(from.y, to.y)); |
|||
|
|||
translation = r.min; |
|||
scale = new Vector3(r.width, r.height, 1.0f); |
|||
|
|||
base.UpdateModel(t); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue