浏览代码

drawing preview now.

/main
Tim Cooper 8 年前
当前提交
01630326
共有 22 个文件被更改,包括 1691 次插入1544 次删除
  1. 752
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphEditWindow.cs
  2. 13
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphDataSource.cs
  3. 286
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphNode.cs
  4. 144
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialNodeData.cs
  5. 108
      MaterialGraphProject/Assets/NewUI/Editor/CustomDataView.cs
  6. 37
      MaterialGraphProject/Assets/NewUI/Editor/DataContainer.cs
  7. 398
      MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/Graph/NodeAnchor.cs
  8. 92
      MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/InvisibleBorderContainer.cs
  9. 60
      MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/IMGUISampleView.cs
  10. 6
      MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/NodalView.cs
  11. 62
      MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/SimpleGraphView.cs
  12. 8
      MaterialGraphProject/Assets/NewUI/Editor/Elements/Data/GraphElementData.cs
  13. 112
      MaterialGraphProject/Assets/NewUI/Editor/Elements/GraphElement.cs
  14. 304
      MaterialGraphProject/Assets/NewUI/Editor/Manipulators/EdgeConnector.cs
  15. 2
      MaterialGraphProject/Assets/NewUI/Editor/Views/Data/GraphViewDataSource.cs
  16. 2
      MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IGraphElementDataSource.cs
  17. 321
      MaterialGraphProject/Assets/NewUI/Editor/Views/GraphView.cs
  18. 430
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/AbstractMaterialNodeUI.cs
  19. 93
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Styles/NodalView.uss
  20. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ColorNode.cs
  21. 0
      /MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IGraphElementDataSource.cs.meta
  22. 0
      /MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IGraphElementDataSource.cs

752
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphEditWindow.cs


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
using UnityEngine.RMGUI;
namespace UnityEditor.Graphing.Drawing
{
public class GraphEditWindow : AbstractGraphEditWindow<IGraphAsset>
{
[MenuItem("Window/Graph Editor")]
public static void OpenMenu()
{
GetWindow<GraphEditWindow>();
}
}
public abstract class AbstractGraphEditWindow<T> : EditorWindow, ISerializationCallbackReceiver where T : class, IGraphAsset
{
public RenderTexture rt;
[NonSerialized]
private T m_LastSelection;
[SerializeField]
private ScriptableObject m_LastSelectedGraphSerialized;
private bool shouldRepaint
{
get
{
return m_LastSelection != null && m_LastSelection.shouldRepaint;
}
}
private MaterialGraphView m_Contents;
void OnEnable()
{
m_Contents = new MaterialGraphView();
m_Contents.name = "theView";
m_Contents.dataProvider = new MaterialGraphDataSource(m_LastSelection);
m_Contents.StretchToParentSize();
windowRoot.AddChild(m_Contents);
}
void OnDisable()
{
windowRoot.ClearChildren();
}
void Update()
{
if (shouldRepaint)
Repaint();
}
void OnSelectionChange()
{
if (Selection.activeObject == null || !EditorUtility.IsPersistent(Selection.activeObject))
return;
if (Selection.activeObject is ScriptableObject)
{
var selection = Selection.activeObject as T;
if (selection != m_LastSelection)
{
var graph = selection.graph;
graph.OnEnable();
graph.ValidateGraph();
m_LastSelection = selection;
m_Contents.dataProvider = new MaterialGraphDataSource(m_LastSelection);
m_Contents.StretchToParentSize();
m_Contents.OnDataChanged();
Repaint();
}
}
}
/*
private void ConvertSelectionToSubGraph()
{
if (m_Canvas.dataSource == null)
return;
var dataSource = m_Canvas.dataSource as GraphDataSource;
if (dataSource == null)
return;
var asset = dataSource.graphAsset;
if (asset == null)
return;
var targetGraph = asset.graph;
if (targetGraph == null)
return;
if (!m_Canvas.selection.Any())
return;
var serialzied = CopySelected.SerializeSelectedElements(m_Canvas);
var deserialized = CopySelected.DeserializeSelectedElements(serialzied);
if (deserialized == null)
return;
string path = EditorUtility.SaveFilePanelInProject("Save subgraph", "New SubGraph", "ShaderSubGraph", "");
path = path.Replace(Application.dataPath, "Assets");
if (path.Length == 0)
return;
var graphAsset = CreateInstance<MaterialSubGraphAsset>();
graphAsset.name = Path.GetFileName(path);
graphAsset.PostCreate();
var graph = graphAsset.subGraph;
if (graphAsset.graph == null)
return;
var nodeGuidMap = new Dictionary<Guid, Guid>();
foreach (var node in deserialized.GetNodes<INode>())
{
var oldGuid = node.guid;
var newGuid = node.RewriteGuid();
nodeGuidMap[oldGuid] = newGuid;
graph.AddNode(node);
}
// remap outputs to the subgraph
var inputEdgeNeedsRemap = new List<IEdge>();
var outputEdgeNeedsRemap = new List<IEdge>();
foreach (var edge in deserialized.edges)
{
var outputSlot = edge.outputSlot;
var inputSlot = edge.inputSlot;
Guid remappedOutputNodeGuid;
Guid remappedInputNodeGuid;
var outputRemapExists = nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid);
var inputRemapExists = nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid);
// pasting nice internal links!
if (outputRemapExists && inputRemapExists)
{
var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId);
var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId);
graph.Connect(outputSlotRef, inputSlotRef);
}
// one edge needs to go to outside world
else if (outputRemapExists)
{
inputEdgeNeedsRemap.Add(edge);
}
else if (inputRemapExists)
{
outputEdgeNeedsRemap.Add(edge);
}
}
// we do a grouping here as the same output can
// point to multiple inputs
var uniqueOutputs = outputEdgeNeedsRemap.GroupBy(edge => edge.outputSlot);
var inputsNeedingConnection = new List<KeyValuePair<IEdge, IEdge>>();
foreach (var group in uniqueOutputs)
{
var inputNode = graph.inputNode;
var slotId = inputNode.AddSlot();
var outputSlotRef = new SlotReference(inputNode.guid, slotId);
foreach (var edge in group)
{
var newEdge = graph.Connect(outputSlotRef, new SlotReference(nodeGuidMap[edge.inputSlot.nodeGuid], edge.inputSlot.slotId));
inputsNeedingConnection.Add(new KeyValuePair<IEdge, IEdge>(edge, newEdge));
}
}
var uniqueInputs = inputEdgeNeedsRemap.GroupBy(edge => edge.inputSlot);
var outputsNeedingConnection = new List<KeyValuePair<IEdge, IEdge>>();
foreach (var group in uniqueInputs)
{
var outputNode = graph.outputNode;
var slotId = outputNode.AddSlot();
var inputSlotRef = new SlotReference(outputNode.guid, slotId);
foreach (var edge in group)
{
var newEdge = graph.Connect(new SlotReference(nodeGuidMap[edge.outputSlot.nodeGuid], edge.outputSlot.slotId), inputSlotRef);
outputsNeedingConnection.Add(new KeyValuePair<IEdge, IEdge>(edge, newEdge));
}
}
AssetDatabase.CreateAsset(graphAsset, path);
var subGraphNode = new SubGraphNode();
targetGraph.AddNode(subGraphNode);
subGraphNode.subGraphAsset = graphAsset;
foreach (var edgeMap in inputsNeedingConnection)
{
targetGraph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.outputSlot.slotId));
}
foreach (var edgeMap in outputsNeedingConnection)
{
targetGraph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot);
}
var toDelete = m_Canvas.selection.Where(x => x is DrawableNode).ToList();
dataSource.DeleteElements(toDelete);
targetGraph.ValidateGraph();
m_Canvas.ReloadData();
m_Canvas.Invalidate();
m_Canvas.selection.Clear();
var toSelect = m_Canvas.elements.OfType<DrawableNode>().FirstOrDefault(x => x.m_Node == subGraphNode);
if (toSelect != null)
{
toSelect.selected = true;
m_Canvas.selection.Add(toSelect);
}
m_Canvas.Repaint();
}
private void Rebuild()
{
if (m_Canvas == null || m_LastSelection == null)
return;
m_DataSource.graphAsset = m_LastSelection;
m_Canvas.ReloadData();
}*/
/* void OnGUI()
{
m_HostWindow = this;
if (m_Canvas == null)
{
InitializeCanvas();
}
if (m_LastSelection == null || m_LastSelection.graph == null)
{
GUILayout.Label("No Graph selected");
return;
}
m_Canvas.OnGUI(this, new Rect(0, 0, position.width - 250, position.height));
if (GUI.Button(new Rect(position.width - 250, 0, 250, 50), "Convert to Sub-Graph"))
ConvertSelectionToSubGraph();
if (GUI.Button(new Rect(position.width - 250, 70, 250, 50), "Export"))
Export(false);
if (GUI.Button(new Rect(position.width - 250, 140, 250, 50), "Export - quick"))
Export(true);
EditorGUI.ObjectField(new Rect(position.width - 250, 210, 250, 50), rt, typeof(RenderTexture), false);
}*/
private string m_LastPath;
public void Export(bool quickExport)
{
var path = quickExport ? m_LastPath : EditorUtility.SaveFilePanelInProject("Export shader to file...", "shader.shader", "shader", "Enter file name");
m_LastPath = path; // For quick exporting
var ds = m_Contents.dataProvider as MaterialGraphDataSource;
if (ds != null && !string.IsNullOrEmpty(path))
{
ExportShader (ds.graphAsset as MaterialGraphAsset, path);
}
else
EditorUtility.DisplayDialog("Export Shader Error", "Cannot export shader", "Ok");
}
public static Shader ExportShader(MaterialGraphAsset graphAsset, string path)
{
if (graphAsset == null)
return null;
var materialGraph = graphAsset.graph as PixelGraph;
if (materialGraph == null)
return null;
List<PropertyGenerator.TextureInfo> configuredTextures;
var shaderString = ShaderGenerator.GenerateSurfaceShader(materialGraph.pixelMasterNode, new MaterialOptions(), materialGraph.name, false, out configuredTextures);
File.WriteAllText(path, shaderString);
AssetDatabase.Refresh(); // Investigate if this is optimal
var shader = AssetDatabase.LoadAssetAtPath(path, typeof(Shader)) as Shader;
if (shader == null)
return null;
var shaderImporter = AssetImporter.GetAtPath(path) as ShaderImporter;
if (shaderImporter == null)
return null;
var textureNames = new List<string>();
var textures = new List<Texture>();
foreach (var textureInfo in configuredTextures.Where(x => x.modifiable == TexturePropertyChunk.ModifiableState.Modifiable))
{
var texture = EditorUtility.InstanceIDToObject(textureInfo.textureId) as Texture;
if (texture == null)
continue;
textureNames.Add(textureInfo.name);
textures.Add(texture);
}
shaderImporter.SetDefaultTextures(textureNames.ToArray(), textures.ToArray());
textureNames.Clear();
textures.Clear();
foreach (var textureInfo in configuredTextures.Where(x => x.modifiable == TexturePropertyChunk.ModifiableState.NonModifiable))
{
var texture = EditorUtility.InstanceIDToObject(textureInfo.textureId) as Texture;
if (texture == null)
continue;
textureNames.Add(textureInfo.name);
textures.Add(texture);
}
shaderImporter.SetNonModifiableTextures(textureNames.ToArray(), textures.ToArray());
shaderImporter.SaveAndReimport();
return shaderImporter.GetShader();
}
/*public void RenderOptions(MaterialGraph graph)
{
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
EditorGUILayout.BeginVertical();
m_ScrollPos = GUILayout.BeginScrollView(m_ScrollPos, EditorStyles.textArea, GUILayout.width(250), GUILayout.ExpandHeight(true));
graph.materialOptions.DoGUI();
EditorGUILayout.Separator();
m_NodeExpanded = MaterialGraphStyles.Header("Selected", m_NodeExpanded);
if (m_NodeExpanded)
DrawableMaterialNode.OnGUI(m_Canvas.selection);
GUILayout.EndScrollView();
if (GUILayout.Button("Export"))
m_DataSource.Export(false);
GUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
}*/
public void OnBeforeSerialize()
{
var o = m_LastSelection as ScriptableObject;
if (o != null)
m_LastSelectedGraphSerialized = o;
}
public void OnAfterDeserialize()
{
if (m_LastSelectedGraphSerialized != null)
m_LastSelection = m_LastSelectedGraphSerialized as T;
m_LastSelectedGraphSerialized = null;
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
using UnityEngine.RMGUI;
namespace UnityEditor.Graphing.Drawing
{
public class GraphEditWindow : AbstractGraphEditWindow<IGraphAsset>
{
[MenuItem("Window/Graph Editor")]
public static void OpenMenu()
{
GetWindow<GraphEditWindow>();
}
}
public abstract class AbstractGraphEditWindow<T> : EditorWindow, ISerializationCallbackReceiver where T : class, IGraphAsset
{
public RenderTexture rt;
[NonSerialized]
private T m_LastSelection;
[SerializeField]
private ScriptableObject m_LastSelectedGraphSerialized;
private bool shouldRepaint
{
get
{
return m_LastSelection != null && m_LastSelection.shouldRepaint;
}
}
private MaterialGraphView m_Contents;
void OnEnable()
{
m_Contents = new MaterialGraphView();
m_Contents.name = "theView";
m_Contents.dataSource = new MaterialGraphDataSource(m_LastSelection);
m_Contents.StretchToParentSize();
windowRoot.AddChild(m_Contents);
}
void OnDisable()
{
windowRoot.ClearChildren();
}
void Update()
{
if (shouldRepaint)
Repaint();
}
void OnSelectionChange()
{
if (Selection.activeObject == null || !EditorUtility.IsPersistent(Selection.activeObject))
return;
if (Selection.activeObject is ScriptableObject)
{
var selection = Selection.activeObject as T;
if (selection != m_LastSelection)
{
var graph = selection.graph;
graph.OnEnable();
graph.ValidateGraph();
m_LastSelection = selection;
m_Contents.dataSource = new MaterialGraphDataSource(m_LastSelection);
m_Contents.StretchToParentSize();
Repaint();
}
}
}
/*
private void ConvertSelectionToSubGraph()
{
if (m_Canvas.dataSource == null)
return;
var dataSource = m_Canvas.dataSource as GraphDataSource;
if (dataSource == null)
return;
var asset = dataSource.graphAsset;
if (asset == null)
return;
var targetGraph = asset.graph;
if (targetGraph == null)
return;
if (!m_Canvas.selection.Any())
return;
var serialzied = CopySelected.SerializeSelectedElements(m_Canvas);
var deserialized = CopySelected.DeserializeSelectedElements(serialzied);
if (deserialized == null)
return;
string path = EditorUtility.SaveFilePanelInProject("Save subgraph", "New SubGraph", "ShaderSubGraph", "");
path = path.Replace(Application.dataPath, "Assets");
if (path.Length == 0)
return;
var graphAsset = CreateInstance<MaterialSubGraphAsset>();
graphAsset.name = Path.GetFileName(path);
graphAsset.PostCreate();
var graph = graphAsset.subGraph;
if (graphAsset.graph == null)
return;
var nodeGuidMap = new Dictionary<Guid, Guid>();
foreach (var node in deserialized.GetNodes<INode>())
{
var oldGuid = node.guid;
var newGuid = node.RewriteGuid();
nodeGuidMap[oldGuid] = newGuid;
graph.AddNode(node);
}
// remap outputs to the subgraph
var inputEdgeNeedsRemap = new List<IEdge>();
var outputEdgeNeedsRemap = new List<IEdge>();
foreach (var edge in deserialized.edges)
{
var outputSlot = edge.outputSlot;
var inputSlot = edge.inputSlot;
Guid remappedOutputNodeGuid;
Guid remappedInputNodeGuid;
var outputRemapExists = nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid);
var inputRemapExists = nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid);
// pasting nice internal links!
if (outputRemapExists && inputRemapExists)
{
var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId);
var inputSlotRef = new SlotReference(remappedInputNodeGuid, inputSlot.slotId);
graph.Connect(outputSlotRef, inputSlotRef);
}
// one edge needs to go to outside world
else if (outputRemapExists)
{
inputEdgeNeedsRemap.Add(edge);
}
else if (inputRemapExists)
{
outputEdgeNeedsRemap.Add(edge);
}
}
// we do a grouping here as the same output can
// point to multiple inputs
var uniqueOutputs = outputEdgeNeedsRemap.GroupBy(edge => edge.outputSlot);
var inputsNeedingConnection = new List<KeyValuePair<IEdge, IEdge>>();
foreach (var group in uniqueOutputs)
{
var inputNode = graph.inputNode;
var slotId = inputNode.AddSlot();
var outputSlotRef = new SlotReference(inputNode.guid, slotId);
foreach (var edge in group)
{
var newEdge = graph.Connect(outputSlotRef, new SlotReference(nodeGuidMap[edge.inputSlot.nodeGuid], edge.inputSlot.slotId));
inputsNeedingConnection.Add(new KeyValuePair<IEdge, IEdge>(edge, newEdge));
}
}
var uniqueInputs = inputEdgeNeedsRemap.GroupBy(edge => edge.inputSlot);
var outputsNeedingConnection = new List<KeyValuePair<IEdge, IEdge>>();
foreach (var group in uniqueInputs)
{
var outputNode = graph.outputNode;
var slotId = outputNode.AddSlot();
var inputSlotRef = new SlotReference(outputNode.guid, slotId);
foreach (var edge in group)
{
var newEdge = graph.Connect(new SlotReference(nodeGuidMap[edge.outputSlot.nodeGuid], edge.outputSlot.slotId), inputSlotRef);
outputsNeedingConnection.Add(new KeyValuePair<IEdge, IEdge>(edge, newEdge));
}
}
AssetDatabase.CreateAsset(graphAsset, path);
var subGraphNode = new SubGraphNode();
targetGraph.AddNode(subGraphNode);
subGraphNode.subGraphAsset = graphAsset;
foreach (var edgeMap in inputsNeedingConnection)
{
targetGraph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.outputSlot.slotId));
}
foreach (var edgeMap in outputsNeedingConnection)
{
targetGraph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot);
}
var toDelete = m_Canvas.selection.Where(x => x is DrawableNode).ToList();
dataSource.DeleteElements(toDelete);
targetGraph.ValidateGraph();
m_Canvas.ReloadData();
m_Canvas.Invalidate();
m_Canvas.selection.Clear();
var toSelect = m_Canvas.elements.OfType<DrawableNode>().FirstOrDefault(x => x.m_Node == subGraphNode);
if (toSelect != null)
{
toSelect.selected = true;
m_Canvas.selection.Add(toSelect);
}
m_Canvas.Repaint();
}
private void Rebuild()
{
if (m_Canvas == null || m_LastSelection == null)
return;
m_DataSource.graphAsset = m_LastSelection;
m_Canvas.ReloadData();
}*/
/* void OnGUI()
{
m_HostWindow = this;
if (m_Canvas == null)
{
InitializeCanvas();
}
if (m_LastSelection == null || m_LastSelection.graph == null)
{
GUILayout.Label("No Graph selected");
return;
}
m_Canvas.OnGUI(this, new Rect(0, 0, position.width - 250, position.height));
if (GUI.Button(new Rect(position.width - 250, 0, 250, 50), "Convert to Sub-Graph"))
ConvertSelectionToSubGraph();
if (GUI.Button(new Rect(position.width - 250, 70, 250, 50), "Export"))
Export(false);
if (GUI.Button(new Rect(position.width - 250, 140, 250, 50), "Export - quick"))
Export(true);
EditorGUI.ObjectField(new Rect(position.width - 250, 210, 250, 50), rt, typeof(RenderTexture), false);
}*/
private string m_LastPath;
public void Export(bool quickExport)
{
var path = quickExport ? m_LastPath : EditorUtility.SaveFilePanelInProject("Export shader to file...", "shader.shader", "shader", "Enter file name");
m_LastPath = path; // For quick exporting
var ds = m_Contents.dataSource as MaterialGraphDataSource;
if (ds != null && !string.IsNullOrEmpty(path))
{
ExportShader (ds.graphAsset as MaterialGraphAsset, path);
}
else
EditorUtility.DisplayDialog("Export Shader Error", "Cannot export shader", "Ok");
}
public static Shader ExportShader(MaterialGraphAsset graphAsset, string path)
{
if (graphAsset == null)
return null;
var materialGraph = graphAsset.graph as PixelGraph;
if (materialGraph == null)
return null;
List<PropertyGenerator.TextureInfo> configuredTextures;
var shaderString = ShaderGenerator.GenerateSurfaceShader(materialGraph.pixelMasterNode, new MaterialOptions(), materialGraph.name, false, out configuredTextures);
File.WriteAllText(path, shaderString);
AssetDatabase.Refresh(); // Investigate if this is optimal
var shader = AssetDatabase.LoadAssetAtPath(path, typeof(Shader)) as Shader;
if (shader == null)
return null;
var shaderImporter = AssetImporter.GetAtPath(path) as ShaderImporter;
if (shaderImporter == null)
return null;
var textureNames = new List<string>();
var textures = new List<Texture>();
foreach (var textureInfo in configuredTextures.Where(x => x.modifiable == TexturePropertyChunk.ModifiableState.Modifiable))
{
var texture = EditorUtility.InstanceIDToObject(textureInfo.textureId) as Texture;
if (texture == null)
continue;
textureNames.Add(textureInfo.name);
textures.Add(texture);
}
shaderImporter.SetDefaultTextures(textureNames.ToArray(), textures.ToArray());
textureNames.Clear();
textures.Clear();
foreach (var textureInfo in configuredTextures.Where(x => x.modifiable == TexturePropertyChunk.ModifiableState.NonModifiable))
{
var texture = EditorUtility.InstanceIDToObject(textureInfo.textureId) as Texture;
if (texture == null)
continue;
textureNames.Add(textureInfo.name);
textures.Add(texture);
}
shaderImporter.SetNonModifiableTextures(textureNames.ToArray(), textures.ToArray());
shaderImporter.SaveAndReimport();
return shaderImporter.GetShader();
}
/*public void RenderOptions(MaterialGraph graph)
{
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
EditorGUILayout.BeginVertical();
m_ScrollPos = GUILayout.BeginScrollView(m_ScrollPos, EditorStyles.textArea, GUILayout.width(250), GUILayout.ExpandHeight(true));
graph.materialOptions.DoGUI();
EditorGUILayout.Separator();
m_NodeExpanded = MaterialGraphStyles.Header("Selected", m_NodeExpanded);
if (m_NodeExpanded)
DrawableMaterialNode.OnGUI(m_Canvas.selection);
GUILayout.EndScrollView();
if (GUILayout.Button("Export"))
m_DataSource.Export(false);
GUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
}*/
public void OnBeforeSerialize()
{
var o = m_LastSelection as ScriptableObject;
if (o != null)
m_LastSelectedGraphSerialized = o;
}
public void OnAfterDeserialize()
{
if (m_LastSelectedGraphSerialized != null)
m_LastSelection = m_LastSelectedGraphSerialized as T;
m_LastSelectedGraphSerialized = null;
}
}
}

13
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphDataSource.cs


using RMGUI.GraphView;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
public class MaterialGraphDataSource : IDataSource
public class MaterialGraphDataSource : IGraphElementDataSource
{
private List<GraphElementData> m_Elements = new List<GraphElementData>();

var drawableNodes = new List<MaterialNodeData>();
foreach (var node in graphAsset.graph.GetNodes<INode>())
{
var nodeData = ScriptableObject.CreateInstance<MaterialNodeData>();
MaterialNodeData nodeData;
if (node is ColorNode)
nodeData = ScriptableObject.CreateInstance<ColorNodeData>();
else
nodeData = ScriptableObject.CreateInstance<MaterialNodeData>();
nodeData.Initialize(node);
drawableNodes.Add(nodeData);
}

}
}
}
m_Elements.AddRange(drawableNodes.OfType<GraphElementData>());
m_Elements.AddRange(drawableEdges.OfType<GraphElementData>());
}

286
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphNode.cs


using System.Linq;
using RMGUI.GraphView;
using RMGUI.GraphView.Demo;
using UnityEditor.MaterialGraph;
using UnityEngine;
using UnityEngine.RMGUI;
using UnityEngine.RMGUI.StyleEnums.Values;
namespace UnityEditor.Graphing.Drawing
{
[GUISkinStyle("window")]
[CustomDataView(typeof(MaterialNodeData))]
public class MaterialGraphNode : GraphElement
{
VisualContainer m_SlotContainer;
// VisualContainer m_ControlsContainer;
VisualContainer m_PreviewContainer;
public MaterialGraphNode()
{
content = new GUIContent("");
m_SlotContainer = new VisualContainer
{
name = "slots", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
/* m_ControlsContainer = new VisualContainer
{
name = "controls", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};*/
m_PreviewContainer = new VisualContainer
{
name = "preview", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
}
public override void DoRepaint(PaintContext painter)
{
base.DoRepaint(painter);
if (GetData<GraphElementData>() != null && GetData<GraphElementData>().selected)
{
painter.DrawRectangleOutline(transform, position, Color.yellow);
}
}
private void AddSlots(MaterialNodeData nodeData)
{
m_SlotContainer.ClearChildren();
if (!nodeData.elements.OfType<NodeAnchorData>().Any())
return;
var inputs = new VisualContainer
{
name = "input", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
m_SlotContainer.AddChild(inputs);
// put a spacer here?
//m_SlotContainer.AddChild(new f);
var outputs = new VisualContainer
{
name = "input", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
m_SlotContainer.AddChild(outputs);
content = new GUIContent(nodeData.name);
foreach (var anchor in nodeData.elements.OfType<NodeAnchorData>())
{
if (anchor.direction == Direction.Input)
inputs.AddChild(new NodeAnchor(anchor));
else
outputs.AddChild(new NodeAnchor(anchor));
}
AddChild(m_SlotContainer);
}
private void AddPreview(MaterialNodeData nodeData)
{
m_PreviewContainer.ClearChildren();
if (!nodeData.elements.OfType<NodePreviewData>().Any())
return;
foreach (var preview in nodeData.elements.OfType<NodePreviewData>())
{
var image = preview.Render(new Vector2(200, 200));
m_PreviewContainer.AddChild(new Image { image = image });
}
AddChild(m_PreviewContainer);
}
public override void OnDataChanged()
{
base.OnDataChanged();
ClearChildren();
// m_ControlsContainer.ClearChildren();
m_PreviewContainer.ClearChildren();
var nodeData = dataProvider as MaterialNodeData;
if (nodeData == null)
return;
AddSlots(nodeData);
AddPreview(nodeData);
positionType = PositionType.Absolute;
positionLeft = nodeData.node.drawState.position.x;
positionTop = nodeData.node.drawState.position.y;
}
}
}
using System.Linq;
using RMGUI.GraphView;
using RMGUI.GraphView.Demo;
using UnityEditor.MaterialGraph;
using UnityEngine;
using UnityEngine.RMGUI;
namespace UnityEditor.Graphing.Drawing
{
class PreviewImage : Image
{
public override void DoRepaint(PaintContext args)
{
Handles.DrawSolidRectangleWithOutline(position, Color.blue, Color.blue);
base.DoRepaint(args);
}
}
[GUISkinStyle("window")]
[CustomDataView(typeof(MaterialNodeData))]
[CustomDataView(typeof(ColorNodeData))]
public class MaterialGraphNode : GraphElement
{
VisualContainer m_SlotContainer;
VisualContainer m_ControlsContainer;
VisualContainer m_PreviewContainer;
public MaterialGraphNode()
{
content = new GUIContent("");
m_SlotContainer = new VisualContainer
{
name = "slots", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
m_ControlsContainer = new VisualContainer
{
name = "controls", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
m_PreviewContainer = new VisualContainer
{
name = "preview", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
}
public override void DoRepaint(PaintContext painter)
{
base.DoRepaint(painter);
if (GetData<GraphElementData>() != null && GetData<GraphElementData>().selected)
{
painter.DrawRectangleOutline(transform, position, Color.yellow);
}
}
private void AddSlots(MaterialNodeData nodeData)
{
m_SlotContainer.ClearChildren();
if (!nodeData.elements.OfType<NodeAnchorData>().Any())
return;
var inputs = new VisualContainer
{
name = "input", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
m_SlotContainer.AddChild(inputs);
// put a spacer here?
//m_SlotContainer.AddChild(new f);
var outputs = new VisualContainer
{
name = "output", // for USS&Flexbox
pickingMode = PickingMode.Ignore,
};
m_SlotContainer.AddChild(outputs);
content = new GUIContent(nodeData.name);
foreach (var anchor in nodeData.elements.OfType<NodeAnchorData>())
{
if (anchor.direction == Direction.Input)
inputs.AddChild(new NodeAnchor(anchor));
else
outputs.AddChild(new NodeAnchor(anchor));
}
AddChild(m_SlotContainer);
}
private void AddControls(MaterialNodeData nodeData)
{
m_ControlsContainer.ClearChildren();
if (!nodeData.elements.OfType<NodeControlData>().Any())
return;
foreach (var controlData in nodeData.elements.OfType<NodeControlData>())
{
var imContainer = new IMGUIContainer()
{
name = "element",
OnGUIHandler = controlData.OnGUIHandler,
pickingMode = PickingMode.Position
};
m_ControlsContainer.AddChild(imContainer);
}
AddChild(m_ControlsContainer);
}
private void AddPreview(MaterialNodeData nodeData)
{
m_PreviewContainer.ClearChildren();
if (!nodeData.elements.OfType<NodePreviewData>().Any())
return;
foreach (var preview in nodeData.elements.OfType<NodePreviewData>())
{
var image = preview.Render(new Vector2(200, 200));
var thePreview = new PreviewImage
{
image = image,
name = "image"
};
m_PreviewContainer.AddChild(thePreview);
}
AddChild(m_PreviewContainer);
}
public override void OnDataChanged()
{
base.OnDataChanged();
ClearChildren();
m_ControlsContainer.ClearChildren();
m_PreviewContainer.ClearChildren();
var nodeData = dataProvider as MaterialNodeData;
if (nodeData == null)
return;
AddSlots(nodeData);
AddControls(nodeData);
AddPreview(nodeData);
/*positionType = PositionType.Absolute;
positionLeft = nodeData.node.drawState.position.x;
positionTop = nodeData.node.drawState.position.y;*/
}
}
}

144
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialNodeData.cs


using System;
using System.Collections.Generic;
using RMGUI.GraphView;
using UnityEditor.MaterialGraph;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
namespace UnityEditor.Graphing.Drawing
{
[Serializable]
public class MaterialNodeData : GraphElementData
{
public INode node { get; private set; }
protected List<GraphElementData> m_Children = new List<GraphElementData>();
public IEnumerable<GraphElementData> elements
{
get { return m_Children; }
}
protected MaterialNodeData()
{}
public void Initialize(INode inNode)
{
node = inNode;
capabilities |= Capabilities.Movable;
if (node == null)
return;
name = inNode.name;
foreach (var input in node.GetSlots<ISlot>())
{
var data = CreateInstance<MaterialNodeAnchorData>();
data.Initialize(input);
m_Children.Add(data);
}
var materialNode = inNode as AbstractMaterialNode;
if (materialNode == null || !materialNode.hasPreview)
return;
var previewData = CreateInstance<NodePreviewData>();
previewData.Initialize(materialNode);
m_Children.Add(previewData);
//position = new Rect(node.drawState.position.x, node.drawState.position.y, 100, 200);
//position
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using RMGUI.GraphView;
using UnityEditor.MaterialGraph;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
namespace UnityEditor.Graphing.Drawing
{
[Serializable]
public class ColorNodeData : MaterialNodeData
{
class ColorNodeContolData : NodeControlData
{
public override void OnGUIHandler()
{
EditorGUILayout.ColorField("test", Color.blue);
}
}
protected override IEnumerable<NodeControlData> GetControlData()
{
return new List<NodeControlData> {new ColorNodeContolData()};
}
}
[Serializable]
public class MaterialNodeData : GraphElementData
{
public INode node { get; private set; }
protected List<GraphElementData> m_Children = new List<GraphElementData>();
public IEnumerable<GraphElementData> elements
{
get { return m_Children; }
}
protected MaterialNodeData()
{}
public void Initialize(INode inNode)
{
node = inNode;
capabilities |= Capabilities.Movable;
if (node == null)
return;
name = inNode.name;
foreach (var input in node.GetSlots<ISlot>())
{
var data = CreateInstance<MaterialNodeAnchorData>();
data.Initialize(input);
m_Children.Add(data);
}
AddPreview(inNode);
m_Children.AddRange(GetControlData().OfType<GraphElementData>());
//position = new Rect(node.drawState.position.x, node.drawState.position.y, 100, 200);
//position
}
private void AddPreview(INode inNode)
{
var materialNode = inNode as AbstractMaterialNode;
if (materialNode == null || !materialNode.hasPreview)
return;
var previewData = CreateInstance<NodePreviewData>();
previewData.Initialize(materialNode);
m_Children.Add(previewData);
}
protected virtual IEnumerable<NodeControlData> GetControlData()
{
return new NodeControlData[0];
}
}
}

108
MaterialGraphProject/Assets/NewUI/Editor/CustomDataView.cs


using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace RMGUI.GraphView
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class CustomDataView : Attribute
{
public CustomDataView(Type t)
{
if (t == null)
Debug.LogError("Failed to load CustomDataView inspected type");
dataType = t;
}
private Type dataType { get; set; }
// map of [datType, viewType]
private static Dictionary<Type, Type> s_TypeMap;
public static DataContainer Create(GraphElementData data)
{
if (s_TypeMap == null)
{
s_TypeMap = new Dictionary<Type, Type>();
// add extension methods
AppDomain currentDomain = AppDomain.CurrentDomain;
foreach (Assembly assembly in currentDomain.GetAssemblies())
{
foreach (Type type in assembly.GetTypes())
{
var attributes = type.GetCustomAttributes(typeof(CustomDataView), false);
foreach (CustomDataView att in attributes)
{
s_TypeMap[att.dataType] = type;
}
}
}
}
Type viewType;
if (s_TypeMap.TryGetValue(data.GetType(), out viewType))
{
var dataContainer = (DataContainer)Activator.CreateInstance(viewType);
dataContainer.dataProvider = data;
return dataContainer;
}
throw new InvalidOperationException("No view in assembly for this data type" + data.GetType());
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace RMGUI.GraphView
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class CustomDataView : Attribute
{
public CustomDataView(Type t)
{
if (t == null)
Debug.LogError("Failed to load CustomDataView inspected type");
dataType = t;
}
private Type dataType { get; set; }
// map of [datType, viewType]
private static Dictionary<Type, Type> s_TypeMap;
public static DataContainer<GraphElementData> Create(GraphElementData data)
{
if (s_TypeMap == null)
{
s_TypeMap = new Dictionary<Type, Type>();
// add extension methods
AppDomain currentDomain = AppDomain.CurrentDomain;
foreach (Assembly assembly in currentDomain.GetAssemblies())
{
foreach (Type type in assembly.GetTypes())
{
var attributes = type.GetCustomAttributes(typeof(CustomDataView), false);
foreach (CustomDataView att in attributes)
{
s_TypeMap[att.dataType] = type;
}
}
}
}
Type viewType;
if (s_TypeMap.TryGetValue(data.GetType(), out viewType))
{
var dataContainer = (DataContainer<GraphElementData>)Activator.CreateInstance(viewType);
dataContainer.dataProvider = data;
return dataContainer;
}
throw new InvalidOperationException("No view in assembly for this data type" + data.GetType());
}
}
}

37
MaterialGraphProject/Assets/NewUI/Editor/DataContainer.cs


using System;
using UnityEngine;
using Object = UnityEngine.Object;
public class DataContainer : VisualContainer
{
IDataSource m_DataProvider;
public class DataContainer <T> : VisualContainer where T : GraphElementData
{
T m_DataProvider;
public IDataSource dataProvider
public T dataProvider
{
get { return m_DataProvider; }
set

}
}
public T GetData<T>() where T : GraphElementData
public TK GetData<TK>() where TK : T
return dataProvider as T;
return dataProvider as TK;
if (m_DataProvider != null && panel != null && m_DataProvider is Object)
if (m_DataProvider != null && panel != null)
DataWatchService.AddDataSpy(this, (Object) m_DataProvider, OnDataChanged);
DataWatchService.AddDataSpy(this, m_DataProvider, OnDataChanged);
if (m_DataProvider != null && panel != null && m_DataProvider is Object)
DataWatchService.RemoveDataSpy((Object) m_DataProvider, OnDataChanged);
}
try
{
if (m_DataProvider != null && panel != null)
DataWatchService.RemoveDataSpy(m_DataProvider, OnDataChanged);
}
catch (Exception e)
{
if (m_DataProvider != null)
{
Debug.LogWarningFormat("No datawatch is registered to: {0} it is type {1}", m_DataProvider.name, m_DataProvider.GetType());
}
Debug.LogException(e, m_DataProvider);
}
}
public DataContainer()
{

398
MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/Graph/NodeAnchor.cs


using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.RMGUI;
using UnityEngine.RMGUI.StyleEnums.Values;
namespace RMGUI.GraphView.Demo
{
[CustomDataView(typeof(NodeAnchorData))]
internal class NodeAnchor : GraphElement
{
public const float k_NodeSize = 15.0f;
private EdgeConnector<EdgeData> m_RegularConnector = new EdgeConnector<EdgeData>();
private EdgeConnector<CustomEdgeData> m_CustomConnector = new EdgeConnector<CustomEdgeData>();
private IManipulator m_CurrentConnector;
public NodeAnchor(NodeAnchorData data)
{
m_CurrentConnector = m_RegularConnector;
AddManipulator(m_CurrentConnector);
dataProvider = data;
}
private void UpdateConnector()
{
var nodeAnchorData = dataProvider as NodeAnchorData;
if (nodeAnchorData == null)
return;
RemoveManipulator(m_CurrentConnector);
if (!nodeAnchorData.connected || nodeAnchorData.direction != Direction.Input)
{
if (nodeAnchorData.orientation == Orientation.Horizontal)
{
m_CurrentConnector = m_RegularConnector;
}
else
{
m_CurrentConnector = m_CustomConnector;
}
AddManipulator(m_CurrentConnector);
}
}
private Rect GetAnchorRect(NodeAnchorData nodeAnchorData)
{
Rect rect = new Rect();
if (nodeAnchorData.orientation == Orientation.Horizontal)
{
// TODO: placement could be better handled using better CSS properties to place the node anchor itself.
if (nodeAnchorData.direction == Direction.Input)
{
rect = new Rect(position.x + 2, position.y + 2, k_NodeSize, k_NodeSize);
}
else if (nodeAnchorData.direction == Direction.Output)
{
rect = new Rect(position.x + position.width - (7 + k_NodeSize), position.y + 2, k_NodeSize, k_NodeSize);
}
}
else
{
if (nodeAnchorData.direction == Direction.Input)
{
rect = new Rect(position.x + (position.width - k_NodeSize)/2, position.y + 4, k_NodeSize, k_NodeSize);
}
else if (nodeAnchorData.direction == Direction.Output)
{
rect = new Rect(position.x + (position.width - k_NodeSize)/2, position.y + position.height - k_NodeSize - 8, k_NodeSize, k_NodeSize);
}
}
return rect;
}
protected virtual void DrawConnector()
{
// TODO This cast here is not ideal
var nodeAnchorData = dataProvider as NodeAnchorData;
if (nodeAnchorData == null)
return;
var anchorColor = Color.yellow;
anchorColor.a = 0.7f;
Rect rect = GetAnchorRect(nodeAnchorData);
Handles.DrawSolidRectangleWithOutline(rect, anchorColor, anchorColor);
if (nodeAnchorData.highlight)
{
var highlightColor = Color.blue;
Rect highlighRect = rect;
highlighRect.x += 4;
highlighRect.y += 4;
highlighRect.width -= 8;
highlighRect.height -= 8;
Handles.DrawSolidRectangleWithOutline(highlighRect, highlightColor, highlightColor);
}
}
public override void DoRepaint(PaintContext args)
{
base.DoRepaint(args);
DrawConnector();
}
public override void OnDataChanged()
{
UpdateConnector();
ClearChildren();
var nodeAnchorData = dataProvider as NodeAnchorData;
if (nodeAnchorData == null)
return;
Type type = nodeAnchorData.type;
Type genericClass = typeof(PortSource<>);
Type constructedClass = genericClass.MakeGenericType(type);
nodeAnchorData.source = Activator.CreateInstance(constructedClass);
Label label;
// TODO: I figure this placement could be more generic with a better use of CSS placement
if (nodeAnchorData.orientation == Orientation.Horizontal)
{
label = new Label(new GUIContent(nodeAnchorData.name))
{
positionType = PositionType.Absolute,
positionTop = 0,
positionLeft = 20,
positionRight = 0,
positionBottom = 0
};
if (nodeAnchorData.direction == Direction.Output)
{
label.textAlignment = TextAnchor.UpperRight;
label.positionLeft = 0;
label.positionRight = 25;
}
}
else
{
label = new Label(new GUIContent(type.Name))
{
positionType = PositionType.Absolute,
positionTop = 20,
positionLeft = 0,
positionRight = 0,
positionBottom = 0
};
if (nodeAnchorData.direction == Direction.Output)
{
label.textAlignment = TextAnchor.LowerCenter;
label.positionTop = 0;
label.positionBottom = 25;
}
else
{
label.textAlignment = TextAnchor.UpperCenter;
}
}
GetData<GraphElementData>().capabilities &= ~Capabilities.Selectable;
label.pickingMode = PickingMode.Ignore;
AddChild(label);
}
public Rect GetSelectionRect()
{
var nodeAnchorData = dataProvider as NodeAnchorData;
if (nodeAnchorData == null)
return new Rect();
return GetAnchorRect(nodeAnchorData);
}
public override Vector3 GetGlobalCenter()
{
var center = GetSelectionRect().center;
var globalCenter = new Vector3(center.x + parent.position.x, center.y + parent.position.y);
return parent.globalTransform.MultiplyPoint3x4(globalCenter);
}
public override bool Overlaps(Rect rect)
{
return GetSelectionRect().Overlaps(rect);
}
public override bool ContainsPoint(Vector2 localPoint)
{
return GetSelectionRect().Contains(localPoint);
}
}
}
using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.RMGUI;
using UnityEngine.RMGUI.StyleEnums.Values;
namespace RMGUI.GraphView.Demo
{
[CustomDataView(typeof(NodeAnchorData))]
internal class NodeAnchor : GraphElement
{
public const float k_NodeSize = 15.0f;
private EdgeConnector<EdgeData> m_RegularConnector = new EdgeConnector<EdgeData>();
private EdgeConnector<CustomEdgeData> m_CustomConnector = new EdgeConnector<CustomEdgeData>();
private IManipulator m_CurrentConnector;
public NodeAnchor(NodeAnchorData data)
{
m_CurrentConnector = m_RegularConnector;
AddManipulator(m_CurrentConnector);
dataProvider = data;
}
private void UpdateConnector()
{
var nodeAnchorData = dataProvider as NodeAnchorData;
if (nodeAnchorData == null)
return;
RemoveManipulator(m_CurrentConnector);
if (!nodeAnchorData.connected || nodeAnchorData.direction != Direction.Input)
{
if (nodeAnchorData.orientation == Orientation.Horizontal)
{
m_CurrentConnector = m_RegularConnector;
}
else
{
m_CurrentConnector = m_CustomConnector;
}
AddManipulator(m_CurrentConnector);
}
}
private Rect GetAnchorRect(NodeAnchorData nodeAnchorData)
{
Rect rect = new Rect();
if (nodeAnchorData.orientation == Orientation.Horizontal)
{
// TODO: placement could be better handled using better CSS properties to place the node anchor itself.
if (nodeAnchorData.direction == Direction.Input)
{
rect = new Rect(position.x + 2, position.y + 2, k_NodeSize, k_NodeSize);
}
else if (nodeAnchorData.direction == Direction.Output)
{
rect = new Rect(position.x + position.width - (7 + k_NodeSize), position.y + 2, k_NodeSize, k_NodeSize);
}
}
else
{
if (nodeAnchorData.direction == Direction.Input)
{
rect = new Rect(position.x + (position.width - k_NodeSize)/2, position.y + 4, k_NodeSize, k_NodeSize);
}
else if (nodeAnchorData.direction == Direction.Output)
{
rect = new Rect(position.x + (position.width - k_NodeSize)/2, position.y + position.height - k_NodeSize - 8, k_NodeSize, k_NodeSize);
}
}
return rect;
}
protected virtual void DrawConnector()
{
// TODO This cast here is not ideal
var nodeAnchorData = dataProvider as NodeAnchorData;
if (nodeAnchorData == null)
return;
var anchorColor = Color.yellow;
anchorColor.a = 0.7f;
Rect rect = GetAnchorRect(nodeAnchorData);
Handles.DrawSolidRectangleWithOutline(rect, anchorColor, anchorColor);
if (nodeAnchorData.highlight)
{
var highlightColor = Color.blue;
Rect highlighRect = rect;
highlighRect.x += 4;
highlighRect.y += 4;
highlighRect.width -= 8;
highlighRect.height -= 8;
Handles.DrawSolidRectangleWithOutline(highlighRect, highlightColor, highlightColor);
}
}
public override void DoRepaint(PaintContext args)
{
base.DoRepaint(args);
DrawConnector();
}
public override void OnDataChanged()
{
UpdateConnector();
ClearChildren();
var nodeAnchorData = dataProvider as NodeAnchorData;
if (nodeAnchorData == null)
return;
Type type = nodeAnchorData.type;
Type genericClass = typeof(PortSource<>);
Type constructedClass = genericClass.MakeGenericType(type);
nodeAnchorData.source = Activator.CreateInstance(constructedClass);
Label label;
// TODO: I figure this placement could be more generic with a better use of CSS placement
if (nodeAnchorData.orientation == Orientation.Horizontal)
{
label = new Label(new GUIContent(nodeAnchorData.name))
{
positionType = PositionType.Absolute,
positionTop = 0,
positionLeft = 20,
positionRight = 0,
positionBottom = 0
};
if (nodeAnchorData.direction == Direction.Output)
{
label.textAlignment = TextAnchor.UpperRight;
label.positionLeft = 0;
label.positionRight = 25;
}
}
else
{
label = new Label(new GUIContent(type.Name))
{
positionType = PositionType.Absolute,
positionTop = 20,
positionLeft = 0,
positionRight = 0,
positionBottom = 0
};
if (nodeAnchorData.direction == Direction.Output)
{
label.textAlignment = TextAnchor.LowerCenter;
label.positionTop = 0;
label.positionBottom = 25;
}
else
{
label.textAlignment = TextAnchor.UpperCenter;
}
}
GetData<GraphElementData>().capabilities &= ~Capabilities.Selectable;
label.pickingMode = PickingMode.Ignore;
AddChild(label);
}
public Rect GetSelectionRect()
{
var nodeAnchorData = dataProvider as NodeAnchorData;
if (nodeAnchorData == null)
return new Rect();
return GetAnchorRect(nodeAnchorData);
}
public override Vector3 GetGlobalCenter()
{
var center = GetSelectionRect().center;
var globalCenter = new Vector3(center.x + parent.position.x, center.y + parent.position.y);
return parent.globalTransform.MultiplyPoint3x4(globalCenter);
}
public override bool Overlaps(Rect rect)
{
return GetSelectionRect().Overlaps(rect);
}
public override bool ContainsPoint(Vector2 localPoint)
{
return GetSelectionRect().Contains(localPoint);
}
}
}

92
MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/InvisibleBorderContainer.cs


using UnityEditor;
using UnityEngine;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView.Demo
{
[CustomDataView(typeof(InvisibleBorderContainerData))]
public class InvisibleBorderContainer : GraphElement
{
private readonly Color m_OutlineColor = new Color(0.0f, 0.0f, 0.0f, 0.5f);
private Rect selectRect
{
get
{
return new Rect(position.width * 0.1f, position.height * 0.1f, position.width * 0.8f, position.height * 0.8f);
}
}
Rect GetRectWithOutline()
{
return new Rect(position.x + selectRect.x, position.y+selectRect.y, selectRect.width, selectRect.height);
}
public override bool Overlaps(Rect rectangle)
{
return GetRectWithOutline().Overlaps(rectangle);
}
public override bool ContainsPoint(Vector2 localPoint)
{
return GetRectWithOutline().Contains(localPoint);
}
public override void DoRepaint(PaintContext args)
{
Color color = m_OutlineColor;
if (GetData<GraphElementData>() != null && GetData<GraphElementData>().selected)
color = Color.blue;
Handles.DrawSolidRectangleWithOutline(position, color, color);
Rect zone = GetRectWithOutline();
Handles.DrawSolidRectangleWithOutline(zone, Color.green, Color.green);
}
}
}
using UnityEditor;
using UnityEngine;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView.Demo
{
[CustomDataView(typeof(InvisibleBorderContainerData))]
public class InvisibleBorderContainer : GraphElement
{
private readonly Color m_OutlineColor = new Color(0.0f, 0.0f, 0.0f, 0.5f);
private Rect selectRect
{
get
{
return new Rect(position.width * 0.1f, position.height * 0.1f, position.width * 0.8f, position.height * 0.8f);
}
}
Rect GetRectWithOutline()
{
return new Rect(position.x + selectRect.x, position.y+selectRect.y, selectRect.width, selectRect.height);
}
public override bool Overlaps(Rect rectangle)
{
return GetRectWithOutline().Overlaps(rectangle);
}
public override bool ContainsPoint(Vector2 localPoint)
{
return GetRectWithOutline().Contains(localPoint);
}
public override void DoRepaint(PaintContext args)
{
Color color = m_OutlineColor;
if (GetData<GraphElementData>() != null && GetData<GraphElementData>().selected)
color = Color.blue;
Handles.DrawSolidRectangleWithOutline(position, color, color);
Rect zone = GetRectWithOutline();
Handles.DrawSolidRectangleWithOutline(zone, Color.green, Color.green);
}
}
}

60
MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/IMGUISampleView.cs


using UnityEditor;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView.Demo
{
public class IMGUISampleView : EditorWindow
{
[MenuItem("Window/GraphView Demo/IMGUISampleView")]
public static void ShowWindow()
{
GetWindow<IMGUISampleView>();
}
void OnEnable()
{
var view = new SimpleContentView
{
name = "theView",
dataProvider = CreateInstance<IMGUISampleViewData>()
};
view.StretchToParentSize();
windowRoot.AddChild(view);
}
void OnDisable()
{
windowRoot.ClearChildren();
}
}
}
using UnityEditor;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView.Demo
{
public class IMGUISampleView : EditorWindow
{
[MenuItem("Window/GraphView Demo/IMGUISampleView")]
public static void ShowWindow()
{
GetWindow<IMGUISampleView>();
}
void OnEnable()
{
var view = new SimpleContentView
{
name = "theView",
dataSource = CreateInstance<IMGUISampleViewData>()
};
view.StretchToParentSize();
windowRoot.AddChild(view);
}
void OnDisable()
{
windowRoot.ClearChildren();
}
}
}

6
MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/NodalView.cs


public void CreateOperator()
{
NodalViewData nodalViewData = dataProvider as NodalViewData;
NodalViewData nodalViewData = dataSource as NodalViewData;
if (nodalViewData != null)
{
var x = rnd.Next(0, 600);

private EventPropagation DeleteSelection()
{
// and DeleteSelection would call that method.
var nodalViewData = dataProvider as NodalViewData;
var nodalViewData = dataSource as NodalViewData;
if (nodalViewData == null)
return EventPropagation.Stop;

var view = new NodesContentView
{
name = "theView",
dataProvider = CreateInstance<NodalViewData>()
dataSource = CreateInstance<NodalViewData>()
};
view.StretchToParentSize();

62
MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/SimpleGraphView.cs


using UnityEditor;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView.Demo
{
public class SimpleGraphView : EditorWindow
{
[MenuItem("Window/GraphView Demo/SimpleGraphView")]
public static void ShowWindow()
{
GetWindow<SimpleGraphView>();
}
void OnEnable()
{
var view = new SimpleContentView
{
name = "theView",
dataProvider = CreateInstance<SimpleGraphViewData>()
};
view.StretchToParentSize();
windowRoot.AddChild(view);
}
void OnDisable()
{
windowRoot.ClearChildren();
}
}
}
using UnityEditor;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView.Demo
{
public class SimpleGraphView : EditorWindow
{
[MenuItem("Window/GraphView Demo/SimpleGraphView")]
public static void ShowWindow()
{
GetWindow<SimpleGraphView>();
}
void OnEnable()
{
var view = new SimpleContentView
{
name = "theView",
dataSource = CreateInstance<SimpleGraphViewData>()
};
view.StretchToParentSize();
windowRoot.AddChild(view);
}
void OnDisable()
{
windowRoot.ClearChildren();
}
}
}

8
MaterialGraphProject/Assets/NewUI/Editor/Elements/Data/GraphElementData.cs


namespace RMGUI.GraphView
{
[Serializable]
public abstract class GraphElementData : ScriptableObject, IDataSource
public abstract class GraphElementData : ScriptableObject
{
[SerializeField]
private bool m_Selected;

{
get { return new GraphElementData[0]; }
}
public virtual void AddElement(GraphElementData element)
{}
public virtual void RemoveElement(GraphElementData element)
{}
public Capabilities capabilities
{

112
MaterialGraphProject/Assets/NewUI/Editor/Elements/GraphElement.cs


using UnityEngine;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView
{
public class GraphElement : DataContainer, ISelectable
{
public override void OnDataChanged()
{
var data = GetData<GraphElementData>();
if (data == null)
{
return;
}
// propagate selection but why?
foreach (VisualElement ve in children)
{
GraphElement ce = ve as GraphElement;
if (ce != null )
{
var childData = ce.dataProvider as GraphElementData;
if (childData != null)
{
childData.selected = data.selected;
}
}
}
SetPosition(data.position);
}
public virtual bool IsSelectable()
{
var data = GetData<GraphElementData>();
if (data != null)
{
return (data.capabilities & Capabilities.Selectable) == Capabilities.Selectable;
}
return false;
}
public virtual Vector3 GetGlobalCenter()
{
var center = position.center;
var globalCenter = new Vector3(center.x + parent.position.x, center.y + parent.position.y);
return parent.globalTransform.MultiplyPoint3x4(globalCenter);
}
public virtual void SetPosition(Rect newPos)
{
// set absolute position from data
position = newPos;
}
}
}
using UnityEngine;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView
{
public class GraphElement : DataContainer<GraphElementData>, ISelectable
{
public override void OnDataChanged()
{
var data = GetData<GraphElementData>();
if (data == null)
{
return;
}
// propagate selection but why?
foreach (VisualElement ve in children)
{
GraphElement ce = ve as GraphElement;
if (ce != null )
{
var childData = ce.dataProvider;
if (childData != null)
{
childData.selected = data.selected;
}
}
}
SetPosition(data.position);
}
public virtual bool IsSelectable()
{
var data = GetData<GraphElementData>();
if (data != null)
{
return (data.capabilities & Capabilities.Selectable) == Capabilities.Selectable;
}
return false;
}
public virtual Vector3 GetGlobalCenter()
{
var center = position.center;
var globalCenter = new Vector3(center.x + parent.position.x, center.y + parent.position.y);
return parent.globalTransform.MultiplyPoint3x4(globalCenter);
}
public virtual void SetPosition(Rect newPos)
{
// set absolute position from data
position = newPos;
}
}
}

304
MaterialGraphProject/Assets/NewUI/Editor/Manipulators/EdgeConnector.cs


using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView
{
internal class EdgeConnector<TEdgeData> : Manipulator where TEdgeData : EdgeData, new()
{
private List<IConnectable> m_CompatibleAnchors = new List<IConnectable>();
private TEdgeData m_EdgeDataCandidate;
private IDataSource m_GraphViewData;
private GraphView m_GraphView;
public MouseButton activateButton { get; set; }
public EdgeConnector()
{
activateButton = MouseButton.LeftMouse;
}
public override EventPropagation HandleEvent(Event evt, VisualElement finalTarget)
{
switch (evt.type)
{
case EventType.MouseDown:
if (evt.button != (int)activateButton)
{
break;
}
IConnectable cnx = null;
var graphElement = finalTarget as GraphElement;
if (graphElement != null && graphElement.GetData<GraphElementData>() != null)
{
var data = graphElement.GetData<GraphElementData>();
cnx = (IConnectable)data;
m_GraphView = graphElement.GetFirstAncestorOfType<GraphView>();
}
if (cnx == null || m_GraphView == null)
{
break;
}
m_GraphViewData = m_GraphView.dataProvider;
if (m_GraphViewData == null)
{
break;
}
this.TakeCapture();
m_CompatibleAnchors.Clear();
NodeAdapter nodeAdapter = new NodeAdapter();
// get all available connectors
IEnumerable<IConnectable> visibleAnchors = m_GraphView.allChildren.OfType<GraphElement>()
.Select( e => e.dataProvider)
.OfType<IConnectable>()
.Where(a => a.IsConnectable() );
foreach (var toCnx in visibleAnchors)
{
if (cnx.orientation != toCnx.orientation)
continue;
bool isBidirectional = ((cnx.direction == Direction.Bidirectional) ||
(toCnx.direction == Direction.Bidirectional));
if (cnx.direction != toCnx.direction || isBidirectional)
{
if (nodeAdapter.GetAdapter(cnx.source, toCnx.source) != null)
{
toCnx.highlight = true;
m_CompatibleAnchors.Add(toCnx);
}
}
}
m_EdgeDataCandidate = ScriptableObject.CreateInstance<TEdgeData>();
m_EdgeDataCandidate.position = new Rect(0, 0, 1, 1);
m_EdgeDataCandidate.left = graphElement.dataProvider as IConnectable;
m_EdgeDataCandidate.right = null;
m_EdgeDataCandidate.candidate = true;
m_EdgeDataCandidate.candidatePosition = target.LocalToGlobal(evt.mousePosition);
m_GraphViewData.AddElement(m_EdgeDataCandidate);
return EventPropagation.Stop;
case EventType.MouseDrag:
if (this.HasCapture())
{
m_EdgeDataCandidate.candidatePosition = target.LocalToGlobal(evt.mousePosition);
return EventPropagation.Stop;
}
break;
case EventType.MouseUp:
if (this.HasCapture() && evt.button == (int) activateButton)
{
this.ReleaseCapture();
foreach (var compatibleAnchor in m_CompatibleAnchors)
{
compatibleAnchor.highlight = false;
if (m_GraphView != null)
{
GraphElement anchorElement = m_GraphView.allElements.OfType<GraphElement>().First(e => e.dataProvider == (Object)compatibleAnchor);
if (anchorElement != null)
{
if (anchorElement.globalBound.Contains(target.LocalToGlobal(evt.mousePosition)))
{
m_EdgeDataCandidate.right = compatibleAnchor;
}
}
}
}
m_CompatibleAnchors.Clear();
if (m_EdgeDataCandidate != null && m_GraphViewData != null)
{
// Not a candidate anymore, let's see if we're actually going to add it to parent
m_EdgeDataCandidate.candidate = false;
if (m_EdgeDataCandidate.right == null)
{
m_GraphViewData.RemoveElement(m_EdgeDataCandidate);
}
else
{
m_EdgeDataCandidate.left.connected = true;
m_EdgeDataCandidate.right.connected = true;
}
}
m_EdgeDataCandidate = null;
m_GraphViewData = null;
return EventPropagation.Stop;
}
break;
}
return this.HasCapture() ? EventPropagation.Stop : EventPropagation.Continue;
}
}
}
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.RMGUI;
namespace RMGUI.GraphView
{
internal class EdgeConnector<TEdgeData> : Manipulator where TEdgeData : EdgeData, new()
{
private List<IConnectable> m_CompatibleAnchors = new List<IConnectable>();
private TEdgeData m_EdgeDataCandidate;
private GraphView m_GraphView;
public MouseButton activateButton { get; set; }
public EdgeConnector()
{
activateButton = MouseButton.LeftMouse;
}
public override EventPropagation HandleEvent(Event evt, VisualElement finalTarget)
{
var dataSource = m_GraphView.dataSource;
switch (evt.type)
{
case EventType.MouseDown:
if (evt.button != (int)activateButton)
{
break;
}
IConnectable cnx = null;
var graphElement = finalTarget as GraphElement;
if (graphElement != null && graphElement.GetData<GraphElementData>() != null)
{
var data = graphElement.GetData<GraphElementData>();
cnx = (IConnectable)data;
m_GraphView = graphElement.GetFirstAncestorOfType<GraphView>();
}
if (cnx == null || m_GraphView == null)
{
break;
}
if (m_GraphView.dataSource == null)
{
break;
}
this.TakeCapture();
m_CompatibleAnchors.Clear();
NodeAdapter nodeAdapter = new NodeAdapter();
// get all available connectors
IEnumerable<IConnectable> visibleAnchors = m_GraphView.allChildren.OfType<GraphElement>()
.Select( e => e.dataProvider)
.OfType<IConnectable>()
.Where(a => a.IsConnectable() );
foreach (var toCnx in visibleAnchors)
{
if (cnx.orientation != toCnx.orientation)
continue;
bool isBidirectional = ((cnx.direction == Direction.Bidirectional) ||
(toCnx.direction == Direction.Bidirectional));
if (cnx.direction != toCnx.direction || isBidirectional)
{
if (nodeAdapter.GetAdapter(cnx.source, toCnx.source) != null)
{
toCnx.highlight = true;
m_CompatibleAnchors.Add(toCnx);
}
}
}
m_EdgeDataCandidate = ScriptableObject.CreateInstance<TEdgeData>();
m_EdgeDataCandidate.position = new Rect(0, 0, 1, 1);
m_EdgeDataCandidate.left = graphElement.dataProvider as IConnectable;
m_EdgeDataCandidate.right = null;
m_EdgeDataCandidate.candidate = true;
m_EdgeDataCandidate.candidatePosition = target.LocalToGlobal(evt.mousePosition);
dataSource.AddElement(m_EdgeDataCandidate);
return EventPropagation.Stop;
case EventType.MouseDrag:
if (this.HasCapture())
{
m_EdgeDataCandidate.candidatePosition = target.LocalToGlobal(evt.mousePosition);
return EventPropagation.Stop;
}
break;
case EventType.MouseUp:
if (this.HasCapture() && evt.button == (int) activateButton)
{
this.ReleaseCapture();
foreach (var compatibleAnchor in m_CompatibleAnchors)
{
compatibleAnchor.highlight = false;
if (m_GraphView != null)
{
GraphElement anchorElement = m_GraphView.allElements.OfType<GraphElement>().First(e => e.dataProvider == (Object)compatibleAnchor);
if (anchorElement != null)
{
if (anchorElement.globalBound.Contains(target.LocalToGlobal(evt.mousePosition)))
{
m_EdgeDataCandidate.right = compatibleAnchor;
}
}
}
}
m_CompatibleAnchors.Clear();
if (m_EdgeDataCandidate != null && dataSource != null)
{
// Not a candidate anymore, let's see if we're actually going to add it to parent
m_EdgeDataCandidate.candidate = false;
if (m_EdgeDataCandidate.right == null)
{
dataSource.RemoveElement(m_EdgeDataCandidate);
}
else
{
m_EdgeDataCandidate.left.connected = true;
m_EdgeDataCandidate.right.connected = true;
}
}
m_EdgeDataCandidate = null;
return EventPropagation.Stop;
}
break;
}
return this.HasCapture() ? EventPropagation.Stop : EventPropagation.Continue;
}
}
}

2
MaterialGraphProject/Assets/NewUI/Editor/Views/Data/GraphViewDataSource.cs


namespace RMGUI.GraphView
{
[Serializable]
public abstract class GraphViewDataSource : ScriptableObject, IDataSource
public abstract class GraphViewDataSource : ScriptableObject, IGraphElementDataSource
{
[SerializeField]
private List<GraphElementData> m_Elements = new List<GraphElementData>();

2
MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IGraphElementDataSource.cs


namespace RMGUI.GraphView
{
public interface IDataSource
public interface IGraphElementDataSource
{
IEnumerable<GraphElementData> elements { get; }
void AddElement(GraphElementData element);

321
MaterialGraphProject/Assets/NewUI/Editor/Views/GraphView.cs


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 : DataContainer, ISelection
{
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);
}
public override void OnDataChanged()
{
if (dataProvider == null)
return;
// process removals
var current = contentViewContainer.children.OfType<GraphElement>().ToList();
current.AddRange(children.OfType<GraphElement>().ToList());
foreach (var c in current)
{
// been removed?
if (!dataProvider.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 dataProvider.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);
}
}
}
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);
}
}
}

430
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/AbstractMaterialNodeUI.cs


using System;
using System.Reflection;
using RMGUI.GraphView;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
using Object = UnityEngine.Object;
namespace UnityEditor.MaterialGraph
{
/* [CustomDataView(typeof(NodePreviewData))]
public class NodePreview : GraphElement
{
public NodePreview(NodePreviewData preview)
{
dataProvider = preview;
}
public override void DoRepaint(PaintContext args)
{
base.DoRepaint(args);
m_WwwTexture = new Texture2D(4, 4, TextureFormat.DXT1, false);
AddChild(new Image { image = m_WwwTexture });
Handles.DrawSolidRectangleWithOutline(parent.position, Color.red, Color.blue);
}
}*/
[Serializable]
public class NodePreviewData : GraphElementData
{
protected NodePreviewData()
{ }
private MaterialGraphPreviewGenerator m_PreviewGenerator;
[NonSerialized]
private int m_LastShaderVersion = -1;
[NonSerialized]
private Material m_PreviewMaterial;
[NonSerialized]
private Shader m_PreviewShader;
private AbstractMaterialNode m_Node;
private PreviewMode m_GeneratedShaderMode = PreviewMode.Preview2D;
public Material previewMaterial
{
get
{
if (m_PreviewMaterial == null)
{
m_PreviewMaterial = new Material(Shader.Find("Unlit/Color")) {hideFlags = HideFlags.HideInHierarchy};
m_PreviewMaterial.hideFlags = HideFlags.HideInHierarchy;
}
return m_PreviewMaterial;
}
}
private MaterialGraphPreviewGenerator previewGenerator
{
get
{
if (m_PreviewGenerator == null)
{
m_PreviewGenerator = new MaterialGraphPreviewGenerator();
}
return m_PreviewGenerator;
}
}
public void Initialize(AbstractMaterialNode node)
{
m_Node = node;
}
public Texture Render(Vector2 dimension)
{
if (m_Node == null)
return null;
if (m_Node.hasPreview == false)
return null;
if (m_LastShaderVersion != m_Node.version)
{
if (UpdatePreviewShader())
m_LastShaderVersion = m_Node.version;
}
return RenderPreview(dimension);
}
protected virtual string GetPreviewShaderString()
{
return ShaderGenerator.GeneratePreviewShader(m_Node, out m_GeneratedShaderMode);
}
private bool UpdatePreviewShader()
{
if (m_Node == null || m_Node.hasError)
return false;
var resultShader = GetPreviewShaderString();
Debug.Log("RecreateShaderAndMaterial : " + m_Node.GetVariableNameForNode() + Environment.NewLine + resultShader);
if (string.IsNullOrEmpty(resultShader))
return false;
// workaround for some internal shader compiler weirdness
// if we are in error we sometimes to not properly clean
// out the error flags and will stay in error, even
// if we are now valid
if (m_PreviewShader && ShaderHasError(m_PreviewShader))
{
Object.DestroyImmediate(m_PreviewShader, true);
m_PreviewShader = null;
}
if (m_PreviewShader == null)
{
m_PreviewShader = ShaderUtil.CreateShaderAsset(resultShader);
m_PreviewShader.hideFlags = HideFlags.HideAndDontSave;
}
else
{
ShaderUtil.UpdateShaderAsset(m_PreviewShader, resultShader);
}
return !ShaderHasError(m_PreviewShader);
}
public static bool ShaderHasError(Shader shader)
{
var hasErrorsCall = typeof(ShaderUtil).GetMethod("GetShaderErrorCount", BindingFlags.Static | BindingFlags.NonPublic);
var result = hasErrorsCall.Invoke(null, new object[] {shader});
return (int)result != 0;
}
/// <summary>
/// RenderPreview gets called in OnPreviewGUI. Nodes can override
/// RenderPreview and do their own rendering to the render texture
/// </summary>
private Texture RenderPreview(Vector2 targetSize)
{
previewMaterial.shader = m_PreviewShader;
UpdateMaterialProperties(m_Node, previewMaterial);
return previewGenerator.DoRenderPreview(previewMaterial, m_GeneratedShaderMode, new Rect(0, 0, targetSize.x, targetSize.y));
}
private static void SetPreviewMaterialProperty(PreviewProperty previewProperty, Material mat)
{
switch (previewProperty.m_PropType)
{
case PropertyType.Texture2D:
mat.SetTexture(previewProperty.m_Name, previewProperty.m_Texture);
break;
case PropertyType.Color:
mat.SetColor(previewProperty.m_Name, previewProperty.m_Color);
break;
case PropertyType.Vector2:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Vector3:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Vector4:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Float:
mat.SetFloat(previewProperty.m_Name, previewProperty.m_Float);
break;
}
}
public static void UpdateMaterialProperties(AbstractMaterialNode target, Material material)
{
var childNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(childNodes, target);
var pList = ListPool<PreviewProperty>.Get();
for (var index = 0; index < childNodes.Count; index++)
{
var node = childNodes[index] as AbstractMaterialNode;
if (node == null)
continue;
node.CollectPreviewMaterialProperties(pList);
}
foreach (var prop in pList)
SetPreviewMaterialProperty(prop, material);
ListPool<INode>.Release(childNodes);
ListPool<PreviewProperty>.Release(pList);
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using RMGUI.GraphView;
using UnityEngine;
using UnityEngine.Graphing;
using UnityEngine.MaterialGraph;
using Object = UnityEngine.Object;
namespace UnityEditor.MaterialGraph
{
/* [CustomDataView(typeof(NodePreviewData))]
public class NodePreview : GraphElement
{
public NodePreview(NodePreviewData preview)
{
dataProvider = preview;
}
public override void DoRepaint(PaintContext args)
{
base.DoRepaint(args);
m_WwwTexture = new Texture2D(4, 4, TextureFormat.DXT1, false);
AddChild(new Image { image = m_WwwTexture });
Handles.DrawSolidRectangleWithOutline(parent.position, Color.red, Color.blue);
}
}*/
[Serializable]
public abstract class NodeControlData : GraphElementData
{
protected NodeControlData()
{ }
public abstract void OnGUIHandler();
}
[Serializable]
public class NodePreviewData : GraphElementData
{
protected NodePreviewData()
{ }
private MaterialGraphPreviewGenerator m_PreviewGenerator;
[NonSerialized]
private int m_LastShaderVersion = -1;
[NonSerialized]
private Material m_PreviewMaterial;
[NonSerialized]
private Shader m_PreviewShader;
private AbstractMaterialNode m_Node;
private PreviewMode m_GeneratedShaderMode = PreviewMode.Preview2D;
public Material previewMaterial
{
get
{
if (m_PreviewMaterial == null)
{
m_PreviewMaterial = new Material(Shader.Find("Unlit/Color")) {hideFlags = HideFlags.HideInHierarchy};
m_PreviewMaterial.hideFlags = HideFlags.HideInHierarchy;
}
return m_PreviewMaterial;
}
}
private MaterialGraphPreviewGenerator previewGenerator
{
get
{
if (m_PreviewGenerator == null)
{
m_PreviewGenerator = new MaterialGraphPreviewGenerator();
}
return m_PreviewGenerator;
}
}
public void Initialize(AbstractMaterialNode node)
{
m_Node = node;
}
public Texture Render(Vector2 dimension)
{
if (m_Node == null)
return null;
if (m_Node.hasPreview == false)
return null;
if (m_LastShaderVersion != m_Node.version)
{
if (UpdatePreviewShader())
m_LastShaderVersion = m_Node.version;
}
return RenderPreview(dimension);
}
protected virtual string GetPreviewShaderString()
{
// TODO: this is a workaround right now.
if (m_Node is PixelShaderNode)
{
var localNode = (PixelShaderNode) m_Node;
if (localNode == null)
return string.Empty;
var shaderName = "Hidden/PreviewShader/" + localNode.GetVariableNameForNode();
List<PropertyGenerator.TextureInfo> defaultTextures;
//TODO: Need to get the real options somehow
var resultShader = ShaderGenerator.GenerateSurfaceShader(localNode, new MaterialOptions(), shaderName, true, out defaultTextures);
m_GeneratedShaderMode = PreviewMode.Preview3D;
return resultShader;
}
return ShaderGenerator.GeneratePreviewShader(m_Node, out m_GeneratedShaderMode);
}
private bool UpdatePreviewShader()
{
if (m_Node == null || m_Node.hasError)
return false;
var resultShader = GetPreviewShaderString();
Debug.Log("RecreateShaderAndMaterial : " + m_Node.GetVariableNameForNode() + Environment.NewLine + resultShader);
if (string.IsNullOrEmpty(resultShader))
return false;
// workaround for some internal shader compiler weirdness
// if we are in error we sometimes to not properly clean
// out the error flags and will stay in error, even
// if we are now valid
if (m_PreviewShader && ShaderHasError(m_PreviewShader))
{
Object.DestroyImmediate(m_PreviewShader, true);
m_PreviewShader = null;
}
if (m_PreviewShader == null)
{
m_PreviewShader = ShaderUtil.CreateShaderAsset(resultShader);
m_PreviewShader.hideFlags = HideFlags.HideAndDontSave;
}
else
{
ShaderUtil.UpdateShaderAsset(m_PreviewShader, resultShader);
}
return !ShaderHasError(m_PreviewShader);
}
public static bool ShaderHasError(Shader shader)
{
var hasErrorsCall = typeof(ShaderUtil).GetMethod("GetShaderErrorCount", BindingFlags.Static | BindingFlags.NonPublic);
var result = hasErrorsCall.Invoke(null, new object[] {shader});
return (int)result != 0;
}
/// <summary>
/// RenderPreview gets called in OnPreviewGUI. Nodes can override
/// RenderPreview and do their own rendering to the render texture
/// </summary>
private Texture RenderPreview(Vector2 targetSize)
{
previewMaterial.shader = m_PreviewShader;
UpdateMaterialProperties(m_Node, previewMaterial);
return previewGenerator.DoRenderPreview(previewMaterial, m_GeneratedShaderMode, new Rect(0, 0, targetSize.x, targetSize.y));
}
private static void SetPreviewMaterialProperty(PreviewProperty previewProperty, Material mat)
{
switch (previewProperty.m_PropType)
{
case PropertyType.Texture2D:
mat.SetTexture(previewProperty.m_Name, previewProperty.m_Texture);
break;
case PropertyType.Color:
mat.SetColor(previewProperty.m_Name, previewProperty.m_Color);
break;
case PropertyType.Vector2:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Vector3:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Vector4:
mat.SetVector(previewProperty.m_Name, previewProperty.m_Vector4);
break;
case PropertyType.Float:
mat.SetFloat(previewProperty.m_Name, previewProperty.m_Float);
break;
}
}
public static void UpdateMaterialProperties(AbstractMaterialNode target, Material material)
{
var childNodes = ListPool<INode>.Get();
NodeUtils.DepthFirstCollectNodesFromNode(childNodes, target);
var pList = ListPool<PreviewProperty>.Get();
for (var index = 0; index < childNodes.Count; index++)
{
var node = childNodes[index] as AbstractMaterialNode;
if (node == null)
continue;
node.CollectPreviewMaterialProperties(pList);
}
foreach (var prop in pList)
SetPreviewMaterialProperty(prop, material);
ListPool<INode>.Release(childNodes);
ListPool<PreviewProperty>.Release(pList);
}
}
}

93
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Styles/NodalView.uss


MaterialGraphNode {
flex-direction: column;
}
MaterialGraphNode #slots {
flex-direction: row;
}
MaterialGraphNode #slots #input {
flex:1;
flex-direction: column;
}
MaterialGraphNode #slots #output {
flex:1;
flex-direction: column;
}
MaterialGraphNode #controls {
flex-direction: column;
}
MaterialGraphNode #preview {
flex-direction: column;
height: 200;
width: 200;
}
NodeAnchor {
height: 26;
width: 100;
}
/* Example of dynamic properties
Read from the GridBackground decorator
#contentViewContainer {
background-color:#404749;
line-color:#20293F;
thick-line-color:#030C22;
spacing:50.0;
thick-lines:10;
}*/
MaterialGraphNode {
flex-direction: column;
}
MaterialGraphNode #slots {
flex-direction: row;
}
MaterialGraphNode #slots #input {
flex:1;
flex-direction: column;
}
MaterialGraphNode #slots #output {
flex:1;
flex-direction: column;
}
MaterialGraphNode #controls {
flex-direction: column;
height: 26;
}
MaterialGraphNode #controls #element{
flex-direction: column;
flex:1;
}
MaterialGraphNode #preview {
flex-direction: column;
}
MaterialGraphNode #preview #image {
height: 200;
width: 200;
align-self: center;
}
NodeAnchor {
height: 26;
}
/* Example of dynamic properties
Read from the GridBackground decorator
#contentViewContainer {
background-color:#404749;
line-color:#20293F;
thick-line-color:#030C22;
spacing:50.0;
thick-lines:10;
}*/

5
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/ColorNode.cs


UpdateNodeAfterDeserialization();
}
public override bool hasPreview
{
get { return true; }
}
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));

/MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IDataSource.cs.meta → /MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IGraphElementDataSource.cs.meta

/MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IDataSource.cs → /MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IGraphElementDataSource.cs

正在加载...
取消
保存