浏览代码

Add Matrix Split node

/main
Matt Dean 7 年前
当前提交
dc41a21f
共有 2 个文件被更改,包括 264 次插入0 次删除
  1. 252
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs
  2. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs.meta

252
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor.Graphing;
namespace UnityEditor.ShaderGraph
{
[Title("Math", "Matrix", "Matrix Split")]
public class MatrixSplitNode : AbstractMaterialNode, IGeneratesBodyCode
{
const string kInputSlotName = "Input";
const string kOutputSlotM0Name = "M0";
const string kOutputSlotM1Name = "M1";
const string kOutputSlotM2Name = "M2";
const string kOutputSlotM3Name = "M3";
public const int InputSlotId = 0;
public const int OutputSlotRId = 1;
public const int OutputSlotGId = 2;
public const int OutputSlotBId = 3;
public const int OutputSlotAId = 4;
public MatrixSplitNode()
{
name = "Matrix Split";
UpdateNodeAfterDeserialization();
}
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new DynamicMatrixMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input));
AddSlot(new DynamicVectorMaterialSlot(OutputSlotRId, kOutputSlotM0Name, kOutputSlotM0Name, SlotType.Output, Vector4.zero));
AddSlot(new DynamicVectorMaterialSlot(OutputSlotGId, kOutputSlotM1Name, kOutputSlotM1Name, SlotType.Output, Vector4.zero));
AddSlot(new DynamicVectorMaterialSlot(OutputSlotBId, kOutputSlotM2Name, kOutputSlotM2Name, SlotType.Output, Vector4.zero));
AddSlot(new DynamicVectorMaterialSlot(OutputSlotAId, kOutputSlotM3Name, kOutputSlotM3Name, SlotType.Output, Vector4.zero));
RemoveSlotsNameNotMatching(new int[] { InputSlotId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId });
}
static int[] s_OutputSlots = {OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId};
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
var inputValue = GetSlotValue(InputSlotId, generationMode);
var inputSlot = FindInputSlot<MaterialSlot>(InputSlotId);
var numInputRows = 0;
if (inputSlot != null)
{
numInputRows = SlotValueHelper.GetMatrixDimension(inputSlot.concreteValueType);
if (numInputRows > 4)
numInputRows = 0;
if (!owner.GetEdges(inputSlot.slotReference).Any())
numInputRows = 0;
}
for (var i = 0; i < 4; i++)
{
var outputFormat = string.Format("{0}[{1}]", inputValue, i);
string outputValue;
if(i >= numInputRows)
{
outputValue = string.Format("{0}{1}(", precision, numInputRows);
for(int r = 0; r < numInputRows; r++)
{
if(r!= 0)
outputValue += ", ";
outputValue += "0";
}
outputValue += ");";
}
else
outputValue = outputFormat;
visitor.AddShaderChunk(string.Format("{0}{1} {2} = {3};", precision, numInputRows, GetVariableNameForSlot(s_OutputSlots[i]), outputValue), true);
}
}
public override void ValidateNode()
{
var isInError = false;
// all children nodes needs to be updated first
// so do that here
var slots = ListPool<MaterialSlot>.Get();
GetInputSlots(slots);
foreach (var inputSlot in slots)
{
inputSlot.hasError = false;
var edges = owner.GetEdges(inputSlot.slotReference);
foreach (var edge in edges)
{
var fromSocketRef = edge.outputSlot;
var outputNode = owner.GetNodeFromGuid(fromSocketRef.nodeGuid);
if (outputNode == null)
continue;
outputNode.ValidateNode();
if (outputNode.hasError)
isInError = true;
}
}
ListPool<MaterialSlot>.Release(slots);
var dynamicInputSlotsToCompare = DictionaryPool<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicSlots = ListPool<DynamicVectorMaterialSlot>.Get();
var dynamicMatrixInputSlotsToCompare = DictionaryPool<DynamicMatrixMaterialSlot, ConcreteSlotValueType>.Get();
var skippedDynamicMatrixSlots = ListPool<DynamicMatrixMaterialSlot>.Get();
// iterate the input slots
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);
foreach (var inputSlot in s_TempSlots)
{
// if there is a connection
var edges = owner.GetEdges(inputSlot.slotReference).ToList();
if (!edges.Any())
{
if (inputSlot is DynamicVectorMaterialSlot)
skippedDynamicSlots.Add(inputSlot as DynamicVectorMaterialSlot);
if (inputSlot is DynamicMatrixMaterialSlot)
skippedDynamicMatrixSlots.Add(inputSlot as DynamicMatrixMaterialSlot);
continue;
}
// get the output details
var outputSlotRef = edges[0].outputSlot;
var outputNode = owner.GetNodeFromGuid(outputSlotRef.nodeGuid);
if (outputNode == null)
continue;
var outputSlot = outputNode.FindOutputSlot<MaterialSlot>(outputSlotRef.slotId);
if (outputSlot == null)
continue;
if (outputSlot.hasError)
{
inputSlot.hasError = true;
continue;
}
var outputConcreteType = outputSlot.concreteValueType;
// dynamic input... depends on output from other node.
// we need to compare ALL dynamic inputs to make sure they
// are compatable.
if (inputSlot is DynamicVectorMaterialSlot)
{
dynamicInputSlotsToCompare.Add((DynamicVectorMaterialSlot)inputSlot, outputConcreteType);
continue;
}
else if (inputSlot is DynamicMatrixMaterialSlot)
{
dynamicMatrixInputSlotsToCompare.Add((DynamicMatrixMaterialSlot)inputSlot, outputConcreteType);
continue;
}
// if we have a standard connection... just check the types work!
if (!AbstractMaterialNode.ImplicitConversionExists(outputConcreteType, inputSlot.concreteValueType))
inputSlot.hasError = true;
}
// and now dynamic matrices
var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicMatrixInputSlotsToCompare.Values);
foreach (var dynamicKvP in dynamicMatrixInputSlotsToCompare)
dynamicKvP.Key.SetConcreteType(dynamicMatrixType);
foreach (var skippedSlot in skippedDynamicMatrixSlots)
skippedSlot.SetConcreteType(dynamicMatrixType);
// we can now figure out the dynamic slotType
// from here set all the
var dynamicType = SlotValueHelper.ConvertMatrixToVectorType(dynamicMatrixType);
foreach (var dynamicKvP in dynamicInputSlotsToCompare)
dynamicKvP.Key.SetConcreteType(dynamicType);
foreach (var skippedSlot in skippedDynamicSlots)
skippedSlot.SetConcreteType(dynamicType);
s_TempSlots.Clear();
GetInputSlots(s_TempSlots);
var inputError = s_TempSlots.Any(x => x.hasError);
// configure the output slots now
// their slotType will either be the default output slotType
// or the above dynanic slotType for dynamic nodes
// or error if there is an input error
s_TempSlots.Clear();
GetOutputSlots(s_TempSlots);
foreach (var outputSlot in s_TempSlots)
{
outputSlot.hasError = false;
if (inputError)
{
outputSlot.hasError = true;
continue;
}
if (outputSlot is DynamicVectorMaterialSlot)
{
(outputSlot as DynamicVectorMaterialSlot).SetConcreteType(dynamicType);
continue;
}
else if (outputSlot is DynamicMatrixMaterialSlot)
{
(outputSlot as DynamicMatrixMaterialSlot).SetConcreteType(dynamicMatrixType);
continue;
}
}
isInError |= inputError;
s_TempSlots.Clear();
GetOutputSlots(s_TempSlots);
isInError |= s_TempSlots.Any(x => x.hasError);
isInError |= CalculateNodeHasError();
hasError = isInError;
if (!hasError)
{
++version;
}
ListPool<DynamicVectorMaterialSlot>.Release(skippedDynamicSlots);
DictionaryPool<DynamicVectorMaterialSlot, ConcreteSlotValueType>.Release(dynamicInputSlotsToCompare);
ListPool<DynamicMatrixMaterialSlot>.Release(skippedDynamicMatrixSlots);
DictionaryPool<DynamicMatrixMaterialSlot, ConcreteSlotValueType>.Release(dynamicMatrixInputSlotsToCompare);
}
public override ConcreteSlotValueType ConvertDynamicInputTypeToConcrete(IEnumerable<ConcreteSlotValueType> inputTypes)
{
var concreteSlotValueTypes = inputTypes as IList<ConcreteSlotValueType> ?? inputTypes.ToList();
var inputTypesDistinct = concreteSlotValueTypes.Distinct().ToList();
switch (inputTypesDistinct.Count)
{
case 0:
return ConcreteSlotValueType.Vector1;
case 1:
return inputTypesDistinct.FirstOrDefault();
default:
// find the 'minumum' channel width excluding 1 as it can promote
inputTypesDistinct.RemoveAll(x => x == ConcreteSlotValueType.Vector1);
var ordered = inputTypesDistinct.OrderByDescending(x => x);
if (ordered.Any())
return ordered.FirstOrDefault();
break;
}
return ConcreteSlotValueType.Vector1;
}
}
}

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs.meta


fileFormatVersion: 2
guid: 03599e40507c24caba0dd9b596f3b5dc
timeCreated: 1490896965
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存