您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

375 行
13 KiB

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