浏览代码

Working 'convert to subgraph'

/main
Tim Cooper 7 年前
当前提交
793887f9
共有 11 个文件被更改,包括 163 次插入15 次删除
  1. 119
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/AbstractMaterialGraphEditWindow.cs
  2. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialGraphPresenter.cs
  3. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialNodePresenter.cs
  4. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/TitleBarPresenter.cs
  5. 5
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/MaterialGraphView.cs
  6. 7
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/Time/SinTimeNode.cs
  7. 7
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/Time/TimeNode.cs
  8. 9
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphNode.cs
  9. 7
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IMayRequireTime.cs
  10. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IRequiresTime.cs
  11. 0
      /MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IMayRequireTime.cs.meta

119
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/AbstractMaterialGraphEditWindow.cs


void Repaint();
void ToggleRequiresTime();
void ToSubGraph();
}
public class MaterialGraphEditWindow : AbstractMaterialGraphEditWindow<UnityEngine.MaterialGraph.MaterialGraph>

}
}
public void ToSubGraph()
{
string path = EditorUtility.SaveFilePanelInProject("Save subgraph", "New SubGraph", "ShaderSubGraph", "");
path = path.Replace(Application.dataPath, "Assets");
if (path.Length == 0)
return;
var graphDataSource = m_GraphEditorView.presenter;
var selected = graphDataSource.elements.Where(e => e.selected).ToArray();
var deserialized = MaterialGraphPresenter.DeserializeCopyBuffer(JsonUtility.ToJson(MaterialGraphPresenter.CreateCopyPasteGraph(selected)));
if (deserialized == null)
return;
var graph = new SubGraph();
graph.AddNode(new SubGraphInputNode());
graph.AddNode(new SubGraphOutputNode());
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));
}
}
File.WriteAllText(path, EditorJsonUtility.ToJson(graph));
AssetDatabase.ImportAsset(path);
var subGraph = AssetDatabase.LoadAssetAtPath(path, typeof(MaterialSubGraphAsset)) as MaterialSubGraphAsset;
if (subGraph == null)
return;
var subGraphNode = new SubGraphNode();
graphDataSource.AddNode(subGraphNode);
subGraphNode.subGraphAsset = subGraph;
foreach (var edgeMap in inputsNeedingConnection)
{
graphDataSource.graph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.outputSlot.slotId));
}
foreach (var edgeMap in outputsNeedingConnection)
{
graphDataSource.graph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot);
}
var toDelete = graphDataSource.elements.Where(e => e.selected).OfType<MaterialNodePresenter>();
graphDataSource.RemoveElements(toDelete, new List<GraphEdgePresenter>());
}
private void UpdateShaderSubGraphOnDisk(string path)
{
var graph = inMemoryAsset as SubGraph;

File.WriteAllText(path, EditorJsonUtility.ToJson(inMemoryAsset));
AssetDatabase.ImportAsset(path);
}
private void UpdateShaderGraphOnDisk(string path)

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialGraphPresenter.cs


}
}
CopyPasteGraph CreateCopyPasteGraph(IEnumerable<GraphElementPresenter> selection)
internal static CopyPasteGraph CreateCopyPasteGraph(IEnumerable<GraphElementPresenter> selection)
{
var graph = new CopyPasteGraph();
foreach (var presenter in selection)

return graph;
}
CopyPasteGraph DeserializeCopyBuffer(string copyBuffer)
internal static CopyPasteGraph DeserializeCopyBuffer(string copyBuffer)
{
try
{

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/MaterialNodePresenter.cs


using (var childrenNodes = ListPool<INode>.GetDisposable())
{
NodeUtils.DepthFirstCollectNodesFromNode(childrenNodes.value, node);
return childrenNodes.value.OfType<IRequiresTime>().Any();
return childrenNodes.value.OfType<IMayRequireTime>().Any(x => x.RequiresTime());
}
}
}

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Presenters/TitleBarPresenter.cs


updateAsset.onClick += UpdateAsset;
m_leftItems.Add(updateAsset);
var showInProjectItem = CreateInstance<TitleBarButtonPresenter>();
var toSubGraph = CreateInstance<TitleBarButtonPresenter>();
toSubGraph.text = "Selection -> Subgraph";
toSubGraph.onClick += ToSubGraph;
m_leftItems.Add(toSubGraph);
var showInProjectItem = CreateInstance<TitleBarButtonPresenter>();
showInProjectItem.text = "Show in project";
showInProjectItem.onClick += OnShowInProjectClick;
m_leftItems.Add(showInProjectItem);

void UpdateAsset()
{
m_Owner.UpdateAsset ();
}
void ToSubGraph()
{
m_Owner.ToSubGraph();
}
void ToggleTime()

5
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/Views/MaterialGraphView.cs


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor.Experimental.UIElements.GraphView;

}
}
}
//gm.AddSeparator("");
// gm.AddItem(new GUIContent("Convert To/SubGraph"), true, ConvertSelectionToSubGraph);
gm.ShowAsContext();
}
evt.StopPropagation();

7
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/Time/SinTimeNode.cs


namespace UnityEngine.MaterialGraph
{
[Title("Input/Time/Sine Time")]
public class SinTimeNode : AbstractMaterialNode, IRequiresTime
public class SinTimeNode : AbstractMaterialNode, IMayRequireTime
{
public SinTimeNode()
{

public override string GetVariableNameForSlot(int slotIds)
{
return "_SinTime";
}
public bool RequiresTime()
{
return true;
}
}
}

7
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/Time/TimeNode.cs


namespace UnityEngine.MaterialGraph
{
[Title("Input/Time/Time")]
public class TimeNode : AbstractMaterialNode, IRequiresTime
public class TimeNode : AbstractMaterialNode, IMayRequireTime
{
private const string kOutputSlotName = "Time";
private const string kOutputSlotNameX = "Time/20";

default:
return "_Time";
}
}
public bool RequiresTime()
{
return true;
}
}
}

9
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphNode.cs


, IMayRequireWorldPosition
, IMayRequireVertexColor
, IMayRequireViewDirectionTangentSpace
, IMayRequireTime
{
[SerializeField]
private string m_SerializedSubGraph = string.Empty;

return false;
return subGraph.activeNodes.OfType<IMayRequireTangent>().Any(x => x.RequiresTangent());
}
public bool RequiresTime()
{
if (subGraph == null)
return false;
return subGraph.activeNodes.OfType<IMayRequireTime>().Any(x => x.RequiresTime());
}
public bool RequiresBitangent()

7
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IMayRequireTime.cs


namespace UnityEngine.MaterialGraph
{
public interface IMayRequireTime
{
bool RequiresTime();
}
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IRequiresTime.cs


namespace UnityEngine.MaterialGraph
{
public interface IRequiresTime
{
}
}

/MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IRequiresTime.cs.meta → /MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Interfaces/IMayRequireTime.cs.meta

正在加载...
取消
保存