using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using UnityEngine;
using UnityEditorInternal;
using System.Reflection;
using Object = UnityEngine.Object;
namespace UnityEditor
{
namespace Experimental
{
///
/// CanvasLayout : the base class for vertical and horizontal layouts
/// WARNING: these layout classes have pretty limited usage.
///
///
/// Do not use this class directly. Use on of the specializations or derive your own
///
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 m_Children = new List();
protected List m_Elements = new List();
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()
{
}
};
///
/// CanvasVerticalLayout : Helps layouting a group of canvas elements vertically
///
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 elementRects = new List();
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();
}
};
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);
}
}
}
}
}