UnityGame/Library/PackageCache/com.unity.shadergraph/Editor/Data/SubGraph/SubGraphOutputNode.cs
2024-10-27 10:53:47 +03:00

114 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor.ShaderGraph.Drawing;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.Rendering;
using UnityEngine.Rendering.ShaderGraph;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
class SubGraphOutputNode : AbstractMaterialNode
{
static string s_MissingOutputSlot = "A Sub Graph must have at least one output slot";
static List<ConcreteSlotValueType> s_ValidSlotTypes = new List<ConcreteSlotValueType>()
{
ConcreteSlotValueType.Vector1,
ConcreteSlotValueType.Vector2,
ConcreteSlotValueType.Vector3,
ConcreteSlotValueType.Vector4,
ConcreteSlotValueType.Matrix2,
ConcreteSlotValueType.Matrix3,
ConcreteSlotValueType.Matrix4,
ConcreteSlotValueType.Boolean
};
public bool IsFirstSlotValid = true;
public SubGraphOutputNode()
{
name = "Output";
}
// Link to the Sub Graph overview page instead of the specific Node page, seems more useful
public override string documentationURL => Documentation.GetPageLink("Sub-graph");
void ValidateShaderStage()
{
List<MaterialSlot> slots = new List<MaterialSlot>();
GetInputSlots(slots);
// Reset all input slots back to All, otherwise they'll be incorrectly configured when traversing below
foreach (MaterialSlot slot in slots)
slot.stageCapability = ShaderStageCapability.All;
foreach (var slot in slots)
{
slot.stageCapability = NodeUtils.GetEffectiveShaderStageCapability(slot, true);
}
}
void ValidateSlotName()
{
List<MaterialSlot> slots = new List<MaterialSlot>();
GetInputSlots(slots);
foreach (var slot in slots)
{
var error = NodeUtils.ValidateSlotName(slot.RawDisplayName(), out string errorMessage);
if (error)
{
owner.AddValidationError(objectId, errorMessage);
break;
}
}
}
void ValidateSlotType()
{
List<MaterialSlot> slots = new List<MaterialSlot>();
GetInputSlots(slots);
if (!slots.Any())
{
owner.AddValidationError(objectId, s_MissingOutputSlot, ShaderCompilerMessageSeverity.Error);
}
else if (!s_ValidSlotTypes.Contains(slots.FirstOrDefault().concreteValueType))
{
IsFirstSlotValid = false;
owner.AddValidationError(objectId, "Preview can only compile if the first output slot is a Vector, Matrix, or Boolean type. Please adjust slot types.", ShaderCompilerMessageSeverity.Error);
}
}
public override void ValidateNode()
{
base.ValidateNode();
IsFirstSlotValid = true;
ValidateSlotType();
if (IsFirstSlotValid)
ValidateShaderStage();
}
protected override void OnSlotsChanged()
{
base.OnSlotsChanged();
ValidateNode();
}
public int AddSlot(ConcreteSlotValueType concreteValueType)
{
var index = this.GetInputSlots<MaterialSlot>().Count() + 1;
var name = NodeUtils.GetDuplicateSafeNameForSlot(this, index, "Out_" + concreteValueType.ToString());
AddSlot(MaterialSlot.CreateMaterialSlot(concreteValueType.ToSlotValueType(), index, name,
NodeUtils.GetHLSLSafeName(name), SlotType.Input, Vector4.zero));
return index;
}
public override bool canDeleteNode => false;
public override bool canCopyNode => false;
}
}