using System; using System.Collections.Generic; using UnityEditor.Graphing; using UnityEditor.ShaderGraph.Drawing.Controls; using UnityEditor.ShaderGraph.Internal; using UnityEngine; namespace UnityEditor.ShaderGraph { [Title("Channel", "Flip")] class FlipNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction { public FlipNode() { name = "Flip"; UpdateNodeAfterDeserialization(); } const int InputSlotId = 0; const int OutputSlotId = 1; const string kInputSlotName = "In"; const string kOutputSlotName = "Out"; public override bool hasPreview { get { return true; } } string GetFunctionName() { // NOTE: it's important we use the $precision generic form of the slot type in the name here return $"Unity_Flip_{FindSlot(InputSlotId).concreteValueType.ToShaderString()}"; } public sealed override void UpdateNodeAfterDeserialization() { AddSlot(new DynamicVectorMaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, Vector4.zero)); AddSlot(new DynamicVectorMaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero)); RemoveSlotsNameNotMatching(new[] { InputSlotId, OutputSlotId }); } int channelCount { get { return SlotValueHelper.GetChannelCount(FindSlot(InputSlotId).concreteValueType); } } [SerializeField] private bool m_RedChannel; [ToggleControl("Red")] public ToggleData redChannel { get { return new ToggleData(m_RedChannel, channelCount > 0); } set { if (m_RedChannel == value.isOn) return; m_RedChannel = value.isOn; Dirty(ModificationScope.Node); } } [SerializeField] private bool m_GreenChannel; [ToggleControl("Green")] public ToggleData greenChannel { get { return new ToggleData(m_GreenChannel, channelCount > 1); } set { if (m_GreenChannel == value.isOn) return; m_GreenChannel = value.isOn; Dirty(ModificationScope.Node); } } [SerializeField] private bool m_BlueChannel; [ToggleControl("Blue")] public ToggleData blueChannel { get { return new ToggleData(m_BlueChannel, channelCount > 2); } set { if (m_BlueChannel == value.isOn) return; m_BlueChannel = value.isOn; Dirty(ModificationScope.Node); } } [SerializeField] private bool m_AlphaChannel; [ToggleControl("Alpha")] public ToggleData alphaChannel { get { return new ToggleData(m_AlphaChannel, channelCount > 3); } set { if (m_AlphaChannel == value.isOn) return; m_AlphaChannel = value.isOn; Dirty(ModificationScope.Node); } } public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode) { var inputValue = GetSlotValue(InputSlotId, generationMode); var outputValue = GetSlotValue(OutputSlotId, generationMode); sb.AppendLine("{0} {1};", FindOutputSlot(OutputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId)); if (!generationMode.IsPreview()) { sb.TryAppendIndentation(); sb.Append("{0} _{1}_Flip = {0} ({2}", FindInputSlot(InputSlotId).concreteValueType.ToShaderString(), GetVariableNameForNode(), Convert.ToInt32(m_RedChannel)); if (channelCount > 1) sb.Append(", {0}", Convert.ToInt32(m_GreenChannel)); if (channelCount > 2) sb.Append(", {0}", Convert.ToInt32(m_BlueChannel)); if (channelCount > 3) sb.Append(", {0}", Convert.ToInt32(m_AlphaChannel)); sb.Append(");"); sb.AppendNewLine(); } sb.AppendLine("{0}({1}, _{2}_Flip, {3});", GetFunctionName(), inputValue, GetVariableNameForNode(), outputValue); } public override void CollectPreviewMaterialProperties(List properties) { base.CollectPreviewMaterialProperties(properties); properties.Add(new PreviewProperty(PropertyType.Vector4) { name = string.Format("_{0}_Flip", GetVariableNameForNode()), vector4Value = new Vector4(Convert.ToInt32(m_RedChannel), Convert.ToInt32(m_GreenChannel), Convert.ToInt32(m_BlueChannel), Convert.ToInt32(m_AlphaChannel)), }); } public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode) { if (!generationMode.IsPreview()) return; base.CollectShaderProperties(properties, generationMode); properties.AddShaderProperty(new Vector4ShaderProperty { overrideReferenceName = string.Format("_{0}_Flip", GetVariableNameForNode()), generatePropertyBlock = false }); } public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode) { registry.ProvideFunction(GetFunctionName(), s => { s.AppendLine("void {0}({1} In, {2} Flip, out {3} Out)", GetFunctionName(), FindInputSlot(InputSlotId).concreteValueType.ToShaderString(), FindInputSlot(InputSlotId).concreteValueType.ToShaderString(), FindOutputSlot(OutputSlotId).concreteValueType.ToShaderString()); using (s.BlockScope()) { s.AppendLine("Out = (Flip * -2 + 1) * In;"); } }); } } }