Matt Dean
7 年前
当前提交
dc41a21f
共有 2 个文件被更改,包括 264 次插入 和 0 次删除
-
252MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs
-
12MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Math/Matrix/MatrixSplitNode.cs.meta
|
|||
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; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 03599e40507c24caba0dd9b596f3b5dc |
|||
timeCreated: 1490896965 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue