public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) { var inputValue = GetSlotValue(InputSlotId, generationMode); var inputSlot = FindInputSlot <MaterialSlot>(InputSlotId); var numInputChannels = 0; if (inputSlot != null) { numInputChannels = SlotValueHelper.GetChannelCount(inputSlot.concreteValueType); if (numInputChannels > 4) { numInputChannels = 0; } if (!owner.GetEdges(inputSlot.slotReference).Any()) { numInputChannels = 0; } } for (var i = 0; i < 4; i++) { var outputFormat = numInputChannels == 1 ? inputValue : string.Format("{0}[{1}]", inputValue, i); var outputValue = i >= numInputChannels ? "0" : outputFormat; visitor.AddShaderChunk(string.Format("{0} {1} = {2};", precision, GetVariableNameForSlot(s_OutputSlots[i]), outputValue), true); } }
private static bool ImplicitConversionExists(ConcreteSlotValueType from, ConcreteSlotValueType to) { if (from == to) { return(true); } var fromCount = SlotValueHelper.GetChannelCount(from); var toCount = SlotValueHelper.GetChannelCount(to); // can convert from v1 vectors :) if (from == ConcreteSlotValueType.Vector1 && toCount > 0) { return(true); } if (toCount == 0) { return(false); } if (toCount <= fromCount) { return(true); } return(false); }
void ValidateChannelCount() { int channelCount = SlotValueHelper.GetChannelCount(FindSlot <MaterialSlot>(InputSlotId).concreteValueType); if (channelMask >= 1 << channelCount) { channelMask = -1; } }
public bool IsCompatibleWith(MaterialSlot otherSlot) { return(otherSlot != null && otherSlot.owner != owner && otherSlot.isInputSlot != isInputSlot && ((isInputSlot ? SlotValueHelper.AreCompatible(valueType, otherSlot.concreteValueType) : SlotValueHelper.AreCompatible(otherSlot.valueType, concreteValueType)))); }
protected override string ConcreteSlotValueAsVariable() { var channelCount = SlotValueHelper.GetChannelCount(concreteValueType); string values = NodeUtils.FloatToShaderValue(value.m00); if (channelCount == 1) return values; for (var i = 1; i < channelCount; i++) values += ", " + NodeUtils.FloatToShaderValue(value.GetRow(0)[i]); return string.Format("$precision{0}({1})", channelCount, values); }
public bool IsCompatibleWith(MaterialSlot otherSlot) { return(otherSlot != null && otherSlot.owner != owner && otherSlot.isInputSlot != isInputSlot && !hidden && !otherSlot.hidden && ((isInputSlot ? SlotValueHelper.AreCompatible(valueType, otherSlot.concreteValueType, otherSlot.IsConnectionTestable()) : SlotValueHelper.AreCompatible(otherSlot.valueType, concreteValueType, IsConnectionTestable())))); }
public override void ValidateNode() { base.ValidateNode(); var inputValueType = FindInputSlot <MaterialSlot>(InputSlotId).concreteValueType; var InputValueSize = SlotValueHelper.GetChannelCount(inputValueType); if (!ValidateMaskInput(InputValueSize)) { owner.AddValidationError(objectId, "Invalid mask for a Vector" + InputValueSize + " input.", ShaderCompilerMessageSeverity.Error); } }
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode) { ValidateChannelCount(); registry.ProvideFunction(GetFunctionName(), s => { int channelCount = SlotValueHelper.GetChannelCount(FindSlot <MaterialSlot>(InputSlotId).concreteValueType); s.AppendLine(GetFunctionPrototype("In", "Out")); using (s.BlockScope()) { if (channelMask == 0) { s.AppendLine("Out = 0;"); } else if (channelMask == -1) { s.AppendLine("Out = In;"); } else { bool red = (channelMask & 1) != 0; bool green = (channelMask & 2) != 0; bool blue = (channelMask & 4) != 0; bool alpha = (channelMask & 8) != 0; switch (channelCount) { case 1: s.AppendLine("Out = In.r;"); break; case 2: s.AppendLine(string.Format("Out = {0}2({1}, {2});", precision, red ? "In.r" : "0", green ? "In.g" : "0")); break; case 3: s.AppendLine(string.Format("Out = {0}3({1}, {2}, {3});", precision, red ? "In.r" : "0", green ? "In.g" : "0", blue ? "In.b" : "0")); break; case 4: s.AppendLine(string.Format("Out = {0}4({1}, {2}, {3}, {4});", precision, red ? "In.r" : "0", green ? "In.g" : "0", blue ? "In.b" : "0", alpha ? "In.a" : "0")); break; default: throw new ArgumentOutOfRangeException(); } } } }); }
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision) { var channelCount = SlotValueHelper.GetChannelCount(concreteValueType); string values = NodeUtils.FloatToShaderValue(value.x); if (channelCount == 1) { return(values); } for (var i = 1; i < channelCount; i++) { values += ", " + value[i]; } return(string.Format("{0}{1}({2})", precision, channelCount, values)); }
protected override string ConcreteSlotValueAsVariable() { var channelCount = (int)SlotValueHelper.GetMatrixDimension(concreteValueType); var values = ""; bool isFirst = true; for (var r = 0; r < channelCount; r++) { for (var c = 0; c < channelCount; c++) { if (!isFirst) values += ", "; isFirst = false; values += value.GetRow(r)[c]; } } return string.Format("$precision{0}x{0}({1})", channelCount, values); }
public static bool ImplicitConversionExists(ConcreteSlotValueType from, ConcreteSlotValueType to) { if (from == to) { return(true); } var fromCount = SlotValueHelper.GetChannelCount(from); var toCount = SlotValueHelper.GetChannelCount(to); if (toCount > 0 && fromCount > 0) { return(true); } return(false); }
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode) { var outputSlotType = FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(); var outputName = GetVariableNameForSlot(OutputSlotId); var inputValue = GetSlotValue(InputSlotId, generationMode); var inputValueType = FindInputSlot <MaterialSlot>(InputSlotId).concreteValueType; var InputValueSize = SlotValueHelper.GetChannelCount(inputValueType); if (!ValidateMaskInput(InputValueSize)) { sb.AppendLine(string.Format("{0} {1} = 0;", outputSlotType, outputName)); } else { sb.AppendLine("{0} {1} = {2}.{3};", outputSlotType, outputName, inputValue, convertedMask); } }
protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision) { var channelCount = (int)SlotValueHelper.GetMatrixDimension(concreteValueType); var values = ""; bool isFirst = true; for (var r = 0; r < channelCount; r++) { for (var c = 0; c < channelCount; c++) { if (!isFirst) { values += ", "; } isFirst = false; values += value.GetRow(r)[c]; } } return(string.Format("{0}{1}x{1}({2})", precision, channelCount, values)); }
void ValidateChannelCount() { var channelCount = SlotValueHelper.GetChannelCount(FindInputSlot <MaterialSlot>(InputSlotId).concreteValueType); if ((int)redChannel >= channelCount) { redChannel = TextureChannel.Red; } if ((int)greenChannel >= channelCount) { greenChannel = TextureChannel.Red; } if ((int)blueChannel >= channelCount) { blueChannel = TextureChannel.Red; } if ((int)alphaChannel >= channelCount) { alphaChannel = TextureChannel.Red; } }
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode) { var inputValue = GetSlotValue(InputSlotId, generationMode); var inputSlot = FindInputSlot <MaterialSlot>(InputSlotId); var numInputChannels = 0; if (inputSlot != null) { numInputChannels = SlotValueHelper.GetChannelCount(inputSlot.concreteValueType); if (numInputChannels > 4) { numInputChannels = 0; } } for (var i = 0; i < 4; i++) { var outputFormat = numInputChannels == 1 ? inputValue : string.Format("{0}[{1}]", inputValue, i); var outputValue = i >= numInputChannels ? "0" : outputFormat; sb.AppendLine(string.Format("$precision {0} = {1};", GetVariableNameForSlot(s_OutputSlots[i]), outputValue)); } }
// Internal validation // ------------------------------------------------- public override void EvaluateDynamicMaterialSlots() { var dynamicInputSlotsToCompare = DictionaryPool <DynamicValueMaterialSlot, ConcreteSlotValueType> .Get(); var skippedDynamicSlots = ListPool <DynamicValueMaterialSlot> .Get(); // iterate the input slots using (var tempSlots = PooledList <MaterialSlot> .Get()) { GetInputSlots(tempSlots); foreach (var inputSlot in tempSlots) { inputSlot.hasError = false; // if there is a connection var edges = owner.GetEdges(inputSlot.slotReference).ToList(); if (!edges.Any()) { if (inputSlot is DynamicValueMaterialSlot) { skippedDynamicSlots.Add(inputSlot as DynamicValueMaterialSlot); } 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 DynamicValueMaterialSlot) { dynamicInputSlotsToCompare.Add((DynamicValueMaterialSlot)inputSlot, outputConcreteType); continue; } } m_MultiplyType = GetMultiplyType(dynamicInputSlotsToCompare.Values); // Resolve dynamics depending on matrix/vector configuration switch (m_MultiplyType) { // If all matrix resolve as per dynamic matrix case MultiplyType.Matrix: var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicInputSlotsToCompare.Values); foreach (var dynamicKvP in dynamicInputSlotsToCompare) { dynamicKvP.Key.SetConcreteType(dynamicMatrixType); } foreach (var skippedSlot in skippedDynamicSlots) { skippedSlot.SetConcreteType(dynamicMatrixType); } break; // If mixed handle differently: // Iterate all slots and set their concretes based on their edges // Find matrix slot and convert its type to a vector type // Reiterate all slots and set non matrix slots to the vector type case MultiplyType.Mixed: foreach (var dynamicKvP in dynamicInputSlotsToCompare) { SetConcreteValueTypeFromEdge(dynamicKvP.Key); } MaterialSlot matrixSlot = GetMatrixSlot(); ConcreteSlotValueType vectorType = SlotValueHelper.ConvertMatrixToVectorType(matrixSlot.concreteValueType); foreach (var dynamicKvP in dynamicInputSlotsToCompare) { if (dynamicKvP.Key != matrixSlot) { dynamicKvP.Key.SetConcreteType(vectorType); } } foreach (var skippedSlot in skippedDynamicSlots) { skippedSlot.SetConcreteType(vectorType); } break; // If all vector resolve as per dynamic vector default: var dynamicVectorType = ConvertDynamicVectorInputTypeToConcrete(dynamicInputSlotsToCompare.Values); foreach (var dynamicKvP in dynamicInputSlotsToCompare) { dynamicKvP.Key.SetConcreteType(dynamicVectorType); } foreach (var skippedSlot in skippedDynamicSlots) { skippedSlot.SetConcreteType(dynamicVectorType); } break; } tempSlots.Clear(); GetInputSlots(tempSlots); bool inputError = tempSlots.Any(x => x.hasError); if (inputError) { owner.AddConcretizationError(guid, string.Format("Node {0} had input error", guid)); hasError = true; } // 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 tempSlots.Clear(); GetOutputSlots(tempSlots); foreach (var outputSlot in tempSlots) { outputSlot.hasError = false; if (inputError) { outputSlot.hasError = true; continue; } if (outputSlot is DynamicValueMaterialSlot) { // Apply similar logic to output slot switch (m_MultiplyType) { // As per dynamic matrix case MultiplyType.Matrix: var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicInputSlotsToCompare.Values); (outputSlot as DynamicValueMaterialSlot).SetConcreteType(dynamicMatrixType); break; // Mixed configuration // Find matrix slot and convert type to vector // Set output concrete to vector case MultiplyType.Mixed: MaterialSlot matrixSlot = GetMatrixSlot(); ConcreteSlotValueType vectorType = SlotValueHelper.ConvertMatrixToVectorType(matrixSlot.concreteValueType); (outputSlot as DynamicValueMaterialSlot).SetConcreteType(vectorType); break; // As per dynamic vector default: var dynamicVectorType = ConvertDynamicVectorInputTypeToConcrete(dynamicInputSlotsToCompare.Values); (outputSlot as DynamicValueMaterialSlot).SetConcreteType(dynamicVectorType); break; } continue; } } tempSlots.Clear(); GetOutputSlots(tempSlots); if (tempSlots.Any(x => x.hasError)) { owner.AddConcretizationError(guid, string.Format("Node {0} had output error", guid)); hasError = true; } } CalculateNodeHasError(); ListPool <DynamicValueMaterialSlot> .Release(skippedDynamicSlots); DictionaryPool <DynamicValueMaterialSlot, ConcreteSlotValueType> .Release(dynamicInputSlotsToCompare); }
// Internal validation // ------------------------------------------------- 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 <DynamicValueMaterialSlot, ConcreteSlotValueType> .Get(); var skippedDynamicSlots = ListPool <DynamicValueMaterialSlot> .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 DynamicValueMaterialSlot) { skippedDynamicSlots.Add(inputSlot as DynamicValueMaterialSlot); } 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 DynamicValueMaterialSlot) { dynamicInputSlotsToCompare.Add((DynamicValueMaterialSlot)inputSlot, outputConcreteType); continue; } // if we have a standard connection... just check the types work! if (!ImplicitConversionExists(outputConcreteType, inputSlot.concreteValueType)) { inputSlot.hasError = true; } } m_MultiplyType = GetMultiplyType(dynamicInputSlotsToCompare.Values); // Resolve dynamics depending on matrix/vector configuration switch (m_MultiplyType) { // If all matrix resolve as per dynamic matrix case MultiplyType.Matrix: var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicInputSlotsToCompare.Values); foreach (var dynamicKvP in dynamicInputSlotsToCompare) { dynamicKvP.Key.SetConcreteType(dynamicMatrixType); } foreach (var skippedSlot in skippedDynamicSlots) { skippedSlot.SetConcreteType(dynamicMatrixType); } break; // If mixed handle differently: // Iterate all slots and set their concretes based on their edges // Find matrix slot and convert its type to a vector type // Reiterate all slots and set non matrix slots to the vector type case MultiplyType.Mixed: foreach (var dynamicKvP in dynamicInputSlotsToCompare) { SetConcreteValueTypeFromEdge(dynamicKvP.Key); } MaterialSlot matrixSlot = GetMatrixSlot(); ConcreteSlotValueType vectorType = SlotValueHelper.ConvertMatrixToVectorType(matrixSlot.concreteValueType); foreach (var dynamicKvP in dynamicInputSlotsToCompare) { if (dynamicKvP.Key != matrixSlot) { dynamicKvP.Key.SetConcreteType(vectorType); } } foreach (var skippedSlot in skippedDynamicSlots) { skippedSlot.SetConcreteType(vectorType); } break; // If all vector resolve as per dynamic vector default: var dynamicVectorType = ConvertDynamicInputTypeToConcrete(dynamicInputSlotsToCompare.Values); foreach (var dynamicKvP in dynamicInputSlotsToCompare) { dynamicKvP.Key.SetConcreteType(dynamicVectorType); } foreach (var skippedSlot in skippedDynamicSlots) { skippedSlot.SetConcreteType(dynamicVectorType); } break; } 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 DynamicValueMaterialSlot) { // Apply similar logic to output slot switch (m_MultiplyType) { // As per dynamic matrix case MultiplyType.Matrix: var dynamicMatrixType = ConvertDynamicMatrixInputTypeToConcrete(dynamicInputSlotsToCompare.Values); (outputSlot as DynamicValueMaterialSlot).SetConcreteType(dynamicMatrixType); break; // Mixed configuration // Find matrix slot and convert type to vector // Set output concrete to vector case MultiplyType.Mixed: MaterialSlot matrixSlot = GetMatrixSlot(); ConcreteSlotValueType vectorType = SlotValueHelper.ConvertMatrixToVectorType(matrixSlot.concreteValueType); (outputSlot as DynamicValueMaterialSlot).SetConcreteType(vectorType); break; // As per dynamic vector default: var dynamicVectorType = ConvertDynamicInputTypeToConcrete(dynamicInputSlotsToCompare.Values); (outputSlot as DynamicValueMaterialSlot).SetConcreteType(dynamicVectorType); break; } continue; } } isInError |= inputError; s_TempSlots.Clear(); GetOutputSlots(s_TempSlots); isInError |= s_TempSlots.Any(x => x.hasError); isInError |= CalculateNodeHasError(); hasError = isInError; if (!hasError) { ++version; } ListPool <DynamicValueMaterialSlot> .Release(skippedDynamicSlots); DictionaryPool <DynamicValueMaterialSlot, ConcreteSlotValueType> .Release(dynamicInputSlotsToCompare); }
public void GenerateNodeCode(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode) { var inputValue = GetSlotValue(InputSlotId, generationMode); var inputSlot = FindInputSlot <MaterialSlot>(InputSlotId); var numInputRows = 0; bool useIndentity = false; if (inputSlot != null) { numInputRows = SlotValueHelper.GetMatrixDimension(inputSlot.concreteValueType); if (numInputRows > 4) { numInputRows = 0; } if (!owner.GetEdges(inputSlot.slotReference).Any()) { numInputRows = 0; useIndentity = true; } } int concreteRowCount = useIndentity ? 2 : numInputRows; for (var r = 0; r < 4; r++) { string outputValue; if (r >= numInputRows) { outputValue = string.Format("{0}{1}(", precision, concreteRowCount); for (int c = 0; c < concreteRowCount; c++) { if (c != 0) { outputValue += ", "; } outputValue += Matrix4x4.identity.GetRow(r)[c]; } outputValue += ")"; } else { switch (m_Axis) { case MatrixAxis.Column: outputValue = string.Format("{0}{1}(", precision, numInputRows); for (int c = 0; c < numInputRows; c++) { if (c != 0) { outputValue += ", "; } outputValue += string.Format("{0}[{1}].{2}", inputValue, c, s_ComponentList[r]); } outputValue += ")"; break; default: outputValue = string.Format("{0}[{1}]", inputValue, r); break; } } visitor.AddShaderChunk(string.Format("{0}{1} {2} = {3};", precision, concreteRowCount, GetVariableNameForSlot(s_OutputSlots[r]), outputValue), true); } }
public override void ValidateNode() { var isInError = false; var errorMessage = k_validationErrorMessage; 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) { inputSlot.hasError = false; // 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(ref errorMessage); hasError = isInError; if (isInError) { ((GraphData)owner).AddValidationError(tempId, errorMessage); } else { ++version; } ListPool <DynamicVectorMaterialSlot> .Release(skippedDynamicSlots); DictionaryPool <DynamicVectorMaterialSlot, ConcreteSlotValueType> .Release(dynamicInputSlotsToCompare); ListPool <DynamicMatrixMaterialSlot> .Release(skippedDynamicMatrixSlots); DictionaryPool <DynamicMatrixMaterialSlot, ConcreteSlotValueType> .Release(dynamicMatrixInputSlotsToCompare); }
public override void EvaluateDynamicMaterialSlots(List <MaterialSlot> inputSlots, List <MaterialSlot> outputSlots) { 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 { foreach (var inputSlot in inputSlots) { inputSlot.hasError = false; // 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 = outputSlotRef.node; 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; } } // 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); } bool inputError = inputSlots.Any(x => x.hasError); if (inputError) { owner.AddConcretizationError(objectId, string.Format("Node {0} had input error", objectId)); hasError = true; } // 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 foreach (var outputSlot in outputSlots) { 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; } } if (outputSlots.Any(x => x.hasError)) { owner.AddConcretizationError(objectId, string.Format("Node {0} had output error", objectId)); hasError = true; } } CalculateNodeHasError(); ListPool <DynamicVectorMaterialSlot> .Release(skippedDynamicSlots); DictionaryPool <DynamicVectorMaterialSlot, ConcreteSlotValueType> .Release(dynamicInputSlotsToCompare); ListPool <DynamicMatrixMaterialSlot> .Release(skippedDynamicMatrixSlots); DictionaryPool <DynamicMatrixMaterialSlot, ConcreteSlotValueType> .Release(dynamicMatrixInputSlotsToCompare); }