void UpdatePorts() { switch (keyword.keywordType) { case KeywordType.Boolean: { // Boolean type has preset slots AddSlot(new DynamicVectorMaterialSlot(OutputSlotId, "Out", "Out", SlotType.Output, Vector4.zero)); AddSlot(new DynamicVectorMaterialSlot(1, "On", "On", SlotType.Input, Vector4.zero)); AddSlot(new DynamicVectorMaterialSlot(2, "Off", "Off", SlotType.Input, Vector4.zero)); RemoveSlotsNameNotMatching(new int[] { 0, 1, 2 }); break; } case KeywordType.Enum: { // Get slots List <MaterialSlot> inputSlots = new List <MaterialSlot>(); GetInputSlots(inputSlots); // Store the edges Dictionary <MaterialSlot, List <IEdge> > edgeDict = new Dictionary <MaterialSlot, List <IEdge> >(); foreach (MaterialSlot slot in inputSlots) { edgeDict.Add(slot, (List <IEdge>)slot.owner.owner.GetEdges(slot.slotReference)); } // Remove old slots for (int i = 0; i < inputSlots.Count; i++) { RemoveSlot(inputSlots[i].id); } // Add output slot AddSlot(new DynamicVectorMaterialSlot(OutputSlotId, "Out", "Out", SlotType.Output, Vector4.zero)); // Add input slots int[] slotIds = new int[keyword.entries.Count + 1]; slotIds[keyword.entries.Count] = OutputSlotId; for (int i = 0; i < keyword.entries.Count; i++) { // Get slot based on entry id MaterialSlot slot = inputSlots.Where(x => x.id == keyword.entries[i].id && x.RawDisplayName() == keyword.entries[i].displayName && x.shaderOutputName == keyword.entries[i].referenceName).FirstOrDefault(); // If slot doesnt exist its new so create it if (slot == null) { slot = new DynamicVectorMaterialSlot(keyword.entries[i].id, keyword.entries[i].displayName, keyword.entries[i].referenceName, SlotType.Input, Vector4.zero); } AddSlot(slot); slotIds[i] = keyword.entries[i].id; } RemoveSlotsNameNotMatching(slotIds); // Reconnect the edges foreach (KeyValuePair <MaterialSlot, List <IEdge> > entry in edgeDict) { foreach (IEdge edge in entry.Value) { owner.Connect(edge.outputSlot, edge.inputSlot); } } break; } } ValidateNode(); }
public static bool RequiresVertexSkinning(this MaterialSlot slot) { var mayRequireVertexSkinning = slot as IMayRequireVertexSkinning; return(mayRequireVertexSkinning != null && mayRequireVertexSkinning.RequiresVertexSkinning()); }
public static bool RequiresDepthTexture(this MaterialSlot slot) { var mayRequireDepthTexture = slot as IMayRequireDepthTexture; return(mayRequireDepthTexture != null && mayRequireDepthTexture.RequiresDepthTexture()); }
public bool Equals(MaterialSlot other) { return(m_Id == other.m_Id && owner == other.owner); }
public bool IsCompatibleStageWith(MaterialSlot otherSlot) { var candidateStage = otherSlot.stageCapability; return(stageCapability == ShaderStageCapability.All || candidateStage == stageCapability); }
public sealed override void UpdateNodeAfterDeserialization() { var method = GetFunctionToConvert(); if (method == null) { throw new ArgumentException("Mapped method is null on node" + this); } if (method.ReturnType != typeof(string)) { throw new ArgumentException("Mapped function should return string"); } // validate no duplicates var slotAtributes = method.GetParameters().Select(GetSlotAttribute).ToList(); if (slotAtributes.Any(x => x == null)) { throw new ArgumentException("Missing SlotAttribute on " + method.Name); } if (slotAtributes.GroupBy(x => x.slotId).Any(x => x.Count() > 1)) { throw new ArgumentException("Duplicate SlotAttribute on " + method.Name); } List <MaterialSlot> slots = new List <MaterialSlot>(); foreach (var par in method.GetParameters()) { var attribute = GetSlotAttribute(par); var name = GraphUtil.ConvertCamelCase(par.Name, true); MaterialSlot s; if (attribute.binding == Binding.None && !par.IsOut && par.ParameterType == typeof(Color)) { s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden); } else if (attribute.binding == Binding.None && !par.IsOut && par.ParameterType == typeof(ColorRGBA)) { s = new ColorRGBAMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, stageCapability: attribute.stageCapability, hidden: attribute.hidden); } else if (attribute.binding == Binding.None && !par.IsOut && par.ParameterType == typeof(ColorRGB)) { s = new ColorRGBMaterialSlot(attribute.slotId, name, par.Name, SlotType.Input, attribute.defaultValue ?? Vector4.zero, ColorMode.Default, stageCapability: attribute.stageCapability, hidden: attribute.hidden); } else if (attribute.binding == Binding.None || par.IsOut) { s = MaterialSlot.CreateMaterialSlot( ConvertTypeToSlotValueType(par), attribute.slotId, name, par.Name, par.IsOut ? SlotType.Output : SlotType.Input, attribute.defaultValue ?? Vector4.zero, shaderStageCapability: attribute.stageCapability, hidden: attribute.hidden); } else { s = CreateBoundSlot(attribute.binding, attribute.slotId, name, par.Name, attribute.stageCapability, attribute.hidden); } slots.Add(s); m_Slots.Add(attribute); } foreach (var slot in slots) { AddSlot(slot); } RemoveSlotsNameNotMatching(slots.Select(x => x.id)); }
public void ValidateGraph() { var propertyNodes = GetNodes <PropertyNode>().Where(n => !m_Properties.Any(p => p.guid == n.propertyGuid)).ToArray(); foreach (var pNode in propertyNodes) { ReplacePropertyNodeWithConcreteNodeNoValidate(pNode); } messageManager?.ClearAllFromProvider(this); //First validate edges, remove any //orphans. This can happen if a user //manually modifies serialized data //of if they delete a node in the inspector //debug view. foreach (var edge in edges.ToArray()) { var outputNode = GetNodeFromGuid(edge.outputSlot.nodeGuid); var inputNode = GetNodeFromGuid(edge.inputSlot.nodeGuid); MaterialSlot outputSlot = null; MaterialSlot inputSlot = null; if (outputNode != null && inputNode != null) { outputSlot = outputNode.FindOutputSlot <MaterialSlot>(edge.outputSlot.slotId); inputSlot = inputNode.FindInputSlot <MaterialSlot>(edge.inputSlot.slotId); } if (outputNode == null || inputNode == null || outputSlot == null || inputSlot == null || !outputSlot.IsCompatibleWith(inputSlot)) { //orphaned edge RemoveEdgeNoValidate(edge); } } var temporaryMarks = IndexSetPool.Get(); var permanentMarks = IndexSetPool.Get(); var slots = ListPool <MaterialSlot> .Get(); // Make sure we process a node's children before the node itself. var stack = StackPool <AbstractMaterialNode> .Get(); foreach (var node in GetNodes <AbstractMaterialNode>()) { stack.Push(node); } while (stack.Count > 0) { var node = stack.Pop(); if (permanentMarks.Contains(node.tempId.index)) { continue; } if (temporaryMarks.Contains(node.tempId.index)) { node.ValidateNode(); permanentMarks.Add(node.tempId.index); } else { temporaryMarks.Add(node.tempId.index); stack.Push(node); node.GetInputSlots(slots); foreach (var inputSlot in slots) { var nodeEdges = GetEdges(inputSlot.slotReference); foreach (var edge in nodeEdges) { var fromSocketRef = edge.outputSlot; var childNode = GetNodeFromGuid(fromSocketRef.nodeGuid); if (childNode != null) { stack.Push(childNode); } } } slots.Clear(); } } StackPool <AbstractMaterialNode> .Release(stack); ListPool <MaterialSlot> .Release(slots); IndexSetPool.Release(temporaryMarks); IndexSetPool.Release(permanentMarks); foreach (var edge in m_AddedEdges.ToList()) { if (!ContainsNodeGuid(edge.outputSlot.nodeGuid) || !ContainsNodeGuid(edge.inputSlot.nodeGuid)) { Debug.LogWarningFormat("Added edge is invalid: {0} -> {1}\n{2}", edge.outputSlot.nodeGuid, edge.inputSlot.nodeGuid, Environment.StackTrace); m_AddedEdges.Remove(edge); } } }
public static bool RequiresScreenPosition(this MaterialSlot slot, ShaderStageCapability stageCapability = ShaderStageCapability.All) { var mayRequireScreenPosition = slot as IMayRequireScreenPosition; return(mayRequireScreenPosition != null && mayRequireScreenPosition.RequiresScreenPosition(stageCapability)); }
public override void CopyValuesFrom(MaterialSlot foundSlot) { // This is a funky slot, that doesn't directly hold a value. }
public static bool RequiresPixelPosition(this MaterialSlot slot, ShaderStageCapability stageCapability = ShaderStageCapability.All) { var mayRequirePixelPosition = slot as IMayRequirePixelPosition; return(mayRequirePixelPosition?.RequiresPixelPosition(stageCapability) ?? false); }
public virtual void UpdateSlots() { var validNames = new List <int>(); if (subGraphData == null) { return; } var props = subGraphData.inputs; foreach (var prop in props) { var propType = prop.propertyType; SlotValueType slotType; switch (propType) { case PropertyType.Color: slotType = SlotValueType.Vector4; break; case PropertyType.Texture2D: slotType = SlotValueType.Texture2D; break; case PropertyType.Texture2DArray: slotType = SlotValueType.Texture2DArray; break; case PropertyType.Texture3D: slotType = SlotValueType.Texture3D; break; case PropertyType.Cubemap: slotType = SlotValueType.Cubemap; break; case PropertyType.Gradient: slotType = SlotValueType.Gradient; break; case PropertyType.Vector1: slotType = SlotValueType.Vector1; break; case PropertyType.Vector2: slotType = SlotValueType.Vector2; break; case PropertyType.Vector3: slotType = SlotValueType.Vector3; break; case PropertyType.Vector4: slotType = SlotValueType.Vector4; break; case PropertyType.Boolean: slotType = SlotValueType.Boolean; break; case PropertyType.Matrix2: slotType = SlotValueType.Matrix2; break; case PropertyType.Matrix3: slotType = SlotValueType.Matrix3; break; case PropertyType.Matrix4: slotType = SlotValueType.Matrix4; break; case PropertyType.SamplerState: slotType = SlotValueType.SamplerState; break; default: throw new ArgumentOutOfRangeException(); } var propertyString = prop.guid.ToString(); var propertyIndex = m_PropertyGuids.IndexOf(propertyString); if (propertyIndex < 0) { propertyIndex = m_PropertyGuids.Count; m_PropertyGuids.Add(propertyString); m_PropertyIds.Add(prop.guid.GetHashCode()); } var id = m_PropertyIds[propertyIndex]; MaterialSlot slot = MaterialSlot.CreateMaterialSlot(slotType, id, prop.displayName, prop.referenceName, SlotType.Input, prop.defaultValue, ShaderStageCapability.All); // copy default for texture for niceness if (slotType == SlotValueType.Texture2D && propType == PropertyType.Texture2D) { var tSlot = slot as Texture2DInputMaterialSlot; var tProp = prop as TextureShaderProperty; if (tSlot != null && tProp != null) { tSlot.texture = tProp.value.texture; } } // copy default for texture array for niceness else if (slotType == SlotValueType.Texture2DArray && propType == PropertyType.Texture2DArray) { var tSlot = slot as Texture2DArrayInputMaterialSlot; var tProp = prop as Texture2DArrayShaderProperty; if (tSlot != null && tProp != null) { tSlot.textureArray = tProp.value.textureArray; } } // copy default for texture 3d for niceness else if (slotType == SlotValueType.Texture3D && propType == PropertyType.Texture3D) { var tSlot = slot as Texture3DInputMaterialSlot; var tProp = prop as Texture3DShaderProperty; if (tSlot != null && tProp != null) { tSlot.texture = tProp.value.texture; } } // copy default for cubemap for niceness else if (slotType == SlotValueType.Cubemap && propType == PropertyType.Cubemap) { var tSlot = slot as CubemapInputMaterialSlot; var tProp = prop as CubemapShaderProperty; if (tSlot != null && tProp != null) { tSlot.cubemap = tProp.value.cubemap; } } // copy default for gradient for niceness else if (slotType == SlotValueType.Gradient && propType == PropertyType.Gradient) { var tSlot = slot as GradientInputMaterialSlot; var tProp = prop as GradientShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } AddSlot(slot); validNames.Add(id); } var outputStage = subGraphData.effectiveShaderStage; foreach (var slot in subGraphData.outputs) { AddSlot(MaterialSlot.CreateMaterialSlot(slot.valueType, slot.id, slot.RawDisplayName(), slot.shaderOutputName, SlotType.Output, Vector4.zero, outputStage)); validNames.Add(slot.id); } RemoveSlotsNameNotMatching(validNames, true); }
public static NeededCoordinateSpace RequiresBitangent(this MaterialSlot slot) { var mayRequireBitangent = slot as IMayRequireBitangent; return(mayRequireBitangent != null?mayRequireBitangent.RequiresBitangent() : NeededCoordinateSpace.None); }
void UpdatePorts() { switch (keyword.keywordType) { case KeywordType.Boolean: { // Boolean type has preset slots PooledList <MaterialSlot> temp = PooledList <MaterialSlot> .Get(); GetInputSlots(temp); if (temp.Any()) { temp.Dispose(); break; } else { temp.Dispose(); } AddSlot(new DynamicVectorMaterialSlot(OutputSlotId, "Out", "Out", SlotType.Output, Vector4.zero)); AddSlot(new DynamicVectorMaterialSlot(1, "On", "On", SlotType.Input, Vector4.zero)); AddSlot(new DynamicVectorMaterialSlot(2, "Off", "Off", SlotType.Input, Vector4.zero)); RemoveSlotsNameNotMatching(new int[] { 0, 1, 2 }); break; } case KeywordType.Enum: using (var inputSlots = PooledList <MaterialSlot> .Get()) using (var slotIDs = PooledList <int> .Get()) { // Get slots GetInputSlots(inputSlots); // Add output slot AddSlot(new DynamicVectorMaterialSlot(OutputSlotId, "Out", "Out", SlotType.Output, Vector4.zero)); slotIDs.Add(OutputSlotId); // Add input slots for (int i = 0; i < keyword.entries.Count; i++) { // Get slot based on entry id MaterialSlot slot = inputSlots.Find(x => x.id == keyword.entries[i].id && x.RawDisplayName() == keyword.entries[i].displayName && x.shaderOutputName == keyword.entries[i].referenceName); // If slot doesn't exist, it's new so create it if (slot == null) { slot = new DynamicVectorMaterialSlot(keyword.entries[i].id, keyword.entries[i].displayName, keyword.entries[i].referenceName, SlotType.Input, Vector4.zero); } AddSlot(slot); slotIDs.Add(keyword.entries[i].id); } RemoveSlotsNameNotMatching(slotIDs); bool orderChanged = SetSlotOrder(slotIDs); if (orderChanged) { // unfortunately there is no way to get the view to update slot order other than Topological Dirty(ModificationScope.Topological); } break; } } ValidateNode(); }
// 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 = 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 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(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 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(objectId, string.Format("Node {0} had output error", objectId)); hasError = true; } } CalculateNodeHasError(); ListPool <DynamicValueMaterialSlot> .Release(skippedDynamicSlots); DictionaryPool <DynamicValueMaterialSlot, ConcreteSlotValueType> .Release(dynamicInputSlotsToCompare); }
// Internal validation // ------------------------------------------------- public override void ValidateNode() { var isInError = false; var errorMessage = k_validationErrorMessage; // 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(); } } 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(ref errorMessage); hasError = isInError; if (isInError) { ((AbstractMaterialGraph)owner).AddValidationError(tempId, errorMessage); } else { ++version; } ListPool <DynamicValueMaterialSlot> .Release(skippedDynamicSlots); DictionaryPool <DynamicValueMaterialSlot, ConcreteSlotValueType> .Release(dynamicInputSlotsToCompare); }
public override void CopyValuesFrom(MaterialSlot foundSlot) { var slot = foundSlot as Vector1MaterialSlot; if (slot != null) value = slot.value; }
bool Equals(MaterialSlot other) { return(m_Id == other.m_Id && owner.guid.Equals(other.owner.guid)); }
public override void CopyDefaultValue(MaterialSlot other) { }
public override void CopyValuesFrom(MaterialSlot foundSlot) { var slot = foundSlot as DynamicMatrixMaterialSlot; if (slot != null) value = slot.value; }
private string GetParamTypeName(MaterialSlot slot) { return(NodeUtils.ConvertConcreteSlotValueTypeToString(precision, slot.concreteValueType)); }
public virtual void UpdateSlots() { var validNames = new List <int>(); if (asset == null) { return; } var props = asset.inputs; foreach (var prop in props) { SlotValueType valueType = prop.concreteShaderValueType.ToSlotValueType(); var propertyString = prop.guid.ToString(); var propertyIndex = m_PropertyGuids.IndexOf(propertyString); if (propertyIndex < 0) { propertyIndex = m_PropertyGuids.Count; m_PropertyGuids.Add(propertyString); m_PropertyIds.Add(prop.guid.GetHashCode()); } var id = m_PropertyIds[propertyIndex]; MaterialSlot slot = MaterialSlot.CreateMaterialSlot(valueType, id, prop.displayName, prop.referenceName, SlotType.Input, Vector4.zero, ShaderStageCapability.All); // Copy defaults switch (prop.concreteShaderValueType) { case ConcreteSlotValueType.Matrix4: { var tSlot = slot as Matrix4MaterialSlot; var tProp = prop as Matrix4ShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } break; case ConcreteSlotValueType.Matrix3: { var tSlot = slot as Matrix3MaterialSlot; var tProp = prop as Matrix3ShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } break; case ConcreteSlotValueType.Matrix2: { var tSlot = slot as Matrix2MaterialSlot; var tProp = prop as Matrix2ShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } break; case ConcreteSlotValueType.Texture2D: { var tSlot = slot as Texture2DInputMaterialSlot; var tProp = prop as Texture2DShaderProperty; if (tSlot != null && tProp != null) { tSlot.texture = tProp.value.texture; } } break; case ConcreteSlotValueType.Texture2DArray: { var tSlot = slot as Texture2DArrayInputMaterialSlot; var tProp = prop as Texture2DArrayShaderProperty; if (tSlot != null && tProp != null) { tSlot.textureArray = tProp.value.textureArray; } } break; case ConcreteSlotValueType.Texture3D: { var tSlot = slot as Texture3DInputMaterialSlot; var tProp = prop as Texture3DShaderProperty; if (tSlot != null && tProp != null) { tSlot.texture = tProp.value.texture; } } break; case ConcreteSlotValueType.Cubemap: { var tSlot = slot as CubemapInputMaterialSlot; var tProp = prop as CubemapShaderProperty; if (tSlot != null && tProp != null) { tSlot.cubemap = tProp.value.cubemap; } } break; case ConcreteSlotValueType.Gradient: { var tSlot = slot as GradientInputMaterialSlot; var tProp = prop as GradientShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } break; case ConcreteSlotValueType.Vector4: { var tSlot = slot as Vector4MaterialSlot; var vector4Prop = prop as Vector4ShaderProperty; var colorProp = prop as ColorShaderProperty; if (tSlot != null && vector4Prop != null) { tSlot.value = vector4Prop.value; } else if (tSlot != null && colorProp != null) { tSlot.value = colorProp.value; } } break; case ConcreteSlotValueType.Vector3: { var tSlot = slot as Vector3MaterialSlot; var tProp = prop as Vector3ShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } break; case ConcreteSlotValueType.Vector2: { var tSlot = slot as Vector2MaterialSlot; var tProp = prop as Vector2ShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } break; case ConcreteSlotValueType.Vector1: { var tSlot = slot as Vector1MaterialSlot; var tProp = prop as Vector1ShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } break; case ConcreteSlotValueType.Boolean: { var tSlot = slot as BooleanMaterialSlot; var tProp = prop as BooleanShaderProperty; if (tSlot != null && tProp != null) { tSlot.value = tProp.value; } } break; } AddSlot(slot); validNames.Add(id); } var outputStage = asset.effectiveShaderStage; foreach (var slot in asset.outputs) { var newSlot = MaterialSlot.CreateMaterialSlot(slot.valueType, slot.id, slot.RawDisplayName(), slot.shaderOutputName, SlotType.Output, Vector4.zero, outputStage, slot.hidden); AddSlot(newSlot); validNames.Add(slot.id); } RemoveSlotsNameNotMatching(validNames, true); }
public static bool RequiresScreenPosition(this MaterialSlot slot) { var mayRequireScreenPosition = slot as IMayRequireScreenPosition; return(mayRequireScreenPosition != null && mayRequireScreenPosition.RequiresScreenPosition()); }
public override void CopyValuesFrom(MaterialSlot foundSlot) { }
public virtual void UpdateSlots() { var validNames = new List <int>(); if (referencedGraph == null) { RemoveSlotsNameNotMatching(validNames); return; } var props = referencedGraph.properties; foreach (var prop in props) { var propType = prop.propertyType; SlotValueType slotType; switch (propType) { case PropertyType.Color: slotType = SlotValueType.Vector4; break; case PropertyType.Texture: slotType = SlotValueType.Texture2D; break; case PropertyType.Cubemap: slotType = SlotValueType.Cubemap; break; case PropertyType.Vector1: slotType = SlotValueType.Vector1; break; case PropertyType.Vector2: slotType = SlotValueType.Vector2; break; case PropertyType.Vector3: slotType = SlotValueType.Vector3; break; case PropertyType.Vector4: slotType = SlotValueType.Vector4; break; case PropertyType.Matrix2: slotType = SlotValueType.Matrix2; break; case PropertyType.Matrix3: slotType = SlotValueType.Matrix3; break; case PropertyType.Matrix4: slotType = SlotValueType.Matrix4; break; default: throw new ArgumentOutOfRangeException(); } var id = prop.guid.GetHashCode(); MaterialSlot slot = MaterialSlot.CreateMaterialSlot(slotType, id, prop.displayName, prop.referenceName, SlotType.Input, prop.defaultValue); // copy default for texture for niceness if (slotType == SlotValueType.Texture2D && propType == PropertyType.Texture) { var tSlot = slot as Texture2DInputMaterialSlot; var tProp = prop as TextureShaderProperty; if (tSlot != null && tProp != null) { tSlot.texture = tProp.value.texture; } } // copy default for cubemap for niceness else if (slotType == SlotValueType.Cubemap && propType == PropertyType.Cubemap) { var tSlot = slot as CubemapInputMaterialSlot; var tProp = prop as CubemapShaderProperty; if (tSlot != null && tProp != null) { tSlot.cubemap = tProp.value.cubemap; } } AddSlot(slot); validNames.Add(id); } var subGraphOutputNode = outputNode; if (outputNode != null) { foreach (var slot in NodeExtensions.GetInputSlots <MaterialSlot>(subGraphOutputNode)) { AddSlot(MaterialSlot.CreateMaterialSlot(slot.valueType, slot.id, slot.RawDisplayName(), slot.shaderOutputName, SlotType.Output, Vector4.zero)); validNames.Add(slot.id); } } RemoveSlotsNameNotMatching(validNames); }
public abstract void CopyValuesFrom(MaterialSlot foundSlot);
public static bool RequiresFaceSign(this MaterialSlot slot) { var mayRequireFaceSign = slot as IMayRequireFaceSign; return(mayRequireFaceSign != null && mayRequireFaceSign.RequiresFaceSign()); }