Tim Cooper
8 年前
当前提交
8c5f323e
共有 61 个文件被更改,包括 1825 次插入 和 2244 次删除
-
750MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/GraphEditWindow.cs
-
146MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphDataSource.cs
-
94MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialGraphNode.cs
-
55MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialNodeData.cs
-
108MaterialGraphProject/Assets/NewUI/Editor/DataContainer.cs
-
4MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/Data/MiniMapData.cs
-
2MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/Graph/CustomEdge.cs
-
40MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/Graph/Data/NodeData.cs
-
10MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/Graph/Data/VerticalNodeData.cs
-
54MaterialGraphProject/Assets/NewUI/Editor/Demo/Elements/MiniMap.cs
-
131MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/Data/IMGUISampleViewData.cs
-
14MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/Data/SimpleGraphView.cs
-
6MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/IMGUISampleView.cs
-
272MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/NodalView.cs
-
3MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/SimpleContentView.cs
-
6MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/SimpleGraphView.cs
-
4MaterialGraphProject/Assets/NewUI/Editor/Elements/Data/EdgeData.cs
-
120MaterialGraphProject/Assets/NewUI/Editor/Elements/Data/GraphElementData.cs
-
90MaterialGraphProject/Assets/NewUI/Editor/Elements/Edge.cs
-
11MaterialGraphProject/Assets/NewUI/Editor/Elements/GraphElement.cs
-
23MaterialGraphProject/Assets/NewUI/Editor/Manipulators/Dragger.cs
-
12MaterialGraphProject/Assets/NewUI/Editor/Manipulators/EdgeConnector.cs
-
344MaterialGraphProject/Assets/NewUI/Editor/Manipulators/Resizer.cs
-
19MaterialGraphProject/Assets/NewUI/Editor/NodeAdapter.cs
-
64MaterialGraphProject/Assets/NewUI/Editor/Views/Data/GraphViewDataSource.cs
-
12MaterialGraphProject/Assets/NewUI/Editor/Views/GraphView.cs
-
25MaterialGraphProject/Assets/NewUI/Editor/Views/GraphView.uss
-
417MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/AbstractMaterialNodeUI.cs
-
6MaterialGraphProject/Assets/UnityShaderEditor/Editor/Editors/MaterialGraphEditor.cs
-
22MaterialGraphProject/Assets/UnityShaderEditor/Editor/Styles/NodalView.uss
-
402MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/IntegrationTests/ShaderGenerationTest.cs
-
2MaterialGraphProject/MaterialGraphProject.sln.DotSettings.user
-
2MaterialGraphProject/ProjectSettings/ProjectVersion.txt
-
25MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialNodeAnchorData.cs
-
12MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/MaterialNodeAnchorData.cs.meta
-
43MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/NodalView.uss
-
8MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/NodalView.uss.meta
-
34MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/SimpleContentView.uss
-
8MaterialGraphProject/Assets/NewUI/Editor/Demo/Views/SimpleContentView.uss.meta
-
11MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IDataSource.cs
-
12MaterialGraphProject/Assets/NewUI/Editor/Views/Data/IDataSource.cs.meta
-
51MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector4NodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector4NodeUI.cs.meta
-
65MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/PixelShaderNodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/PixelShaderNodeUI.cs.meta
-
49MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/ColorNodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/ColorNodeUI.cs.meta
-
37MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/CombineNodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/CombineNodeUI.cs.meta
-
41MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector1NodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector1NodeUI.cs.meta
-
51MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector2NodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector2NodeUI.cs.meta
-
51MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector3NodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/Vector3NodeUI.cs.meta
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/TextureNodeUI.cs.meta
-
55MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/SubGraphIONodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/SubGraphIONodeUI.cs.meta
-
39MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/SubGraphNodeUI.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/SubGraphNodeUI.cs.meta
-
87MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeDrawers/TextureNodeUI.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
|
|||
/* if (!string.IsNullOrEmpty(path)) |
|||
ExportShader(m_DataSource.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.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.Linq; |
|||
using RMGUI.GraphView; |
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[Serializable] |
|||
class MaterialGraphDataSource : IDataSource |
|||
{ |
|||
private List<GraphElementData> m_Elements = new List<GraphElementData>(); |
|||
|
|||
public IGraphAsset graphAsset { get; private set; } |
|||
|
|||
public MaterialGraphDataSource(IGraphAsset graphAsset) |
|||
{ |
|||
this.graphAsset = graphAsset; |
|||
|
|||
if (graphAsset == null) |
|||
return; |
|||
|
|||
var drawableNodes = new List<MaterialNodeData>(); |
|||
foreach (var node in graphAsset.graph.GetNodes<INode>()) |
|||
{ |
|||
var nodeData = new MaterialNodeData(node); |
|||
drawableNodes.Add(nodeData); |
|||
} |
|||
|
|||
var drawableEdges = new List<EdgeData>(); |
|||
foreach (var addedNode in drawableNodes) |
|||
{ |
|||
var baseNode = addedNode.node; |
|||
foreach (var slot in baseNode.GetOutputSlots<ISlot>()) |
|||
{ |
|||
var sourceAnchors = addedNode.elements.OfType<MaterialNodeAnchorData>(); |
|||
var sourceAnchor = sourceAnchors.FirstOrDefault(x => x.slot == slot); |
|||
|
|||
var edges = baseNode.owner.GetEdges(new SlotReference(baseNode.guid, slot.id)); |
|||
foreach (var edge in edges) |
|||
{ |
|||
var toNode = baseNode.owner.GetNodeFromGuid(edge.inputSlot.nodeGuid); |
|||
var toSlot = toNode.FindInputSlot<ISlot>(edge.inputSlot.slotId); |
|||
var targetNode = drawableNodes.FirstOrDefault(x => x.node == toNode); |
|||
|
|||
var targetAnchors = targetNode.elements.OfType<MaterialNodeAnchorData>(); |
|||
var targetAnchor = targetAnchors.FirstOrDefault(x => x.slot == toSlot); |
|||
drawableEdges.Add(new EdgeData {Left = sourceAnchor, Right = targetAnchor}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
m_Elements.AddRange(drawableNodes.OfType<GraphElementData>()); |
|||
m_Elements.AddRange(drawableEdges.OfType<GraphElementData>()); |
|||
} |
|||
|
|||
public IEnumerable<GraphElementData> elements |
|||
{ |
|||
get { return m_Elements; } |
|||
} |
|||
|
|||
public void AddElement(GraphElementData element) |
|||
{ |
|||
m_Elements.Add(element); |
|||
} |
|||
|
|||
public void RemoveElement(GraphElementData element) |
|||
{ |
|||
m_Elements.RemoveAll(x => x == element); |
|||
} |
|||
} |
|||
} |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using RMGUI.GraphView; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[Serializable] |
|||
public class MaterialGraphDataSource : IDataSource |
|||
{ |
|||
private List<GraphElementData> m_Elements = new List<GraphElementData>(); |
|||
|
|||
public IGraphAsset graphAsset { get; private set; } |
|||
|
|||
public MaterialGraphDataSource(IGraphAsset graphAsset) |
|||
{ |
|||
this.graphAsset = graphAsset; |
|||
|
|||
if (graphAsset == null) |
|||
return; |
|||
|
|||
var drawableNodes = new List<MaterialNodeData>(); |
|||
foreach (var node in graphAsset.graph.GetNodes<INode>()) |
|||
{ |
|||
var nodeData = ScriptableObject.CreateInstance<MaterialNodeData>(); |
|||
nodeData.Initialize(node); |
|||
drawableNodes.Add(nodeData); |
|||
} |
|||
|
|||
var drawableEdges = new List<EdgeData>(); |
|||
foreach (var addedNode in drawableNodes) |
|||
{ |
|||
var baseNode = addedNode.node; |
|||
foreach (var slot in baseNode.GetOutputSlots<ISlot>()) |
|||
{ |
|||
var sourceAnchors = addedNode.elements.OfType<MaterialNodeAnchorData>(); |
|||
var sourceAnchor = sourceAnchors.FirstOrDefault(x => x.slot == slot); |
|||
|
|||
var edges = baseNode.owner.GetEdges(new SlotReference(baseNode.guid, slot.id)); |
|||
foreach (var edge in edges) |
|||
{ |
|||
var toNode = baseNode.owner.GetNodeFromGuid(edge.inputSlot.nodeGuid); |
|||
var toSlot = toNode.FindInputSlot<ISlot>(edge.inputSlot.slotId); |
|||
var targetNode = drawableNodes.FirstOrDefault(x => x.node == toNode); |
|||
|
|||
var targetAnchors = targetNode.elements.OfType<MaterialNodeAnchorData>(); |
|||
var targetAnchor = targetAnchors.FirstOrDefault(x => x.slot == toSlot); |
|||
drawableEdges.Add(new EdgeData {left = sourceAnchor, right = targetAnchor}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
m_Elements.AddRange(drawableNodes.OfType<GraphElementData>()); |
|||
m_Elements.AddRange(drawableEdges.OfType<GraphElementData>()); |
|||
} |
|||
|
|||
public IEnumerable<GraphElementData> elements |
|||
{ |
|||
get { return m_Elements; } |
|||
} |
|||
|
|||
public void AddElement(GraphElementData element) |
|||
{ |
|||
m_Elements.Add(element); |
|||
} |
|||
|
|||
public void RemoveElement(GraphElementData element) |
|||
{ |
|||
m_Elements.RemoveAll(x => x == element); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using RMGUI.GraphView.Demo; |
|||
using UnityEngine; |
|||
using UnityEditor.MaterialGraph; |
|||
using UnityEngine.MaterialGraph; |
|||
[Serializable] |
|||
public class MaterialNodeAnchorData : NodeAnchorData |
|||
{ |
|||
public ISlot slot { get; private set; } |
|||
public MaterialNodeAnchorData(ISlot slot) |
|||
{ |
|||
this.slot = slot; |
|||
name = slot.displayName; |
|||
type = typeof(Vector4); |
|||
direction = slot.isInputSlot ? Direction.Input : Direction.Output; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public class MaterialNodeData : GraphElementData |
|||
{ |
|||
[Serializable] |
|||
public class MaterialNodeData : GraphElementData |
|||
{ |
|||
protected List<NodeAnchorData> m_Anchors = new List<NodeAnchorData>(); |
|||
protected List<GraphElementData> m_Children = new List<GraphElementData>(); |
|||
get { return m_Anchors.OfType<GraphElementData>(); } |
|||
get { return m_Children; } |
|||
public MaterialNodeData(INode inNode) |
|||
protected MaterialNodeData() |
|||
{} |
|||
|
|||
public void Initialize(INode inNode) |
|||
capabilities |= Capabilities.Movable; |
|||
name = inNode.name; |
|||
name = inNode.name; |
|||
m_Anchors.Add(new MaterialNodeAnchorData(input)); |
|||
var data = CreateInstance<MaterialNodeAnchorData>(); |
|||
data.Initialize(input); |
|||
m_Children.Add(data); |
|||
|
|||
position = new Rect(node.drawState.position.x, node.drawState.position.y, 100, 200); |
|||
capabilities |= Capabilities.Movable; |
|||
|
|||
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 UnityEngine.RMGUI; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
public class DataContainer : VisualContainer |
|||
{ |
|||
IDataSource m_DataProvider; |
|||
|
|||
public IDataSource dataProvider |
|||
{ |
|||
get { return m_DataProvider; } |
|||
set |
|||
{ |
|||
if (m_DataProvider == value) |
|||
return; |
|||
RemoveWatch(); |
|||
m_DataProvider = value; |
|||
OnDataChanged(); |
|||
AddWatch(); |
|||
} |
|||
} |
|||
|
|||
public T GetData<T>() where T : GraphElementData |
|||
{ |
|||
return dataProvider as T; |
|||
} |
|||
|
|||
void AddWatch() |
|||
{ |
|||
if (m_DataProvider != null && panel != null && m_DataProvider is Object) |
|||
// TODO: consider a disposable handle?
|
|||
DataWatchService.AddDataSpy(this, (Object) m_DataProvider, OnDataChanged); |
|||
} |
|||
|
|||
void RemoveWatch() |
|||
{ |
|||
if (m_DataProvider != null && panel != null && m_DataProvider is Object) |
|||
DataWatchService.RemoveDataSpy((Object) m_DataProvider, OnDataChanged); |
|||
} |
|||
|
|||
public DataContainer() |
|||
{ |
|||
// trigger data source reset when entering leaving panel
|
|||
onEnter += AddWatch; |
|||
onLeave += RemoveWatch; |
|||
} |
|||
|
|||
// called when Serialized object has changed
|
|||
// only works while widget is in a panel
|
|||
public virtual void OnDataChanged() |
|||
{} |
|||
} |
|||
} |
|||
using UnityEngine.RMGUI; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
public class DataContainer : VisualContainer |
|||
{ |
|||
IDataSource m_DataProvider; |
|||
|
|||
public IDataSource dataProvider |
|||
{ |
|||
get { return m_DataProvider; } |
|||
set |
|||
{ |
|||
if (m_DataProvider == value) |
|||
return; |
|||
RemoveWatch(); |
|||
m_DataProvider = value; |
|||
OnDataChanged(); |
|||
AddWatch(); |
|||
} |
|||
} |
|||
|
|||
public T GetData<T>() where T : GraphElementData |
|||
{ |
|||
return dataProvider as T; |
|||
} |
|||
|
|||
void AddWatch() |
|||
{ |
|||
if (m_DataProvider != null && panel != null && m_DataProvider is Object) |
|||
// TODO: consider a disposable handle?
|
|||
DataWatchService.AddDataSpy(this, (Object) m_DataProvider, OnDataChanged); |
|||
} |
|||
|
|||
void RemoveWatch() |
|||
{ |
|||
if (m_DataProvider != null && panel != null && m_DataProvider is Object) |
|||
DataWatchService.RemoveDataSpy((Object) m_DataProvider, OnDataChanged); |
|||
} |
|||
|
|||
public DataContainer() |
|||
{ |
|||
// trigger data source reset when entering leaving panel
|
|||
onEnter += AddWatch; |
|||
onLeave += RemoveWatch; |
|||
} |
|||
|
|||
// called when Serialized object has changed
|
|||
// only works while widget is in a panel
|
|||
public virtual void OnDataChanged() |
|||
{} |
|||
} |
|||
} |
|
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
|
|||
namespace RMGUI.GraphView.Demo |
|||
{ |
|||
public class IMGUISampleElementData : IMGUIData |
|||
{ |
|||
private int m_ControlInteger; |
|||
private bool m_GUIToggle; |
|||
private float m_GUIFloatValue = 42.0f; |
|||
private string m_SomeText = "<enter some text>"; |
|||
|
|||
public override void OnGUIHandler() |
|||
{ |
|||
EventType t = Event.current.type; |
|||
Color backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.7f); |
|||
|
|||
Color selectedColor = new Color(1.0f, 0.7f, 0.0f, 0.7f); |
|||
EditorGUI.DrawRect(new Rect(0, 0, position.width, position.height), selected ? selectedColor : backgroundColor); |
|||
|
|||
GUILayout.BeginVertical(); |
|||
GUILayout.Label("Layout begins here"); |
|||
GUILayout.Label("X = " + position.x + " Y = " + position.y + " W = " + position.width + " H = " + position.height); |
|||
if (GUILayout.Button("Layout Buttton" + m_ControlInteger, GUILayout.Width(150))) |
|||
{ |
|||
m_ControlInteger++; |
|||
Debug.Log("Layout Button was pressed: " + m_ControlInteger); |
|||
} |
|||
|
|||
m_GUIToggle = GUILayout.Toggle(m_GUIToggle, "GUI Toggle"); |
|||
|
|||
m_GUIFloatValue = GUILayout.HorizontalSlider(m_GUIFloatValue, 0.0f, 100.0f, GUILayout.Width(150)); |
|||
|
|||
m_SomeText = GUILayout.TextField(m_SomeText, GUILayout.Width(200)); |
|||
GUILayout.Label("Layout ends here"); |
|||
GUILayout.EndVertical(); |
|||
|
|||
float y = 150.0f; |
|||
GUI.Label(new Rect(0, y, 150, 30), "No-layout begins here"); |
|||
|
|||
if (GUI.Button(new Rect(0, y + 30.0f, 120, 30), "GUI Button:" + m_ControlInteger)) |
|||
{ |
|||
m_ControlInteger++; |
|||
Debug.Log("GUI Button was pressed: " + m_ControlInteger); |
|||
} |
|||
|
|||
m_GUIToggle = GUI.Toggle(new Rect(120, y + 30.0f, 120, 30), m_GUIToggle, "GUI Toggle"); |
|||
|
|||
m_GUIFloatValue = GUI.HorizontalSlider(new Rect(0, y + 60.0f, 120, 30), m_GUIFloatValue, 0.0f, 100.0f); |
|||
|
|||
GUI.Label(new Rect(0, y + 90.0f, 120, 30), "No-layout ends here"); |
|||
} |
|||
} |
|||
|
|||
public class IMGUISampleViewData : GraphViewDataSource |
|||
{ |
|||
protected new void OnEnable() |
|||
{ |
|||
var imguiSample = CreateInstance<IMGUISampleElementData>(); |
|||
imguiSample.position = new Rect(100, 200, 230, 300); |
|||
imguiSample.title = "IMGUIControls: modal"; |
|||
imguiSample.capabilities |= Capabilities.Resizable; |
|||
AddElement(imguiSample); |
|||
} |
|||
} |
|||
} |
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
|
|||
namespace RMGUI.GraphView.Demo |
|||
{ |
|||
public class IMGUISampleElementData : IMGUIData |
|||
{ |
|||
private int m_ControlInteger; |
|||
private bool m_GUIToggle; |
|||
private float m_GUIFloatValue = 42.0f; |
|||
private string m_SomeText = "<enter some text>"; |
|||
|
|||
public override void OnGUIHandler() |
|||
{ |
|||
Color backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.7f); |
|||
|
|||
Color selectedColor = new Color(1.0f, 0.7f, 0.0f, 0.7f); |
|||
EditorGUI.DrawRect(new Rect(0, 0, position.width, position.height), selected ? selectedColor : backgroundColor); |
|||
|
|||
GUILayout.BeginVertical(); |
|||
GUILayout.Label("Layout begins here"); |
|||
GUILayout.Label("X = " + position.x + " Y = " + position.y + " W = " + position.width + " H = " + position.height); |
|||
if (GUILayout.Button("Layout Buttton" + m_ControlInteger, GUILayout.Width(150))) |
|||
{ |
|||
m_ControlInteger++; |
|||
Debug.Log("Layout Button was pressed: " + m_ControlInteger); |
|||
} |
|||
|
|||
m_GUIToggle = GUILayout.Toggle(m_GUIToggle, "GUI Toggle"); |
|||
|
|||
m_GUIFloatValue = GUILayout.HorizontalSlider(m_GUIFloatValue, 0.0f, 100.0f, GUILayout.Width(150)); |
|||
|
|||
m_SomeText = GUILayout.TextField(m_SomeText, GUILayout.Width(200)); |
|||
GUILayout.Label("Layout ends here"); |
|||
GUILayout.EndVertical(); |
|||
|
|||
float y = 150.0f; |
|||
GUI.Label(new Rect(0, y, 150, 30), "No-layout begins here"); |
|||
|
|||
if (GUI.Button(new Rect(0, y + 30.0f, 120, 30), "GUI Button:" + m_ControlInteger)) |
|||
{ |
|||
m_ControlInteger++; |
|||
Debug.Log("GUI Button was pressed: " + m_ControlInteger); |
|||
} |
|||
|
|||
m_GUIToggle = GUI.Toggle(new Rect(120, y + 30.0f, 120, 30), m_GUIToggle, "GUI Toggle"); |
|||
|
|||
m_GUIFloatValue = GUI.HorizontalSlider(new Rect(0, y + 60.0f, 120, 30), m_GUIFloatValue, 0.0f, 100.0f); |
|||
|
|||
GUI.Label(new Rect(0, y + 90.0f, 120, 30), "No-layout ends here"); |
|||
} |
|||
} |
|||
|
|||
public class IMGUISampleViewData : GraphViewDataSource |
|||
{ |
|||
protected void OnEnable() |
|||
{ |
|||
var imguiSample = CreateInstance<IMGUISampleElementData>(); |
|||
imguiSample.position = new Rect(100, 200, 230, 300); |
|||
imguiSample.title = "IMGUIControls: modal"; |
|||
imguiSample.capabilities |= Capabilities.Resizable; |
|||
AddElement(imguiSample); |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
using UnityEngine.RMGUI; |
|||
|
|||
namespace RMGUI.GraphView.Demo |
|||
{ |
|||
[StyleSheet("Assets/Editor/Demo/NodalView.uss")] |
|||
class NodesContentView : SimpleContentView |
|||
{ |
|||
System.Random rnd = new System.Random(); |
|||
|
|||
public NodesContentView() |
|||
{ |
|||
// Shortcut handler to delete elements
|
|||
var dictionary = new Dictionary<Event, ShortcutDelegate>(); |
|||
dictionary[Event.KeyboardEvent("delete")] = DeleteSelection; |
|||
contentViewContainer.AddManipulator(new ShortcutHandler(dictionary)); |
|||
|
|||
// Contextual menu to create new nodes
|
|||
contentViewContainer.AddManipulator(new ContextualMenu((evt, customData) => |
|||
{ |
|||
var menu = new GenericMenu(); |
|||
menu.AddItem(new GUIContent("Create Operator"), false, |
|||
contentView => CreateOperator(), |
|||
this); |
|||
menu.ShowAsContext(); |
|||
return EventPropagation.Continue; |
|||
})); |
|||
} |
|||
|
|||
public void CreateOperator() |
|||
{ |
|||
NodalViewData nodalViewData = dataProvider as NodalViewData; |
|||
if (nodalViewData != null) |
|||
{ |
|||
var x = rnd.Next(0, 600); |
|||
var y = rnd.Next(0, 300); |
|||
|
|||
nodalViewData.CreateOperator(typeof(Vector3), new Rect(x, y, 200, 176), "Shiny New Operator"); |
|||
} |
|||
} |
|||
|
|||
// TODO: this has data model knowledge, move this to GraphData
|
|||
private EventPropagation DeleteSelection() |
|||
{ |
|||
// and DeleteSelection would call that method.
|
|||
var nodalViewData = dataProvider as NodalViewData; |
|||
if (nodalViewData == null) |
|||
return EventPropagation.Stop; |
|||
|
|||
// TODO We will want to move this up to GraphView
|
|||
var elementsToRemove = new List<GraphElementData>(); |
|||
foreach (var selectedElement in selection.Cast<GraphElement>() |
|||
.Where(e => e != null && e.dataProvider != null)) |
|||
{ |
|||
var nodeData = selectedElement.dataProvider as NodeData; |
|||
if (nodeData != null) |
|||
{ |
|||
// If there are connected edges, disconnect first (if such functionality is available) and delete
|
|||
foreach (var element in allElements.OfType<GraphElement>()) |
|||
{ |
|||
var edge = element as Edge; |
|||
if (edge == null) continue; |
|||
|
|||
var edgeData = edge.dataProvider as EdgeData; |
|||
if (edgeData == null) continue; |
|||
|
|||
// Try output anchor first
|
|||
if ((edgeData.Left != null && edgeData.Left == (IConnectable)nodeData.outputAnchor) || |
|||
(edgeData.Right != null && edgeData.Right == (IConnectable)nodeData.outputAnchor)) |
|||
{ |
|||
elementsToRemove.Add(edgeData); |
|||
continue; |
|||
} |
|||
|
|||
// Check each input anchor
|
|||
if (nodeData.anchors.Any(a => (edgeData.Left != null && edgeData.Left == (IConnectable)a) || |
|||
(edgeData.Right != null && edgeData.Right == (IConnectable)a))) |
|||
{ |
|||
elementsToRemove.Add(edgeData); |
|||
} |
|||
} |
|||
} |
|||
|
|||
elementsToRemove.Add(selectedElement.GetData<GraphElementData>()); |
|||
} |
|||
|
|||
// Notify node anchors of deconnection
|
|||
foreach (var edgeData in elementsToRemove.OfType<EdgeData>()) |
|||
{ |
|||
if (edgeData.Left != null) |
|||
{ |
|||
edgeData.Left.connected = false; |
|||
} |
|||
|
|||
if (edgeData.Right != null) |
|||
{ |
|||
edgeData.Right.connected = false; |
|||
} |
|||
} |
|||
|
|||
foreach (var b in elementsToRemove.OfType<GraphElementData>()) |
|||
nodalViewData.RemoveElement(b); |
|||
|
|||
return EventPropagation.Stop; |
|||
} |
|||
} |
|||
|
|||
class NodalView : EditorWindow |
|||
{ |
|||
[MenuItem("Window/GraphView Demo/Nodal UI")] |
|||
public static void ShowWindow() |
|||
{ |
|||
GetWindow<NodalView>(); |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
var zeView = new NodesContentView |
|||
{ |
|||
name = "theView", |
|||
dataProvider = CreateInstance<NodalViewData>() |
|||
}; |
|||
zeView.StretchToParentSize(); |
|||
|
|||
windowRoot.AddChild(zeView); |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
windowRoot.ClearChildren(); |
|||
} |
|||
} |
|||
} |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
using UnityEngine.RMGUI; |
|||
|
|||
namespace RMGUI.GraphView.Demo |
|||
{ |
|||
[StyleSheet("Assets/Editor/Demo/Views/NodalView.uss")] |
|||
class NodesContentView : SimpleContentView |
|||
{ |
|||
System.Random rnd = new System.Random(); |
|||
|
|||
public NodesContentView() |
|||
{ |
|||
// Shortcut handler to delete elements
|
|||
var dictionary = new Dictionary<Event, ShortcutDelegate>(); |
|||
dictionary[Event.KeyboardEvent("delete")] = DeleteSelection; |
|||
contentViewContainer.AddManipulator(new ShortcutHandler(dictionary)); |
|||
|
|||
// Contextual menu to create new nodes
|
|||
contentViewContainer.AddManipulator(new ContextualMenu((evt, customData) => |
|||
{ |
|||
var menu = new GenericMenu(); |
|||
menu.AddItem(new GUIContent("Create Operator"), false, |
|||
contentView => CreateOperator(), |
|||
this); |
|||
menu.ShowAsContext(); |
|||
return EventPropagation.Continue; |
|||
})); |
|||
} |
|||
|
|||
public void CreateOperator() |
|||
{ |
|||
NodalViewData nodalViewData = dataProvider as NodalViewData; |
|||
if (nodalViewData != null) |
|||
{ |
|||
var x = rnd.Next(0, 600); |
|||
var y = rnd.Next(0, 300); |
|||
|
|||
nodalViewData.CreateOperator(typeof(Vector3), new Rect(x, y, 200, 176), "Shiny New Operator"); |
|||
} |
|||
} |
|||
|
|||
// TODO: this has data model knowledge, move this to GraphData
|
|||
private EventPropagation DeleteSelection() |
|||
{ |
|||
// and DeleteSelection would call that method.
|
|||
var nodalViewData = dataProvider as NodalViewData; |
|||
if (nodalViewData == null) |
|||
return EventPropagation.Stop; |
|||
|
|||
// TODO We will want to move this up to GraphView
|
|||
var elementsToRemove = new List<GraphElementData>(); |
|||
foreach (var selectedElement in selection.Cast<GraphElement>() |
|||
.Where(e => e != null && e.dataProvider != null)) |
|||
{ |
|||
var nodeData = selectedElement.dataProvider as NodeData; |
|||
if (nodeData != null) |
|||
{ |
|||
// If there are connected edges, disconnect first (if such functionality is available) and delete
|
|||
foreach (var element in allElements.OfType<GraphElement>()) |
|||
{ |
|||
var edge = element as Edge; |
|||
if (edge == null) continue; |
|||
|
|||
var edgeData = edge.dataProvider as EdgeData; |
|||
if (edgeData == null) continue; |
|||
|
|||
// Try output anchor first
|
|||
if ((edgeData.left != null && edgeData.left == (IConnectable)nodeData.outputAnchor) || |
|||
(edgeData.right != null && edgeData.right == (IConnectable)nodeData.outputAnchor)) |
|||
{ |
|||
elementsToRemove.Add(edgeData); |
|||
continue; |
|||
} |
|||
|
|||
// Check each input anchor
|
|||
if (nodeData.anchors.Any(a => (edgeData.left != null && edgeData.left == (IConnectable)a) || |
|||
(edgeData.right != null && edgeData.right == (IConnectable)a))) |
|||
{ |
|||
elementsToRemove.Add(edgeData); |
|||
} |
|||
} |
|||
} |
|||
|
|||
elementsToRemove.Add(selectedElement.GetData<GraphElementData>()); |
|||
} |
|||
|
|||
// Notify node anchors of deconnection
|
|||
foreach (var edgeData in elementsToRemove.OfType<EdgeData>()) |
|||
{ |
|||
if (edgeData.left != null) |
|||
{ |
|||
edgeData.left.connected = false; |
|||
} |
|||
|
|||
if (edgeData.right != null) |
|||
{ |
|||
edgeData.right.connected = false; |
|||
} |
|||
} |
|||
|
|||
foreach (var b in elementsToRemove) |
|||
nodalViewData.RemoveElement(b); |
|||
|
|||
return EventPropagation.Stop; |
|||
} |
|||
} |
|||
|
|||
class NodalView : EditorWindow |
|||
{ |
|||
[MenuItem("Window/GraphView Demo/Nodal UI")] |
|||
public static void ShowWindow() |
|||
{ |
|||
GetWindow<NodalView>(); |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
var view = new NodesContentView |
|||
{ |
|||
name = "theView", |
|||
dataProvider = CreateInstance<NodalViewData>() |
|||
}; |
|||
view.StretchToParentSize(); |
|||
|
|||
windowRoot.AddChild(view); |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
windowRoot.ClearChildren(); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
[Serializable] |
|||
public abstract class GraphElementData : ScriptableObject, IDataSource |
|||
{ |
|||
[SerializeField] |
|||
private bool m_Selected; |
|||
|
|||
[SerializeField] |
|||
private Rect m_Position; |
|||
|
|||
[SerializeField] |
|||
private Capabilities m_Capabilities; |
|||
|
|||
public Rect position |
|||
{ |
|||
get { return m_Position; } |
|||
set { m_Position = value; } |
|||
} |
|||
|
|||
public bool selected |
|||
{ |
|||
get { return m_Selected; } |
|||
set |
|||
{ |
|||
// Set new value (toggle old value)
|
|||
if ((capabilities & Capabilities.Selectable) == Capabilities.Selectable) |
|||
{ |
|||
m_Selected = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected void OnEnable() |
|||
{ |
|||
capabilities = Capabilities.Normal | Capabilities.Movable | Capabilities.Selectable; |
|||
} |
|||
|
|||
public virtual IEnumerable<GraphElementData> elements |
|||
{ |
|||
get { return new GraphElementData[0]; } |
|||
} |
|||
|
|||
public virtual void AddElement(GraphElementData element) |
|||
{} |
|||
|
|||
public virtual void RemoveElement(GraphElementData element) |
|||
{} |
|||
|
|||
public Capabilities capabilities |
|||
{ |
|||
get { return m_Capabilities; } |
|||
set { m_Capabilities = value; } |
|||
} |
|||
} |
|||
} |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
[Serializable] |
|||
public abstract class GraphElementData : ScriptableObject, IDataSource |
|||
{ |
|||
[SerializeField] |
|||
private bool m_Selected; |
|||
|
|||
[SerializeField] |
|||
private Rect m_Position; |
|||
|
|||
[SerializeField] |
|||
private Capabilities m_Capabilities; |
|||
|
|||
public Rect position |
|||
{ |
|||
get { return m_Position; } |
|||
set { m_Position = value; } |
|||
} |
|||
|
|||
public bool selected |
|||
{ |
|||
get { return m_Selected; } |
|||
set |
|||
{ |
|||
// Set new value (toggle old value)
|
|||
if ((capabilities & Capabilities.Selectable) == Capabilities.Selectable) |
|||
{ |
|||
m_Selected = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected void OnEnable() |
|||
{ |
|||
capabilities = Capabilities.Normal | Capabilities.Movable | Capabilities.Selectable; |
|||
} |
|||
|
|||
public virtual IEnumerable<GraphElementData> elements |
|||
{ |
|||
get { return new GraphElementData[0]; } |
|||
} |
|||
|
|||
public virtual void AddElement(GraphElementData element) |
|||
{} |
|||
|
|||
public virtual void RemoveElement(GraphElementData element) |
|||
{} |
|||
|
|||
public Capabilities capabilities |
|||
{ |
|||
get { return m_Capabilities; } |
|||
set { m_Capabilities = value; } |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using UnityEngine; |
|||
using UnityEngine.RMGUI; |
|||
using UnityEngine.RMGUI.StyleEnums.Values; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
public class Resizer : Manipulator, IDecorator |
|||
{ |
|||
public MouseButton activateButton { get; set; } |
|||
|
|||
// When applyInvTransform is true, Resizer will apply target's inverse transform before drawing/picking
|
|||
// (has the effect of being zoom factor independent)
|
|||
public bool applyInvTransform { get; set; } |
|||
|
|||
private Vector2 m_Start; |
|||
private Rect m_StartPos; |
|||
|
|||
private string m_SizeStr; |
|||
private Vector2 m_MinimumSize; |
|||
|
|||
// We need to delay style creation because we need to make sure we have a GUISkin loaded.
|
|||
private GUIStyle m_StyleWidget; |
|||
private GUIStyle m_StyleLabel; |
|||
|
|||
private readonly Rect k_WidgetRect = new Rect(0, 0, 10, 6); |
|||
private readonly Rect k_WidgetPickRect = new Rect(0, 0, 20, 20); |
|||
private readonly Rect k_WidgetTextOffset = new Rect(0, 0, 5, 5); |
|||
|
|||
public Resizer() |
|||
{ |
|||
m_MinimumSize = new Vector2(30.0f, 30.0f); |
|||
m_SizeStr = ""; |
|||
activateButton = MouseButton.LeftMouse; |
|||
} |
|||
|
|||
public Resizer(Vector2 minimumSize) |
|||
{ |
|||
m_MinimumSize = minimumSize; |
|||
m_SizeStr = ""; |
|||
} |
|||
|
|||
public override EventPropagation HandleEvent(Event evt, VisualElement finalTarget) |
|||
{ |
|||
GraphElement ce = target as GraphElement; |
|||
if (ce==null) |
|||
return EventPropagation.Continue; |
|||
|
|||
var data = ce.GetData<GraphElementData>(); |
|||
if (data==null) |
|||
return EventPropagation.Continue; |
|||
|
|||
if ( (data.capabilities & Capabilities.Resizable) != Capabilities.Resizable) |
|||
return EventPropagation.Continue; |
|||
|
|||
switch (evt.type) |
|||
{ |
|||
case EventType.MouseDown: |
|||
if (evt.button == (int) activateButton) |
|||
{ |
|||
m_Start = evt.mousePosition; |
|||
m_StartPos = target.position; |
|||
|
|||
var adjustedWidget = k_WidgetPickRect; |
|||
if (applyInvTransform) |
|||
{ |
|||
var inv = target.globalTransform.inverse; |
|||
adjustedWidget.width *= inv.m00; // Apply scale
|
|||
adjustedWidget.height *= inv.m11; |
|||
} |
|||
|
|||
var widget = m_StartPos; |
|||
|
|||
widget.x = widget.width - adjustedWidget.width; |
|||
widget.y = widget.height - adjustedWidget.height; |
|||
widget.width = adjustedWidget.width; |
|||
widget.height = adjustedWidget.height; |
|||
|
|||
if (widget.Contains(m_Start)) |
|||
{ |
|||
// Warn user if target uses a relative CSS position type
|
|||
if (target.positionType != PositionType.Absolute) |
|||
{ |
|||
Debug.LogWarning("Attempting to resize an object with a non absolute CSS position type"); |
|||
} |
|||
this.TakeCapture(); |
|||
return EventPropagation.Stop; |
|||
} |
|||
} |
|||
break; |
|||
|
|||
case EventType.MouseDrag: |
|||
if (this.HasCapture() && target.positionType == PositionType.Absolute) |
|||
{ |
|||
var diff = evt.mousePosition - m_Start; |
|||
var newSize = new Vector2(m_StartPos.width + diff.x, m_StartPos.height + diff.y); |
|||
|
|||
if (newSize.x < m_MinimumSize.x) |
|||
newSize.x = m_MinimumSize.x; |
|||
if (newSize.y < m_MinimumSize.y) |
|||
newSize.y = m_MinimumSize.y; |
|||
|
|||
data.position = new Rect(data.position.x, data.position.y, newSize.x, newSize.y); |
|||
|
|||
m_SizeStr = String.Format("{0:0}", target.position.width) + "x" + String.Format("{0:0}", target.position.height); |
|||
|
|||
return EventPropagation.Stop; |
|||
} |
|||
return EventPropagation.Continue; |
|||
|
|||
case EventType.MouseUp: |
|||
if (this.HasCapture() && evt.button == (int)activateButton) |
|||
{ |
|||
this.ReleaseCapture(); |
|||
return EventPropagation.Stop; |
|||
} |
|||
break; |
|||
} |
|||
return EventPropagation.Continue; |
|||
} |
|||
|
|||
public void PrePaint(VisualElement t, PaintContext pc) |
|||
{ |
|||
} |
|||
|
|||
public void PostPaint(VisualElement t, PaintContext pc) |
|||
{ |
|||
// TODO: I would like to listen for skin change and create GUIStyle then and only then
|
|||
if (m_StyleWidget == null) |
|||
{ |
|||
m_StyleWidget = new GUIStyle("WindowBottomResize") { fixedHeight = 0 }; |
|||
} |
|||
|
|||
if (m_StyleLabel == null) |
|||
{ |
|||
m_StyleLabel = new GUIStyle("Label"); |
|||
} |
|||
|
|||
// Draw resize widget
|
|||
var widget = k_WidgetRect; |
|||
if (applyInvTransform) |
|||
{ |
|||
var inv = pc.worldXForm.inverse; |
|||
widget.width *= inv.m00; |
|||
widget.height *= inv.m11; |
|||
} |
|||
|
|||
widget.position = new Vector2(target.position.max.x - widget.width, target.position.max.y - widget.height); |
|||
|
|||
// todo painter as drawimage
|
|||
m_StyleWidget.Draw(widget, GUIContent.none, 0); |
|||
|
|||
if (this.HasCapture()) |
|||
{ |
|||
// Get adjusted text offset
|
|||
var adjustedWidget = k_WidgetTextOffset; |
|||
if (applyInvTransform) |
|||
{ |
|||
var inv = pc.worldXForm.inverse; |
|||
adjustedWidget.width *= inv.m00; // Apply scale
|
|||
adjustedWidget.height *= inv.m11; |
|||
} |
|||
|
|||
// Now define widget to locate label
|
|||
widget = new Rect(target.position.max.x + adjustedWidget.width, |
|||
target.position.max.y + adjustedWidget.height, |
|||
200.0f, 20.0f); |
|||
m_StyleLabel.Draw(widget, new GUIContent(m_SizeStr), false, false, false, false); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
using System; |
|||
using UnityEngine; |
|||
using UnityEngine.RMGUI; |
|||
using UnityEngine.RMGUI.StyleEnums.Values; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
public class Resizer : Manipulator, IDecorator |
|||
{ |
|||
public MouseButton activateButton { get; set; } |
|||
|
|||
// When applyInvTransform is true, Resizer will apply target's inverse transform before drawing/picking
|
|||
// (has the effect of being zoom factor independent)
|
|||
public bool applyInvTransform { get; set; } |
|||
|
|||
private Vector2 m_Start; |
|||
private Rect m_StartPos; |
|||
|
|||
private string m_SizeStr; |
|||
private Vector2 m_MinimumSize; |
|||
|
|||
// We need to delay style creation because we need to make sure we have a GUISkin loaded.
|
|||
private GUIStyle m_StyleWidget; |
|||
private GUIStyle m_StyleLabel; |
|||
|
|||
private readonly Rect k_WidgetRect = new Rect(0, 0, 10, 6); |
|||
private readonly Rect k_WidgetPickRect = new Rect(0, 0, 20, 20); |
|||
private readonly Rect k_WidgetTextOffset = new Rect(0, 0, 5, 5); |
|||
|
|||
public Resizer() |
|||
{ |
|||
m_MinimumSize = new Vector2(30.0f, 30.0f); |
|||
m_SizeStr = ""; |
|||
activateButton = MouseButton.LeftMouse; |
|||
} |
|||
|
|||
public Resizer(Vector2 minimumSize) |
|||
{ |
|||
m_MinimumSize = minimumSize; |
|||
m_SizeStr = ""; |
|||
} |
|||
|
|||
public override EventPropagation HandleEvent(Event evt, VisualElement finalTarget) |
|||
{ |
|||
GraphElement ce = target as GraphElement; |
|||
if (ce==null) |
|||
return EventPropagation.Continue; |
|||
|
|||
var data = ce.GetData<GraphElementData>(); |
|||
if (data==null) |
|||
return EventPropagation.Continue; |
|||
|
|||
if ( (data.capabilities & Capabilities.Resizable) != Capabilities.Resizable) |
|||
return EventPropagation.Continue; |
|||
|
|||
switch (evt.type) |
|||
{ |
|||
case EventType.MouseDown: |
|||
if (evt.button == (int) activateButton) |
|||
{ |
|||
m_Start = evt.mousePosition; |
|||
m_StartPos = target.position; |
|||
|
|||
var adjustedWidget = k_WidgetPickRect; |
|||
if (applyInvTransform) |
|||
{ |
|||
var inv = target.globalTransform.inverse; |
|||
adjustedWidget.width *= inv.m00; // Apply scale
|
|||
adjustedWidget.height *= inv.m11; |
|||
} |
|||
|
|||
var widget = m_StartPos; |
|||
|
|||
widget.x = widget.width - adjustedWidget.width; |
|||
widget.y = widget.height - adjustedWidget.height; |
|||
widget.width = adjustedWidget.width; |
|||
widget.height = adjustedWidget.height; |
|||
|
|||
if (widget.Contains(m_Start)) |
|||
{ |
|||
// Warn user if target uses a relative CSS position type
|
|||
if (target.positionType != PositionType.Absolute) |
|||
{ |
|||
Debug.LogWarning("Attempting to resize an object with a non absolute CSS position type"); |
|||
} |
|||
this.TakeCapture(); |
|||
return EventPropagation.Stop; |
|||
} |
|||
} |
|||
break; |
|||
|
|||
case EventType.MouseDrag: |
|||
if (this.HasCapture() && target.positionType == PositionType.Absolute) |
|||
{ |
|||
var diff = evt.mousePosition - m_Start; |
|||
var newSize = new Vector2(m_StartPos.width + diff.x, m_StartPos.height + diff.y); |
|||
|
|||
if (newSize.x < m_MinimumSize.x) |
|||
newSize.x = m_MinimumSize.x; |
|||
if (newSize.y < m_MinimumSize.y) |
|||
newSize.y = m_MinimumSize.y; |
|||
|
|||
data.position = new Rect(data.position.x, data.position.y, newSize.x, newSize.y); |
|||
|
|||
m_SizeStr = String.Format("{0:0}", target.position.width) + "x" + String.Format("{0:0}", target.position.height); |
|||
|
|||
return EventPropagation.Stop; |
|||
} |
|||
return EventPropagation.Continue; |
|||
|
|||
case EventType.MouseUp: |
|||
if (this.HasCapture() && evt.button == (int)activateButton) |
|||
{ |
|||
this.ReleaseCapture(); |
|||
return EventPropagation.Stop; |
|||
} |
|||
break; |
|||
} |
|||
return EventPropagation.Continue; |
|||
} |
|||
|
|||
public void PrePaint(VisualElement t, PaintContext pc) |
|||
{ |
|||
} |
|||
|
|||
public void PostPaint(VisualElement t, PaintContext pc) |
|||
{ |
|||
// TODO: I would like to listen for skin change and create GUIStyle then and only then
|
|||
if (m_StyleWidget == null) |
|||
{ |
|||
m_StyleWidget = new GUIStyle("WindowBottomResize") { fixedHeight = 0 }; |
|||
} |
|||
|
|||
if (m_StyleLabel == null) |
|||
{ |
|||
m_StyleLabel = new GUIStyle("Label"); |
|||
} |
|||
|
|||
// Draw resize widget
|
|||
var widget = k_WidgetRect; |
|||
if (applyInvTransform) |
|||
{ |
|||
var inv = pc.worldXForm.inverse; |
|||
widget.width *= inv.m00; |
|||
widget.height *= inv.m11; |
|||
} |
|||
|
|||
widget.position = new Vector2(target.position.max.x - widget.width, target.position.max.y - widget.height); |
|||
|
|||
// todo painter as drawimage
|
|||
m_StyleWidget.Draw(widget, GUIContent.none, 0); |
|||
|
|||
if (this.HasCapture()) |
|||
{ |
|||
// Get adjusted text offset
|
|||
var adjustedWidget = k_WidgetTextOffset; |
|||
if (applyInvTransform) |
|||
{ |
|||
var inv = pc.worldXForm.inverse; |
|||
adjustedWidget.width *= inv.m00; // Apply scale
|
|||
adjustedWidget.height *= inv.m11; |
|||
} |
|||
|
|||
// Now define widget to locate label
|
|||
widget = new Rect(target.position.max.x + adjustedWidget.width, |
|||
target.position.max.y + adjustedWidget.height, |
|||
200.0f, 20.0f); |
|||
m_StyleLabel.Draw(widget, new GUIContent(m_SizeStr), false, false, false, false); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
public interface IDataSource |
|||
{ |
|||
IEnumerable<GraphElementData> elements { get; } |
|||
void AddElement(GraphElementData element); |
|||
void RemoveElement(GraphElementData element); |
|||
} |
|||
|
|||
[Serializable] |
|||
public abstract class GraphViewDataSource : ScriptableObject, IDataSource |
|||
{ |
|||
[SerializeField] |
|||
private List<GraphElementData> m_Elements = new List<GraphElementData>(); |
|||
|
|||
public IEnumerable<GraphElementData> elements |
|||
{ |
|||
get { return m_Elements.OfType<GraphElementData>(); } |
|||
} |
|||
|
|||
public void AddElement(GraphElementData element) |
|||
{ |
|||
m_Elements.Add(element); |
|||
} |
|||
|
|||
public void RemoveElement(GraphElementData element) |
|||
{ |
|||
m_Elements.RemoveAll(x => x == element); |
|||
} |
|||
} |
|||
} |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
[Serializable] |
|||
public abstract class GraphViewDataSource : ScriptableObject, IDataSource |
|||
{ |
|||
[SerializeField] |
|||
private List<GraphElementData> m_Elements = new List<GraphElementData>(); |
|||
|
|||
public IEnumerable<GraphElementData> elements |
|||
{ |
|||
get { return m_Elements; } |
|||
} |
|||
|
|||
public void AddElement(GraphElementData element) |
|||
{ |
|||
m_Elements.Add(element); |
|||
} |
|||
|
|||
public void RemoveElement(GraphElementData element) |
|||
{ |
|||
m_Elements.RemoveAll(x => x == element); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Reflection; |
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(AbstractMaterialNode))] |
|||
public class AbstractMaterialNodeUI : ICustomNodeUi |
|||
{ |
|||
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; |
|||
} |
|||
} |
|||
|
|||
private float m_PreviewWidth; |
|||
public virtual float GetNodeUiHeight(float width) |
|||
{ |
|||
if (!m_Node.drawState.expanded) |
|||
return 0; |
|||
|
|||
if (m_Node.hasPreview == false) |
|||
return 0; |
|||
|
|||
m_PreviewWidth = width - 20; |
|||
return m_PreviewWidth; |
|||
} |
|||
|
|||
public INode node |
|||
{ |
|||
get { return m_Node; } |
|||
set |
|||
{ |
|||
var materialNode = value as AbstractMaterialNode; |
|||
if (materialNode != null) |
|||
m_Node = materialNode; |
|||
} |
|||
} |
|||
|
|||
public PreviewMode generatedShaderMode |
|||
{ |
|||
get { return m_GeneratedShaderMode; } |
|||
set { m_GeneratedShaderMode = value; } |
|||
} |
|||
|
|||
public virtual float GetNodeWidth() |
|||
{ |
|||
return 200; |
|||
} |
|||
|
|||
public virtual GUIModificationType Render(Rect area) |
|||
{ |
|||
if (m_Node == null || !m_Node.drawState.expanded) |
|||
return GUIModificationType.None; |
|||
|
|||
if (m_Node.hasPreview == false) |
|||
return GUIModificationType.None; |
|||
|
|||
if (m_LastShaderVersion != m_Node.version) |
|||
{ |
|||
if (UpdatePreviewShader()) |
|||
m_LastShaderVersion = m_Node.version; |
|||
} |
|||
|
|||
var preview = RenderPreview(area); |
|||
GL.sRGBWrite = QualitySettings.activeColorSpace == ColorSpace.Linear; |
|||
GUI.DrawTexture(area, preview, ScaleMode.StretchToFill, false); |
|||
GL.sRGBWrite = false; |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
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>
|
|||
public Texture RenderPreview(Rect targetSize) |
|||
{ |
|||
previewMaterial.shader = m_PreviewShader; |
|||
UpdateMaterialProperties(m_Node, previewMaterial); |
|||
return previewGenerator.DoRenderPreview(previewMaterial, m_GeneratedShaderMode, targetSize); |
|||
} |
|||
|
|||
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.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.Collections; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using NUnit.Framework; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.MaterialGraph; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
|
|||
namespace UnityEditor.MaterialGraph.IntegrationTests |
|||
{ |
|||
public class ShaderGenerationTest |
|||
{ |
|||
private static readonly string[] s_Path = |
|||
{ |
|||
"UnityShaderEditor", |
|||
"Editor", |
|||
"Testing", |
|||
"IntegrationTests", |
|||
"Graphs" |
|||
}; |
|||
|
|||
public struct TestInfo |
|||
{ |
|||
public string name; |
|||
public FileInfo info; |
|||
public float threshold; |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return name; |
|||
} |
|||
} |
|||
|
|||
public static class CollectGraphs |
|||
{ |
|||
public static IEnumerable graphs |
|||
{ |
|||
get |
|||
{ |
|||
var absoluteGraphsPath = s_Path.Aggregate(Application.dataPath, Path.Combine); |
|||
var filePaths = Directory.GetFiles(absoluteGraphsPath).Select(x => new FileInfo(x)).Where(x => x.Extension == ".ShaderGraph"); |
|||
|
|||
foreach (var p in filePaths) |
|||
{ |
|||
yield return new TestInfo |
|||
{ |
|||
name = p.Name, |
|||
info = p, |
|||
threshold = 0.02f |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private Shader m_Shader; |
|||
private Material m_PreviewMaterial; |
|||
private Texture2D m_Captured; |
|||
private Texture2D m_FromDisk; |
|||
|
|||
[TearDown] |
|||
public void CleanUp() |
|||
{ |
|||
if (m_Shader != null) |
|||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Shader)); |
|||
|
|||
if (m_PreviewMaterial != null) |
|||
Object.DestroyImmediate(m_PreviewMaterial); |
|||
|
|||
if (m_Captured != null) |
|||
Object.DestroyImmediate(m_Captured); |
|||
|
|||
if (m_FromDisk != null) |
|||
Object.DestroyImmediate(m_FromDisk); |
|||
} |
|||
|
|||
[Test, TestCaseSource(typeof(CollectGraphs), "graphs")] |
|||
public void ShaderGeneratorOutput(TestInfo testInfo) |
|||
{ |
|||
var file = testInfo.info; |
|||
var prjRelativeGraphsPath = s_Path.Aggregate("Assets", Path.Combine); |
|||
var filePath = Path.Combine(prjRelativeGraphsPath, file.Name); |
|||
|
|||
var graphAsset = AssetDatabase.LoadAssetAtPath<MaterialGraphAsset>(filePath); |
|||
|
|||
Assert.IsNotNull(graphAsset, "Graph asset not found"); |
|||
|
|||
var materialGraph = graphAsset.graph as PixelGraph; |
|||
Assert.IsNotNull(materialGraph); |
|||
|
|||
// Generate the shader
|
|||
List<PropertyGenerator.TextureInfo> configuredTextures; |
|||
var shaderString = ShaderGenerator.GenerateSurfaceShader(materialGraph.pixelMasterNode, graphAsset.options, materialGraph.name, false, out configuredTextures); |
|||
m_Shader = ShaderUtil.CreateShaderAsset(shaderString); |
|||
m_Shader.hideFlags = HideFlags.HideAndDontSave; |
|||
Assert.IsNotNull(m_Shader, "Shader Generation Failed"); |
|||
Assert.IsFalse(AbstractMaterialNodeUI.ShaderHasError(m_Shader), "Shader has error"); |
|||
|
|||
m_PreviewMaterial = new Material(m_Shader) |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave |
|||
}; |
|||
|
|||
foreach (var textureInfo in configuredTextures) |
|||
{ |
|||
var texture = EditorUtility.InstanceIDToObject(textureInfo.textureId) as Texture; |
|||
if (texture == null) |
|||
continue; |
|||
m_PreviewMaterial.SetTexture(textureInfo.name, texture); |
|||
} |
|||
|
|||
Assert.IsNotNull(m_PreviewMaterial, "preview material could not be created"); |
|||
|
|||
const int res = 256; |
|||
var generator = new MaterialGraphPreviewGenerator(); |
|||
var rendered = generator.DoRenderPreview(m_PreviewMaterial, PreviewMode.Preview3D, new Rect(0, 0, res, res), 10) as RenderTexture; |
|||
|
|||
Assert.IsNotNull(rendered, "Render failed"); |
|||
|
|||
RenderTexture.active = rendered; |
|||
m_Captured = new Texture2D(rendered.width, rendered.height, TextureFormat.ARGB32, false); |
|||
m_Captured.ReadPixels(new Rect(0, 0, rendered.width, rendered.height), 0, 0); |
|||
RenderTexture.active = null; //can help avoid errors
|
|||
|
|||
var rootPath = Directory.GetParent(Directory.GetParent(Application.dataPath).ToString()); |
|||
var templatePath = Path.Combine(rootPath.ToString(), "ImageTemplates"); |
|||
|
|||
// find the reference image
|
|||
var dumpFileLocation = Path.Combine(templatePath, string.Format("{0}.{1}", file.Name, "png")); |
|||
if (!File.Exists(dumpFileLocation)) |
|||
{ |
|||
// no reference exists, create it
|
|||
Directory.CreateDirectory(templatePath); |
|||
var generated = m_Captured.EncodeToPNG(); |
|||
File.WriteAllBytes(dumpFileLocation, generated); |
|||
Assert.Fail("Template file not found for {0}, creating it.", file); |
|||
} |
|||
|
|||
var template = File.ReadAllBytes(dumpFileLocation); |
|||
m_FromDisk = new Texture2D(2,2); |
|||
m_FromDisk.LoadImage(template, false); |
|||
|
|||
var areEqual = CompareTextures(m_FromDisk, m_Captured, testInfo.threshold); |
|||
|
|||
if (!areEqual) |
|||
{ |
|||
var failedPath = Path.Combine(rootPath.ToString(), "Failed"); |
|||
Directory.CreateDirectory(failedPath); |
|||
var misMatchLocationResult = Path.Combine(failedPath, string.Format("{0}.{1}", file.Name, "png")); |
|||
var misMatchLocationTemplate = Path.Combine(failedPath, string.Format("{0}.template.{1}", file.Name, "png")); |
|||
var generated = m_Captured.EncodeToPNG(); |
|||
File.WriteAllBytes(misMatchLocationResult, generated); |
|||
File.WriteAllBytes(misMatchLocationTemplate, template); |
|||
} |
|||
|
|||
Assert.IsTrue(areEqual, "Shader from graph {0}, did not match .template file.", file); |
|||
} |
|||
|
|||
private bool CompareTextures(Texture2D fromDisk, Texture2D captured, float threshold) |
|||
{ |
|||
if (fromDisk == null || captured == null) |
|||
return false; |
|||
|
|||
if (fromDisk.width != captured.width |
|||
|| fromDisk.height != captured.height) |
|||
return false; |
|||
|
|||
var pixels1 = fromDisk.GetPixels(); |
|||
var pixels2 = captured.GetPixels(); |
|||
|
|||
if (pixels1.Length != pixels2.Length) |
|||
return false; |
|||
|
|||
for (int i = 0; i < pixels1.Length; i++) |
|||
{ |
|||
if (!CompareColor(pixels1[i], pixels2[i], threshold)) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
private bool CompareColor(Vector4 left, Vector4 right, float threshold) |
|||
{ |
|||
Vector4 diff = left - right; |
|||
|
|||
if (Mathf.Abs(diff.x) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.y) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.z) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.w) > threshold) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using NUnit.Framework; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.MaterialGraph; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
|
|||
namespace UnityEditor.MaterialGraph.IntegrationTests |
|||
{ |
|||
public class ShaderGenerationTest |
|||
{ |
|||
private static readonly string[] s_Path = |
|||
{ |
|||
"UnityShaderEditor", |
|||
"Editor", |
|||
"Testing", |
|||
"IntegrationTests", |
|||
"Graphs" |
|||
}; |
|||
|
|||
public struct TestInfo |
|||
{ |
|||
public string name; |
|||
public FileInfo info; |
|||
public float threshold; |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return name; |
|||
} |
|||
} |
|||
|
|||
public static class CollectGraphs |
|||
{ |
|||
public static IEnumerable graphs |
|||
{ |
|||
get |
|||
{ |
|||
var absoluteGraphsPath = s_Path.Aggregate(Application.dataPath, Path.Combine); |
|||
var filePaths = Directory.GetFiles(absoluteGraphsPath).Select(x => new FileInfo(x)).Where(x => x.Extension == ".ShaderGraph"); |
|||
|
|||
foreach (var p in filePaths) |
|||
{ |
|||
yield return new TestInfo |
|||
{ |
|||
name = p.Name, |
|||
info = p, |
|||
threshold = 0.02f |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private Shader m_Shader; |
|||
private Material m_PreviewMaterial; |
|||
private Texture2D m_Captured; |
|||
private Texture2D m_FromDisk; |
|||
|
|||
[TearDown] |
|||
public void CleanUp() |
|||
{ |
|||
if (m_Shader != null) |
|||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Shader)); |
|||
|
|||
if (m_PreviewMaterial != null) |
|||
Object.DestroyImmediate(m_PreviewMaterial); |
|||
|
|||
if (m_Captured != null) |
|||
Object.DestroyImmediate(m_Captured); |
|||
|
|||
if (m_FromDisk != null) |
|||
Object.DestroyImmediate(m_FromDisk); |
|||
} |
|||
|
|||
[Test, TestCaseSource(typeof(CollectGraphs), "graphs")] |
|||
public void ShaderGeneratorOutput(TestInfo testInfo) |
|||
{ |
|||
var file = testInfo.info; |
|||
var prjRelativeGraphsPath = s_Path.Aggregate("Assets", Path.Combine); |
|||
var filePath = Path.Combine(prjRelativeGraphsPath, file.Name); |
|||
|
|||
var graphAsset = AssetDatabase.LoadAssetAtPath<MaterialGraphAsset>(filePath); |
|||
|
|||
Assert.IsNotNull(graphAsset, "Graph asset not found"); |
|||
|
|||
var materialGraph = graphAsset.graph as PixelGraph; |
|||
Assert.IsNotNull(materialGraph); |
|||
|
|||
// Generate the shader
|
|||
List<PropertyGenerator.TextureInfo> configuredTextures; |
|||
var shaderString = ShaderGenerator.GenerateSurfaceShader(materialGraph.pixelMasterNode, graphAsset.options, materialGraph.name, false, out configuredTextures); |
|||
m_Shader = ShaderUtil.CreateShaderAsset(shaderString); |
|||
m_Shader.hideFlags = HideFlags.HideAndDontSave; |
|||
Assert.IsNotNull(m_Shader, "Shader Generation Failed"); |
|||
//Assert.IsFalse(AbstractMaterialNodeUI.ShaderHasError(m_Shader), "Shader has error");
|
|||
|
|||
m_PreviewMaterial = new Material(m_Shader) |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave |
|||
}; |
|||
|
|||
foreach (var textureInfo in configuredTextures) |
|||
{ |
|||
var texture = EditorUtility.InstanceIDToObject(textureInfo.textureId) as Texture; |
|||
if (texture == null) |
|||
continue; |
|||
m_PreviewMaterial.SetTexture(textureInfo.name, texture); |
|||
} |
|||
|
|||
Assert.IsNotNull(m_PreviewMaterial, "preview material could not be created"); |
|||
|
|||
const int res = 256; |
|||
var generator = new MaterialGraphPreviewGenerator(); |
|||
var rendered = generator.DoRenderPreview(m_PreviewMaterial, PreviewMode.Preview3D, new Rect(0, 0, res, res), 10) as RenderTexture; |
|||
|
|||
Assert.IsNotNull(rendered, "Render failed"); |
|||
|
|||
RenderTexture.active = rendered; |
|||
m_Captured = new Texture2D(rendered.width, rendered.height, TextureFormat.ARGB32, false); |
|||
m_Captured.ReadPixels(new Rect(0, 0, rendered.width, rendered.height), 0, 0); |
|||
RenderTexture.active = null; //can help avoid errors
|
|||
|
|||
var rootPath = Directory.GetParent(Directory.GetParent(Application.dataPath).ToString()); |
|||
var templatePath = Path.Combine(rootPath.ToString(), "ImageTemplates"); |
|||
|
|||
// find the reference image
|
|||
var dumpFileLocation = Path.Combine(templatePath, string.Format("{0}.{1}", file.Name, "png")); |
|||
if (!File.Exists(dumpFileLocation)) |
|||
{ |
|||
// no reference exists, create it
|
|||
Directory.CreateDirectory(templatePath); |
|||
var generated = m_Captured.EncodeToPNG(); |
|||
File.WriteAllBytes(dumpFileLocation, generated); |
|||
Assert.Fail("Template file not found for {0}, creating it.", file); |
|||
} |
|||
|
|||
var template = File.ReadAllBytes(dumpFileLocation); |
|||
m_FromDisk = new Texture2D(2,2); |
|||
m_FromDisk.LoadImage(template, false); |
|||
|
|||
var areEqual = CompareTextures(m_FromDisk, m_Captured, testInfo.threshold); |
|||
|
|||
if (!areEqual) |
|||
{ |
|||
var failedPath = Path.Combine(rootPath.ToString(), "Failed"); |
|||
Directory.CreateDirectory(failedPath); |
|||
var misMatchLocationResult = Path.Combine(failedPath, string.Format("{0}.{1}", file.Name, "png")); |
|||
var misMatchLocationTemplate = Path.Combine(failedPath, string.Format("{0}.template.{1}", file.Name, "png")); |
|||
var generated = m_Captured.EncodeToPNG(); |
|||
File.WriteAllBytes(misMatchLocationResult, generated); |
|||
File.WriteAllBytes(misMatchLocationTemplate, template); |
|||
} |
|||
|
|||
Assert.IsTrue(areEqual, "Shader from graph {0}, did not match .template file.", file); |
|||
} |
|||
|
|||
private bool CompareTextures(Texture2D fromDisk, Texture2D captured, float threshold) |
|||
{ |
|||
if (fromDisk == null || captured == null) |
|||
return false; |
|||
|
|||
if (fromDisk.width != captured.width |
|||
|| fromDisk.height != captured.height) |
|||
return false; |
|||
|
|||
var pixels1 = fromDisk.GetPixels(); |
|||
var pixels2 = captured.GetPixels(); |
|||
|
|||
if (pixels1.Length != pixels2.Length) |
|||
return false; |
|||
|
|||
for (int i = 0; i < pixels1.Length; i++) |
|||
{ |
|||
if (!CompareColor(pixels1[i], pixels2[i], threshold)) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
private bool CompareColor(Vector4 left, Vector4 right, float threshold) |
|||
{ |
|||
Vector4 diff = left - right; |
|||
|
|||
if (Mathf.Abs(diff.x) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.y) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.z) > threshold) |
|||
return false; |
|||
if (Mathf.Abs(diff.w) > threshold) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|
|||
m_EditorVersion: 5.5.0a4 |
|||
m_EditorVersion: 5.5.0b1 |
|
|||
using System; |
|||
using RMGUI.GraphView; |
|||
using RMGUI.GraphView.Demo; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEditor.Graphing.Drawing |
|||
{ |
|||
[Serializable] |
|||
public class MaterialNodeAnchorData : NodeAnchorData |
|||
{ |
|||
protected MaterialNodeAnchorData() |
|||
{} |
|||
|
|||
public ISlot slot { get; private set; } |
|||
|
|||
public void Initialize(ISlot slot) |
|||
{ |
|||
this.slot = slot; |
|||
name = slot.displayName; |
|||
type = typeof(Vector4); |
|||
direction = slot.isInputSlot ? Direction.Input : Direction.Output; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1203426382783614091fee813fe72265 |
|||
timeCreated: 1475825200 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
VerticalNode #top { |
|||
flex: 1; |
|||
align-items: flex-start; |
|||
flex-direction: row; |
|||
} |
|||
|
|||
VerticalNode #bottom { |
|||
flex: 1; |
|||
align-items: flex-start; |
|||
flex-direction: row; |
|||
} |
|||
|
|||
VerticalNode NodeAnchor { |
|||
height: 50; |
|||
flex:1; |
|||
} |
|||
|
|||
Node { |
|||
flex-direction: row; |
|||
} |
|||
|
|||
Node #input { |
|||
flex:1; |
|||
} |
|||
|
|||
Node #output { |
|||
flex:1; |
|||
justify-content: flex-end; |
|||
} |
|||
|
|||
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; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b3dd47151f230aa41a6182074b34fc0a |
|||
timeCreated: 1475841339 |
|||
licenseType: Pro |
|||
StyleSheetImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
WWWImage { |
|||
/* TODO refactor with two containers. |
|||
Here reseting the padding-top will offset the text content as well*/ |
|||
/*padding-top: 0;*/ |
|||
padding-left: 0; |
|||
padding-right: 0; |
|||
padding-bottom: 0; |
|||
} |
|||
|
|||
WWWImage > Image { |
|||
flex:1; |
|||
} |
|||
|
|||
MiniMap Label { |
|||
position-type:absolute; |
|||
position-top:0; |
|||
position-left:0; |
|||
position-right:0; |
|||
height: 16; |
|||
} |
|||
|
|||
MiniMap { |
|||
position-type:absolute; |
|||
padding-top:20; |
|||
} |
|||
|
|||
MiniMap.anchored { |
|||
position-left:20; |
|||
position-bottom:20; |
|||
} |
|||
|
|||
MiniMap.anchored Label{ |
|||
color:#aaaa00 |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 19a7fac700a3cd14789ff6cd06ff8e74 |
|||
timeCreated: 1475841339 |
|||
licenseType: Pro |
|||
StyleSheetImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace RMGUI.GraphView |
|||
{ |
|||
public interface IDataSource |
|||
{ |
|||
IEnumerable<GraphElementData> elements { get; } |
|||
void AddElement(GraphElementData element); |
|||
void RemoveElement(GraphElementData element); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: adeb8115e066ca44891d5c8978e6db6d |
|||
timeCreated: 1475852344 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(Vector4Node))] |
|||
public class Vector4NodeUI : ICustomNodeUi |
|||
{ |
|||
private Vector4Node m_Node; |
|||
|
|||
public float GetNodeUiHeight(float width) |
|||
{ |
|||
return 2 * EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public GUIModificationType Render(Rect area) |
|||
{ |
|||
if (m_Node == null) |
|||
return GUIModificationType.None; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Node.value = EditorGUI.Vector4Field(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), "Value", m_Node.value); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
//TODO:tidy this shit.
|
|||
//EditorUtility.SetDirty(materialGraphOwner.owner);
|
|||
return GUIModificationType.Repaint; |
|||
} |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public INode node |
|||
{ |
|||
get { return m_Node; } |
|||
set |
|||
{ |
|||
var materialNode = value as Vector4Node; |
|||
if (materialNode != null) |
|||
m_Node = materialNode; |
|||
} |
|||
} |
|||
|
|||
public float GetNodeWidth() |
|||
{ |
|||
return 200; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f970378d854a8e6458eb369bfb46bc42 |
|||
timeCreated: 1464865885 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(PixelShaderNode))] |
|||
public class PixelShaderNodeUI : AbstractMaterialNodeUI |
|||
{ |
|||
public override float GetNodeWidth() |
|||
{ |
|||
return 300; |
|||
} |
|||
|
|||
public override float GetNodeUiHeight(float width) |
|||
{ |
|||
return base.GetNodeUiHeight(width) + EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public override GUIModificationType Render(Rect area) |
|||
{ |
|||
var localNode = node as PixelShaderNode; |
|||
if (localNode == null) |
|||
return base.Render(area); |
|||
|
|||
var lightFunctions = PixelShaderNode.GetLightFunctions(); |
|||
var lightFunction = localNode.lightFunction.GetType(); |
|||
|
|||
int lightFuncIndex = 0; |
|||
if (lightFunction != null) |
|||
lightFuncIndex = lightFunctions.Select(x => x.GetType()).ToList().IndexOf(lightFunction); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
lightFuncIndex = EditorGUI.Popup(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), lightFuncIndex, lightFunctions.Select(x => x.lightFunctionName).ToArray(), EditorStyles.popup); |
|||
localNode.lightFunction = lightFunctions[lightFuncIndex]; |
|||
var toReturn = GUIModificationType.None; |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
localNode.UpdateNodeAfterDeserialization(); |
|||
toReturn = GUIModificationType.ModelChanged; |
|||
} |
|||
area.y += EditorGUIUtility.singleLineHeight; |
|||
area.height -= EditorGUIUtility.singleLineHeight; |
|||
toReturn |= base.Render(area); |
|||
return toReturn; |
|||
} |
|||
|
|||
protected override string GetPreviewShaderString() |
|||
{ |
|||
var localNode = node as PixelShaderNode; |
|||
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); |
|||
generatedShaderMode = PreviewMode.Preview3D; |
|||
return resultShader; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 083ef7de3d86719428d2018dc114d827 |
|||
timeCreated: 1464940201 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(ColorNode))] |
|||
public class ColorNodeUI : ICustomNodeUi |
|||
{ |
|||
private ColorNode m_Node; |
|||
|
|||
public float GetNodeUiHeight(float width) |
|||
{ |
|||
return 2 * EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public GUIModificationType Render(Rect area) |
|||
{ |
|||
if (m_Node == null) |
|||
return GUIModificationType.None; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Node.color = EditorGUI.ColorField(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), "Value", m_Node.color); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
return GUIModificationType.Repaint; |
|||
} |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public INode node |
|||
{ |
|||
get { return m_Node; } |
|||
set |
|||
{ |
|||
var materialNode = value as ColorNode; |
|||
if (materialNode != null) |
|||
m_Node = materialNode; |
|||
} |
|||
} |
|||
|
|||
public float GetNodeWidth() |
|||
{ |
|||
return 200; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1764879bbfb2621418d1c58fdf5b93fc |
|||
timeCreated: 1464957369 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(CombineNode))] |
|||
public class CombineNodeUI : AbstractMaterialNodeUI |
|||
{ |
|||
public override float GetNodeUiHeight(float width) |
|||
{ |
|||
return base.GetNodeUiHeight(width) + EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public override GUIModificationType Render(Rect area) |
|||
{ |
|||
var localNode = node as CombineNode; |
|||
if (localNode == null) |
|||
return base.Render(area); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
localNode.operation = (CombineNode.Operation)EditorGUI.EnumPopup(area, localNode.operation); |
|||
|
|||
var toReturn = GUIModificationType.None; |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
toReturn = GUIModificationType.DataChanged; |
|||
} |
|||
|
|||
area.y += EditorGUIUtility.singleLineHeight; |
|||
area.height -= EditorGUIUtility.singleLineHeight; |
|||
toReturn |= base.Render(area); |
|||
return toReturn; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 699eabcc43767844f9558d3314df6b1b |
|||
timeCreated: 1464957369 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(Vector1Node))] |
|||
public class Vector1NodeUI : PropertyNodeUI |
|||
{ |
|||
public override float GetNodeUiHeight(float width) |
|||
{ |
|||
return base.GetNodeUiHeight(width) + EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public override GUIModificationType Render(Rect area) |
|||
{ |
|||
var localNode = node as Vector1Node; |
|||
if (localNode == null) |
|||
return base.Render(area); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
localNode.value = EditorGUI.FloatField(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), "Value", localNode.value); |
|||
|
|||
var toReturn = GUIModificationType.None; |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
//TODO:tidy this shit.
|
|||
//EditorUtility.SetDirty(materialGraphOwner.owner);
|
|||
toReturn |= GUIModificationType.Repaint; |
|||
} |
|||
|
|||
area.y += EditorGUIUtility.singleLineHeight; |
|||
area.height -= EditorGUIUtility.singleLineHeight; |
|||
toReturn |= base.Render(area); |
|||
return toReturn; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 384d8aee5b4f7be4986d433b2713a49a |
|||
timeCreated: 1464961768 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(Vector2Node))] |
|||
public class Vector2NodeUI : ICustomNodeUi |
|||
{ |
|||
private Vector2Node m_Node; |
|||
|
|||
public float GetNodeUiHeight(float width) |
|||
{ |
|||
return 2 * EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public GUIModificationType Render(Rect area) |
|||
{ |
|||
if (m_Node == null) |
|||
return GUIModificationType.None; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Node.value = EditorGUI.Vector2Field(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), "Value", m_Node.value); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
//TODO:tidy this shit.
|
|||
//EditorUtility.SetDirty(materialGraphOwner.owner);
|
|||
return GUIModificationType.Repaint; |
|||
} |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public INode node |
|||
{ |
|||
get { return m_Node; } |
|||
set |
|||
{ |
|||
var materialNode = value as Vector2Node; |
|||
if (materialNode != null) |
|||
m_Node = materialNode; |
|||
} |
|||
} |
|||
|
|||
public float GetNodeWidth() |
|||
{ |
|||
return 200; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9d3c3a11d71fc154d8d6c3c5a6ebfdfe |
|||
timeCreated: 1464961768 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(Vector3Node))] |
|||
public class Vector3NodeUI : ICustomNodeUi |
|||
{ |
|||
private Vector3Node m_Node; |
|||
|
|||
public float GetNodeUiHeight(float width) |
|||
{ |
|||
return 2 * EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public GUIModificationType Render(Rect area) |
|||
{ |
|||
if (m_Node == null) |
|||
return GUIModificationType.None; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_Node.value = EditorGUI.Vector3Field(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), "Value", m_Node.value); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
//TODO:tidy this shit.
|
|||
//EditorUtility.SetDirty(materialGraphOwner.owner);
|
|||
return GUIModificationType.Repaint; |
|||
} |
|||
return GUIModificationType.None; |
|||
} |
|||
|
|||
public INode node |
|||
{ |
|||
get { return m_Node; } |
|||
set |
|||
{ |
|||
var materialNode = value as Vector3Node; |
|||
if (materialNode != null) |
|||
m_Node = materialNode; |
|||
} |
|||
} |
|||
|
|||
public float GetNodeWidth() |
|||
{ |
|||
return 200; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fb53610f494711741a3c0f528c5e9d87 |
|||
timeCreated: 1464961769 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 18bed0222cc2dfa4db99426806adb913 |
|||
timeCreated: 1465476659 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.Graphing; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(AbstractSubGraphIONode))] |
|||
public class SubGraphIONodeUI : ICustomNodeUi |
|||
{ |
|||
private AbstractSubGraphIONode m_Node; |
|||
|
|||
public float GetNodeUiHeight(float width) |
|||
{ |
|||
return 2 * EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public GUIModificationType Render(Rect area) |
|||
{ |
|||
if (m_Node == null) |
|||
return GUIModificationType.None; |
|||
|
|||
var modification = GUIModificationType.None; |
|||
if (GUI.Button(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), "Add Slot")) |
|||
{ |
|||
m_Node.AddSlot(); |
|||
modification |= GUIModificationType.ModelChanged; |
|||
} |
|||
|
|||
if (GUI.Button(new Rect(area.x, area.y + EditorGUIUtility.singleLineHeight, area.width, EditorGUIUtility.singleLineHeight), "Remove Slot")) |
|||
{ |
|||
m_Node.RemoveSlot(); |
|||
modification |= GUIModificationType.ModelChanged; |
|||
} |
|||
return modification; |
|||
} |
|||
|
|||
public INode node |
|||
{ |
|||
get { return m_Node; } |
|||
set |
|||
{ |
|||
var materialNode = value as AbstractSubGraphIONode; |
|||
if (materialNode != null) |
|||
m_Node = materialNode; |
|||
} |
|||
} |
|||
|
|||
public float GetNodeWidth() |
|||
{ |
|||
return 100; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 266aca8675f91a74bb0441f8bcf8acb8 |
|||
timeCreated: 1465809586 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(SubGraphNode))] |
|||
public class SubgraphNodeUI : AbstractMaterialNodeUI |
|||
{ |
|||
public override float GetNodeUiHeight(float width) |
|||
{ |
|||
return base.GetNodeUiHeight(width) + EditorGUIUtility.singleLineHeight; |
|||
} |
|||
|
|||
public override GUIModificationType Render(Rect area) |
|||
{ |
|||
var localNode = node as SubGraphNode; |
|||
if (localNode == null) |
|||
return base.Render(area); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
localNode.subGraphAsset = (MaterialSubGraphAsset)EditorGUI.ObjectField(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), |
|||
new GUIContent("SubGraph"), |
|||
localNode.subGraphAsset, |
|||
typeof(MaterialSubGraphAsset), false); |
|||
|
|||
var toReturn = GUIModificationType.None; |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
toReturn |= GUIModificationType.ModelChanged; |
|||
|
|||
area.y += EditorGUIUtility.singleLineHeight; |
|||
area.height -= EditorGUIUtility.singleLineHeight; |
|||
toReturn |= base.Render(area); |
|||
return toReturn; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 311840105ab3e5c48859be33dab6b33e |
|||
timeCreated: 1468327292 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEditor.Graphing; |
|||
using UnityEditor.Graphing.Drawing; |
|||
using UnityEngine; |
|||
using UnityEngine.MaterialGraph; |
|||
|
|||
namespace UnityEditor.MaterialGraph |
|||
{ |
|||
[CustomNodeUI(typeof(PropertyNode))] |
|||
public class PropertyNodeUI : AbstractMaterialNodeUI |
|||
{ |
|||
public override float GetNodeUiHeight(float width) |
|||
{ |
|||
return base.GetNodeUiHeight(width) + EditorGUIUtility.singleLineHeight * 1; |
|||
} |
|||
|
|||
public override GUIModificationType Render(Rect area) |
|||
{ |
|||
var localNode = node as PropertyNode; |
|||
if (localNode == null) |
|||
return base.Render(area); |
|||
|
|||
var toReturn = GUIModificationType.None; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
localNode.exposedState = (PropertyNode.ExposedState)EditorGUI.EnumPopup(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), new GUIContent("Exposed"), localNode.exposedState); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
toReturn |= GUIModificationType.DataChanged; |
|||
|
|||
area.y += EditorGUIUtility.singleLineHeight; |
|||
area.height -= EditorGUIUtility.singleLineHeight; |
|||
toReturn |= base.Render(area); |
|||
return toReturn; |
|||
} |
|||
} |
|||
|
|||
[CustomNodeUI(typeof(TextureNode))] |
|||
public class TextureNodeUI : PropertyNodeUI |
|||
{ |
|||
public override float GetNodeUiHeight(float width) |
|||
{ |
|||
return base.GetNodeUiHeight(width) + EditorGUIUtility.singleLineHeight * 2; |
|||
} |
|||
|
|||
private string[] m_TextureTypeNames; |
|||
private string[] textureTypeNames |
|||
{ |
|||
get |
|||
{ |
|||
if (m_TextureTypeNames == null) |
|||
m_TextureTypeNames = Enum.GetNames(typeof(TextureType)); |
|||
return m_TextureTypeNames; |
|||
} |
|||
} |
|||
|
|||
public override GUIModificationType Render(Rect area) |
|||
{ |
|||
var localNode = node as TextureNode; |
|||
if (localNode == null) |
|||
return base.Render(area); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
//localNode.defaultTexture = EditorGUI.MiniThumbnailObjectField(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), new GUIContent("Texture"), localNode.defaultTexture, typeof(Texture2D), null) as Texture2D;
|
|||
var texureChanged = EditorGUI.EndChangeCheck(); |
|||
area.y += EditorGUIUtility.singleLineHeight; |
|||
area.height -= EditorGUIUtility.singleLineHeight; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
localNode.textureType = (TextureType)EditorGUI.Popup(new Rect(area.x, area.y, area.width, EditorGUIUtility.singleLineHeight), (int)localNode.textureType, textureTypeNames, EditorStyles.popup); |
|||
var typeChanged = EditorGUI.EndChangeCheck(); |
|||
|
|||
var toReturn = GUIModificationType.None; |
|||
if (typeChanged) |
|||
{ |
|||
toReturn |= GUIModificationType.DataChanged; |
|||
} |
|||
|
|||
if (texureChanged) |
|||
toReturn |= GUIModificationType.Repaint; |
|||
|
|||
area.y += EditorGUIUtility.singleLineHeight; |
|||
area.height -= EditorGUIUtility.singleLineHeight; |
|||
toReturn |= base.Render(area); |
|||
return toReturn; |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue