using System; using System.Linq; using UnityEngine; using UnityEditor.Graphing; namespace UnityEditor.ShaderGraph { [Title("Input", "Property")] public class PropertyNode : AbstractMaterialNode, IGeneratesBodyCode, IOnAssetEnabled { private Guid m_PropertyGuid; [SerializeField] private string m_PropertyGuidSerialized; public const int OutputSlotId = 0; public PropertyNode() { name = "Property"; UpdateNodeAfterDeserialization(); } public override string documentationURL { get { return "https://github.com/Unity-Technologies/ShaderGraph/wiki/Property-Node"; } } private void UpdateNode() { var graph = owner as AbstractMaterialGraph; var property = graph.properties.FirstOrDefault(x => x.guid == propertyGuid); if (property == null) return; if (property is Vector1ShaderProperty) { AddSlot(new Vector1MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, 0)); RemoveSlotsNameNotMatching(new[] {OutputSlotId}); } else if (property is Vector2ShaderProperty) { AddSlot(new Vector2MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, Vector4.zero)); RemoveSlotsNameNotMatching(new[] {OutputSlotId}); } else if (property is Vector3ShaderProperty) { AddSlot(new Vector3MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, Vector4.zero)); RemoveSlotsNameNotMatching(new[] {OutputSlotId}); } else if (property is Vector4ShaderProperty) { AddSlot(new Vector4MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, Vector4.zero)); RemoveSlotsNameNotMatching(new[] {OutputSlotId}); } else if (property is ColorShaderProperty) { AddSlot(new Vector4MaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, Vector4.zero)); RemoveSlotsNameNotMatching(new[] {OutputSlotId}); } else if (property is TextureShaderProperty) { AddSlot(new Texture2DMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output)); RemoveSlotsNameNotMatching(new[] {OutputSlotId}); } else if (property is Texture2DArrayShaderProperty) { AddSlot(new Texture2DArrayMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output)); RemoveSlotsNameNotMatching(new[] {OutputSlotId}); } else if (property is Texture3DShaderProperty) { AddSlot(new Texture3DMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output)); RemoveSlotsNameNotMatching(new[] {OutputSlotId}); } else if (property is CubemapShaderProperty) { AddSlot(new CubemapMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output)); RemoveSlotsNameNotMatching(new[] { OutputSlotId }); } else if (property is BooleanShaderProperty) { AddSlot(new BooleanMaterialSlot(OutputSlotId, property.displayName, "Out", SlotType.Output, false)); RemoveSlotsNameNotMatching(new[] { OutputSlotId }); } } public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) { var graph = owner as AbstractMaterialGraph; var property = graph.properties.FirstOrDefault(x => x.guid == propertyGuid); if (property == null) return; if (property is Vector1ShaderProperty) { var result = string.Format("{0} {1} = {2};" , precision , GetVariableNameForSlot(OutputSlotId) , property.referenceName); visitor.AddShaderChunk(result, true); } else if (property is Vector2ShaderProperty) { var result = string.Format("{0}2 {1} = {2};" , precision , GetVariableNameForSlot(OutputSlotId) , property.referenceName); visitor.AddShaderChunk(result, true); } else if (property is Vector3ShaderProperty) { var result = string.Format("{0}3 {1} = {2};" , precision , GetVariableNameForSlot(OutputSlotId) , property.referenceName); visitor.AddShaderChunk(result, true); } else if (property is Vector4ShaderProperty) { var result = string.Format("{0}4 {1} = {2};" , precision , GetVariableNameForSlot(OutputSlotId) , property.referenceName); visitor.AddShaderChunk(result, true); } else if (property is ColorShaderProperty) { var result = string.Format("{0}4 {1} = {2};" , precision , GetVariableNameForSlot(OutputSlotId) , property.referenceName); visitor.AddShaderChunk(result, true); } else if (property is BooleanShaderProperty) { var result = string.Format("{0} {1} = {2};" , precision , GetVariableNameForSlot(OutputSlotId) , property.referenceName); visitor.AddShaderChunk(result, true); } } public Guid propertyGuid { get { return m_PropertyGuid; } set { if (m_PropertyGuid == value) return; var graph = owner as AbstractMaterialGraph; var property = graph.properties.FirstOrDefault(x => x.guid == value); if (property == null) return; m_PropertyGuid = value; UpdateNode(); Dirty(ModificationScope.Topological); } } public override string GetVariableNameForSlot(int slotId) { var graph = owner as AbstractMaterialGraph; var property = graph.properties.FirstOrDefault(x => x.guid == propertyGuid); if (!(property is TextureShaderProperty) && !(property is Texture2DArrayShaderProperty) && !(property is Texture3DShaderProperty) && !(property is CubemapShaderProperty)) return base.GetVariableNameForSlot(slotId); return property.referenceName; } protected override bool CalculateNodeHasError() { var graph = owner as AbstractMaterialGraph; if (!graph.properties.Any(x => x.guid == propertyGuid)) return true; return false; } public override void OnBeforeSerialize() { base.OnBeforeSerialize(); m_PropertyGuidSerialized = m_PropertyGuid.ToString(); } public override void OnAfterDeserialize() { base.OnAfterDeserialize(); if (!string.IsNullOrEmpty(m_PropertyGuidSerialized)) m_PropertyGuid = new Guid(m_PropertyGuidSerialized); } public void OnEnable() { UpdateNode(); } } }