您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
176 行
4.5 KiB
176 行
4.5 KiB
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.RMGUI;
|
|
using UnityEngine.RMGUI.StyleSheets;
|
|
|
|
namespace RMGUI.GraphView
|
|
{
|
|
[StyleSheet("Assets/Editor/Views/GraphView.uss")]
|
|
public abstract class GraphView : VisualContainer, ISelection
|
|
{
|
|
private IGraphElementDataSource m_DataSource;
|
|
|
|
public IGraphElementDataSource dataSource
|
|
{
|
|
get { return m_DataSource; }
|
|
set
|
|
{
|
|
if (m_DataSource == value)
|
|
return;
|
|
|
|
RemoveWatch();
|
|
m_DataSource = value;
|
|
OnDataChanged();
|
|
AddWatch();
|
|
}
|
|
}
|
|
|
|
|
|
class ContentiewContainer : VisualContainer
|
|
{
|
|
public override bool Overlaps(Rect r)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public VisualContainer contentViewContainer{ get; private set; }
|
|
|
|
readonly ClassList elementsClassList = new ClassList("graphElement");
|
|
|
|
public VisualContainer viewport
|
|
{
|
|
get { return this; }
|
|
}
|
|
|
|
protected GraphView()
|
|
{
|
|
selection = new List<ISelectable>();
|
|
clipChildren = true;
|
|
contentViewContainer = new ContentiewContainer
|
|
{
|
|
name = "contentViewContainer",
|
|
clipChildren = false,
|
|
position = new Rect(0, 0, 0, 0)
|
|
};
|
|
// make it absolute and 0 sized so it acts as a transform to move children to and fro
|
|
AddChild(contentViewContainer);
|
|
}
|
|
|
|
private void OnDataChanged()
|
|
{
|
|
if (m_DataSource == null)
|
|
return;
|
|
|
|
// process removals
|
|
var current = contentViewContainer.children.OfType<GraphElement>().ToList();
|
|
current.AddRange(children.OfType<GraphElement>());
|
|
foreach (var c in current)
|
|
{
|
|
// been removed?
|
|
if (!m_DataSource.elements.Contains(c.GetData<GraphElementData>()))
|
|
{
|
|
c.parent.RemoveChild(c);
|
|
}
|
|
}
|
|
|
|
// process additions
|
|
var elements = contentViewContainer.children.OfType<GraphElement>().ToList();
|
|
elements.AddRange(children.OfType<GraphElement>().ToList());
|
|
foreach (var elementData in m_DataSource.elements)
|
|
{
|
|
// been added?
|
|
bool found = false;
|
|
|
|
// TODO what the heck is a "dc" anyway?
|
|
foreach (var dc in elements)
|
|
{
|
|
if (dc != null && dc.dataProvider == elementData)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
InstanciateElement(elementData);
|
|
}
|
|
}
|
|
|
|
// ISelection implementation
|
|
public List<ISelectable> selection { get; protected set; }
|
|
|
|
// functions to ISelection extensions
|
|
public void AddToSelection(ISelectable e)
|
|
{
|
|
GraphElement ce = e as GraphElement;
|
|
if (ce != null && ce.GetData<GraphElementData>() != null)
|
|
ce.GetData<GraphElementData>().selected = true;
|
|
selection.Add(e);
|
|
contentViewContainer.Touch(ChangeType.Repaint);
|
|
}
|
|
|
|
public void RemoveFromSelection(ISelectable e)
|
|
{
|
|
GraphElement ce = e as GraphElement;
|
|
if (ce != null && ce.GetData<GraphElementData>() != null)
|
|
ce.GetData<GraphElementData>().selected = false;
|
|
selection.Remove(e);
|
|
contentViewContainer.Touch(ChangeType.Repaint);
|
|
}
|
|
|
|
public void ClearSelection()
|
|
{
|
|
foreach (GraphElement e in selection.OfType<GraphElement>())
|
|
{
|
|
if (e.GetData<GraphElementData>() != null)
|
|
e.GetData<GraphElementData>().selected = false;
|
|
}
|
|
|
|
selection.Clear();
|
|
contentViewContainer.Touch(ChangeType.Repaint);
|
|
}
|
|
|
|
private void InstanciateElement(GraphElementData elementData)
|
|
{
|
|
// call factory
|
|
var newElem = CustomDataView.Create(elementData) as GraphElement;
|
|
|
|
if (newElem == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
newElem.SetPosition(elementData.position);
|
|
newElem.classList = elementsClassList;
|
|
newElem.dataProvider = elementData;
|
|
|
|
if ((elementData.capabilities & Capabilities.Resizable) != 0)
|
|
{
|
|
var resizable = new Resizer();
|
|
newElem.AddManipulator(resizable);
|
|
newElem.AddDecorator(resizable);
|
|
newElem.borderBottom = 6;
|
|
}
|
|
|
|
bool attachToContainer = (elementData.capabilities & Capabilities.Floating) == 0;
|
|
if (attachToContainer)
|
|
contentViewContainer.AddChild(newElem);
|
|
else
|
|
AddChild(newElem);
|
|
}
|
|
|
|
void AddWatch()
|
|
{
|
|
if (m_DataSource != null && panel != null && m_DataSource is Object)
|
|
// TODO: consider a disposable handle?
|
|
DataWatchService.AddDataSpy(this, (Object)m_DataSource, OnDataChanged);
|
|
}
|
|
|
|
void RemoveWatch()
|
|
{
|
|
if (m_DataSource != null && panel != null && m_DataSource is Object)
|
|
DataWatchService.RemoveDataSpy((Object)m_DataSource, OnDataChanged);
|
|
}
|
|
}
|
|
}
|