This commit is contained in:
2021-06-13 10:28:03 +02:00
parent eb70603c85
commit df2d24cbd3
7487 changed files with 943244 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace UnityEditor.ShaderGraph.Drawing
{
[AttributeUsage(AttributeTargets.Method)]
class BuiltinKeywordAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,9 @@
using System;
namespace UnityEditor.ShaderGraph
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
internal abstract class ContextFilterableAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,24 @@
using System;
namespace UnityEditor.ShaderGraph.Drawing
{
[AttributeUsage(AttributeTargets.Property)]
public class InspectableAttribute : Attribute
{
// String value to use in the Property name TextLabel
public string labelName { get; private set; }
// The default value of this property
public object defaultValue { get; private set; }
// String value to supply if you wish to use a custom style when drawing this property
public string customStyleName { get; private set; }
public InspectableAttribute(string labelName, object defaultValue, string customStyleName = "")
{
this.labelName = labelName;
this.defaultValue = defaultValue;
this.customStyleName = customStyleName;
}
}
}

View File

@@ -0,0 +1,9 @@
using System;
namespace UnityEditor.ShaderGraph
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
internal class NeverAllowedByTargetAttribute : ContextFilterableAttribute
{
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace UnityEditor.ShaderGraph.Drawing
{
[AttributeUsage(AttributeTargets.Class)]
public class SGPropertyDrawerAttribute : Attribute
{
public Type propertyType { get; private set; }
public SGPropertyDrawerAttribute(Type propertyType)
{
this.propertyType = propertyType;
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace UnityEditor.ShaderGraph
{
[GenerationAPI]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
internal class SRPFilterAttribute : ContextFilterableAttribute
{
public Type[] srpTypes = null;
public SRPFilterAttribute(params Type[] WorksWithSRP)
{
srpTypes = WorksWithSRP;
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
using UnityEditor.ShaderGraph.Serialization;
namespace UnityEditor.ShaderGraph
{
[Serializable]
sealed class ContextData
{
[SerializeField]
Vector2 m_Position;
[SerializeField]
List<JsonRef<BlockNode>> m_Blocks = new List<JsonRef<BlockNode>>();
[NonSerialized]
ShaderStage m_ShaderStage;
public ContextData()
{
}
public List<JsonRef<BlockNode>> blocks => m_Blocks;
public Vector2 position
{
get => m_Position;
set => m_Position = value;
}
public ShaderStage shaderStage
{
get => m_ShaderStage;
set => m_ShaderStage = value;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace UnityEditor.ShaderGraph.Internal
{
enum Precision
{
Inherit,
Single,
Half,
}
public enum ConcretePrecision
{
Single,
Half,
}
}

View File

@@ -0,0 +1,3 @@
namespace UnityEditor.ShaderGraph
{
}

View File

@@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
public abstract class AbstractShaderProperty : ShaderInput
{
public abstract PropertyType propertyType { get; }
internal override ConcreteSlotValueType concreteShaderValueType => propertyType.ToConcreteShaderValueType();
// user selected precision setting
[SerializeField]
Precision m_Precision = Precision.Inherit;
[Obsolete("AbstractShaderProperty.gpuInstanced is no longer used")]
public bool gpuInstanced
{
get { return false; }
set {}
}
internal virtual string GetHLSLVariableName(bool isSubgraphProperty)
{
return referenceName;
}
// NOTE: this does not tell you the HLSLDeclaration of the entire property...
// instead, it tells you what the DEFAULT HLSL Declaration would be, IF the property makes use of the default
// to check ACTUAL HLSL Declaration types, enumerate the HLSL Properties and check their HLSLDeclarations...
internal virtual HLSLDeclaration GetDefaultHLSLDeclaration()
{
if (overrideHLSLDeclaration)
return hlslDeclarationOverride;
// default Behavior switches between UnityPerMaterial and Global based on Exposed checkbox
if (generatePropertyBlock)
return HLSLDeclaration.UnityPerMaterial;
else
return HLSLDeclaration.Global;
}
// by default we disallow UI from choosing "DoNotDeclare"
// it needs a bit more UI support to disable property node output slots before we make it public
internal virtual bool AllowHLSLDeclaration(HLSLDeclaration decl) => (decl != HLSLDeclaration.DoNotDeclare);
[SerializeField]
internal bool overrideHLSLDeclaration = false;
[SerializeField]
internal HLSLDeclaration hlslDeclarationOverride;
internal Precision precision
{
get => m_Precision;
set => m_Precision = value;
}
ConcretePrecision m_ConcretePrecision = ConcretePrecision.Single;
public ConcretePrecision concretePrecision => m_ConcretePrecision;
internal void ValidateConcretePrecision(ConcretePrecision graphPrecision)
{
m_ConcretePrecision = (precision == Precision.Inherit) ? graphPrecision : precision.ToConcrete();
}
[SerializeField]
bool m_Hidden = false;
public bool hidden
{
get => m_Hidden;
set => m_Hidden = value;
}
internal string hideTagString => hidden ? "[HideInInspector]" : "";
// reference names are the HLSL declaration name / property block ref name
internal virtual void GetPropertyReferenceNames(List<string> result)
{
result.Add(referenceName);
}
// display names are used as the UI name in the property block / show up in the Material Inspector
internal virtual void GetPropertyDisplayNames(List<string> result)
{
result.Add(displayName);
}
// the simple interface for simple properties
internal virtual string GetPropertyBlockString()
{
return string.Empty;
}
// the more complex interface for complex properties (defaulted for simple properties)
internal virtual void AppendPropertyBlockStrings(ShaderStringBuilder builder)
{
builder.AppendLine(GetPropertyBlockString());
}
internal abstract void ForeachHLSLProperty(Action<HLSLProperty> action);
internal virtual string GetPropertyAsArgumentStringForVFX()
{
return GetPropertyAsArgumentString();
}
internal abstract string GetPropertyAsArgumentString();
internal abstract AbstractMaterialNode ToConcreteNode();
internal abstract PreviewProperty GetPreviewMaterialProperty();
public virtual string GetPropertyTypeString()
{
string depString = $" (Deprecated{(ShaderGraphPreferences.allowDeprecatedBehaviors ? " V" + sgVersion : "" )})";
return propertyType.ToString() + (sgVersion < latestVersion ? depString : "");
}
}
[Serializable]
public abstract class AbstractShaderProperty<T> : AbstractShaderProperty
{
[SerializeField]
T m_Value;
public virtual T value
{
get => m_Value;
set => m_Value = value;
}
}
// class for extracting deprecated data from older versions of AbstractShaderProperty
class LegacyShaderPropertyData
{
// indicates user wishes to support the HYBRID renderer GPU instanced path
[SerializeField]
public bool m_GPUInstanced = false;
// converts the old m_GPUInstanced data into the new override HLSLDeclaration system.
public static void UpgradeToHLSLDeclarationOverride(string json, AbstractShaderProperty property)
{
// this maintains the old behavior for versioned properties:
// old exposed GPUInstanced properties are declared hybrid (becomes override in new system)
// old unexposed GPUInstanced properties are declared global (becomes override in new system)
// old exposed properties are declared UnityPerMaterial (default behavior, no override necessary)
// old unexposed properties are declared Global (default behavior, no override necessary)
// moving forward, users can use the overrides directly to control what it does
var legacyShaderPropertyData = new LegacyShaderPropertyData();
JsonUtility.FromJsonOverwrite(json, legacyShaderPropertyData);
if (legacyShaderPropertyData.m_GPUInstanced)
{
property.overrideHLSLDeclaration = true;
if (property.generatePropertyBlock)
property.hlslDeclarationOverride = HLSLDeclaration.HybridPerInstance;
else
property.hlslDeclarationOverride = HLSLDeclaration.Global;
}
}
}
public enum HLSLType
{
// value types
_float,
_float2,
_float3,
_float4,
_matrix4x4,
// object types
FirstObjectType,
_Texture2D = FirstObjectType,
_Texture3D,
_TextureCube,
_Texture2DArray,
_SamplerState,
// custom type
_CUSTOM
}
// describes the different ways we can generate HLSL declarations
[Flags]
internal enum HLSLDeclaration
{
DoNotDeclare, // NOT declared in HLSL
Global, // declared in the global scope, mainly for use with state coming from Shader.SetGlobal*()
UnityPerMaterial, // declared in the UnityPerMaterial cbuffer, populated by Material or MaterialPropertyBlock
HybridPerInstance, // declared using HybridRenderer path (v1 or v2) to get DOTS GPU instancing
}
internal struct HLSLProperty
{
public string name;
public HLSLType type;
public ConcretePrecision precision;
public HLSLDeclaration declaration;
public Action<ShaderStringBuilder> customDeclaration;
public HLSLProperty(HLSLType type, string name, HLSLDeclaration declaration, ConcretePrecision precision = ConcretePrecision.Single)
{
this.type = type;
this.name = name;
this.declaration = declaration;
this.precision = precision;
this.customDeclaration = null;
}
static string[,] kValueTypeStrings = new string[(int)HLSLType.FirstObjectType, 2]
{
{"float", "half"},
{"float2", "half2"},
{"float3", "half3"},
{"float4", "half4"},
{"float4x4", "half4x4"}
};
static string[] kObjectTypeStrings = new string[(int)HLSLType._CUSTOM - (int)HLSLType.FirstObjectType]
{
"TEXTURE2D",
"TEXTURE3D",
"TEXTURECUBE",
"TEXTURE2D_ARRAY",
"SAMPLER",
};
public string GetValueTypeString()
{
if (type < HLSLType.FirstObjectType)
return kValueTypeStrings[(int)type, (int)precision];
return null;
}
public void AppendTo(ShaderStringBuilder ssb, Func<string, string> nameModifier = null)
{
var mName = nameModifier?.Invoke(name) ?? name;
if (type < HLSLType.FirstObjectType)
{
ssb.Append(kValueTypeStrings[(int)type, (int)precision]);
ssb.Append(" ");
ssb.Append(mName);
ssb.Append(";");
}
else if (type < HLSLType._CUSTOM)
{
ssb.Append(kObjectTypeStrings[type - HLSLType.FirstObjectType]);
ssb.Append("(");
ssb.Append(mName);
ssb.Append(");");
}
else
{
customDeclaration(ssb);
}
//ssb.Append(" // ");
//ssb.Append(declaration.ToString());
ssb.AppendNewLine();
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class BitangentMaterialSlot : SpaceMaterialSlot, IMayRequireBitangent
{
public BitangentMaterialSlot() : base()
{}
public BitangentMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView(space + " Space");
}
public override string GetDefaultValue(GenerationMode generationMode)
{
return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.BiTangent));
}
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;
return space.ToNeededCoordinateSpace();
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class BooleanMaterialSlot : MaterialSlot, IMaterialSlotHasValue<bool>
{
[SerializeField]
private bool m_Value;
[SerializeField]
private bool m_DefaultValue;
public BooleanMaterialSlot()
{}
public BooleanMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
bool value,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_DefaultValue = value;
m_Value = value;
}
public override VisualElement InstantiateControl()
{
return new BooleanSlotControlView(this);
}
public bool defaultValue { get { return m_DefaultValue; } }
public bool value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
protected override string ConcreteSlotValueAsVariable()
{
return (value ? 1 : 0).ToString();
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new BooleanShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override SlotValueType valueType { get { return SlotValueType.Boolean; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Boolean; } }
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Boolean)
{
name = name,
booleanValue = value
};
properties.Add(pp);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as BooleanMaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<bool> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.Text;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Controls;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.BooleanShaderProperty")]
[BlackboardInputInfo(20)]
public sealed class BooleanShaderProperty : AbstractShaderProperty<bool>
{
internal BooleanShaderProperty()
{
displayName = "Boolean";
}
public override PropertyType propertyType => PropertyType.Boolean;
internal override bool isExposable => true;
internal override bool isRenamable => true;
internal override string GetPropertyAsArgumentString()
{
return $"{concreteShaderValueType.ToShaderString(concretePrecision.ToShaderString())} {referenceName}";
}
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
HLSLDeclaration decl = GetDefaultHLSLDeclaration();
action(new HLSLProperty(HLSLType._float, referenceName, decl, concretePrecision));
}
internal override string GetPropertyBlockString()
{
return $"{hideTagString}[ToggleUI]{referenceName}(\"{displayName}\", Float) = {(value == true ? 1 : 0)}";
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new BooleanNode { value = new ToggleData(value) };
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
booleanValue = value
};
}
internal override ShaderInput Copy()
{
return new BooleanShaderProperty()
{
displayName = displayName,
value = value,
};
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
class ColorRGBAMaterialSlot : Vector4MaterialSlot
{
public ColorRGBAMaterialSlot() {}
public ColorRGBAMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, value, stageCapability, hidden: hidden)
{
}
public override VisualElement InstantiateControl()
{
return new ColorRGBASlotControlView(this);
}
protected override string ConcreteSlotValueAsVariable()
{
return string.Format("IsGammaSpace() ? $precision4({0}, {1}, {2}, {3}) : $precision4 (SRGBToLinear($precision3({0}, {1}, {2})), {3})"
, NodeUtils.FloatToShaderValue(value.x)
, NodeUtils.FloatToShaderValue(value.y)
, NodeUtils.FloatToShaderValue(value.z)
, NodeUtils.FloatToShaderValue(value.w));
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new ColorShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Color)
{
name = name,
colorValue = new Color(value.x, value.y, value.z, value.w),
};
properties.Add(pp);
}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
class ColorRGBMaterialSlot : Vector3MaterialSlot
{
[SerializeField]
ColorMode m_ColorMode = ColorMode.Default;
[SerializeField]
private Color m_DefaultColor = Color.grey;
public ColorRGBMaterialSlot() {}
public ColorRGBMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Color value,
ColorMode colorMode,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, (Vector4)value, stageCapability, hidden: hidden)
{
m_ColorMode = colorMode;
m_DefaultColor = value;
}
public ColorMode colorMode
{
get { return m_ColorMode; }
set { m_ColorMode = value; }
}
public Color defaultColor => m_DefaultColor;
public override bool isDefaultValue => value.Equals((Vector4)defaultColor);
public override VisualElement InstantiateControl()
{
return new ColorRGBSlotControlView(this);
}
protected override string ConcreteSlotValueAsVariable()
{
return string.Format(m_ColorMode == ColorMode.Default ? "IsGammaSpace() ? $precision3({0}, {1}, {2}) : SRGBToLinear($precision3({0}, {1}, {2}))" : "$precision3({0}, {1}, {2})"
, NodeUtils.FloatToShaderValue(value.x)
, NodeUtils.FloatToShaderValue(value.y)
, NodeUtils.FloatToShaderValue(value.z));
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new ColorShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = new Color(value.x, value.y, value.z)
};
properties.AddShaderProperty(property);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Color)
{
name = name,
colorValue = new Color(value.x, value.y, value.z, 1),
};
properties.Add(pp);
}
}
}

View File

@@ -0,0 +1,115 @@
using System;
using System.Text;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.ColorShaderProperty")]
[BlackboardInputInfo(10)]
public sealed class ColorShaderProperty : AbstractShaderProperty<Color>
{
// 0 - original (broken color space)
// 1 - fixed color space
// 2 - original (broken color space) with HLSLDeclaration override
// 3 - fixed color space with HLSLDeclaration override
public override int latestVersion => 3;
public const int deprecatedVersion = 2;
internal ColorShaderProperty()
{
displayName = "Color";
}
internal ColorShaderProperty(int version) : this()
{
this.sgVersion = version;
}
public override PropertyType propertyType => PropertyType.Color;
internal override bool isExposable => true;
internal override bool isRenamable => true;
internal string hdrTagString => colorMode == ColorMode.HDR ? "[HDR]" : "";
internal override string GetPropertyBlockString()
{
return $"{hideTagString}{hdrTagString}{referenceName}(\"{displayName}\", Color) = ({NodeUtils.FloatToShaderValue(value.r)}, {NodeUtils.FloatToShaderValue(value.g)}, {NodeUtils.FloatToShaderValue(value.b)}, {NodeUtils.FloatToShaderValue(value.a)})";
}
internal override string GetPropertyAsArgumentString()
{
return $"{concreteShaderValueType.ToShaderString(concretePrecision.ToShaderString())} {referenceName}";
}
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
HLSLDeclaration decl = GetDefaultHLSLDeclaration();
action(new HLSLProperty(HLSLType._float4, referenceName, decl, concretePrecision));
}
public override string GetOldDefaultReferenceName()
{
return $"Color_{objectId}";
}
[SerializeField]
ColorMode m_ColorMode;
public ColorMode colorMode
{
get => m_ColorMode;
set => m_ColorMode = value;
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new ColorNode { color = new ColorNode.Color(value, colorMode) };
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
UnityEngine.Color propColor = value;
if (colorMode == ColorMode.Default)
{
if (PlayerSettings.colorSpace == ColorSpace.Linear)
propColor = propColor.linear;
}
else if (colorMode == ColorMode.HDR)
{
// conversion from linear to active color space is handled in the shader code (see PropertyNode.cs)
}
// we use Vector4 type to avoid all of the automatic color conversions of PropertyType.Color
return new PreviewProperty(PropertyType.Vector4)
{
name = referenceName,
vector4Value = propColor
};
}
internal override ShaderInput Copy()
{
return new ColorShaderProperty()
{
sgVersion = sgVersion,
displayName = displayName,
value = value,
colorMode = colorMode,
};
}
public override void OnAfterDeserialize(string json)
{
if (sgVersion < 2)
{
LegacyShaderPropertyData.UpgradeToHLSLDeclarationOverride(json, this);
// version 0 upgrades to 2
// version 1 upgrades to 3
ChangeVersion((sgVersion == 0) ? 2 : 3);
}
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[HasDependencies(typeof(MinimalCubemapInputMaterialSlot))]
class CubemapInputMaterialSlot : CubemapMaterialSlot
{
[SerializeField]
private SerializableCubemap m_Cubemap = new SerializableCubemap();
public Cubemap cubemap
{
get { return m_Cubemap.cubemap; }
set { m_Cubemap.cubemap = value; }
}
public override bool isDefaultValue => cubemap == null;
public CubemapInputMaterialSlot()
{}
public CubemapInputMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new CubemapSlotControlView(this);
}
public override string GetDefaultValue(GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
return $"UnityBuildTextureCubeStruct({nodeOwner.GetVariableNameForSlot(id)})";
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var prop = new CubemapShaderProperty();
prop.overrideReferenceName = nodeOwner.GetVariableNameForSlot(id);
prop.modifiable = false;
prop.generatePropertyBlock = true;
prop.value.cubemap = cubemap;
properties.AddShaderProperty(prop);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Cubemap)
{
name = name,
cubemapValue = cubemap
};
properties.Add(pp);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as CubemapInputMaterialSlot;
if (slot != null)
{
m_Cubemap = slot.m_Cubemap;
bareResource = slot.bareResource;
}
}
}
class MinimalCubemapInputMaterialSlot : IHasDependencies
{
[SerializeField]
private SerializableCubemap m_Cubemap = null;
public void GetSourceAssetDependencies(AssetCollection assetCollection)
{
var guidString = m_Cubemap.guid;
if (!string.IsNullOrEmpty(guidString) && GUID.TryParse(guidString, out var guid))
{
assetCollection.AddAssetDependency(guid, AssetCollection.Flags.IncludeInExportPackage);
}
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class CubemapMaterialSlot : MaterialSlot
{
public CubemapMaterialSlot()
{}
public CubemapMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{}
[SerializeField]
bool m_BareResource = false;
internal override bool bareResource
{
get { return m_BareResource; }
set { m_BareResource = value; }
}
public override void AppendHLSLParameterDeclaration(ShaderStringBuilder sb, string paramName)
{
if (m_BareResource)
{
sb.Append("TEXTURECUBE(");
sb.Append(paramName);
sb.Append(")");
}
else
base.AppendHLSLParameterDeclaration(sb, paramName);
}
public override SlotValueType valueType { get { return SlotValueType.Cubemap; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Cubemap; } }
public override bool isDefaultValue => true;
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{}
}
}

View File

@@ -0,0 +1,89 @@
using System;
using System.Text;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.CubemapShaderProperty")]
[BlackboardInputInfo(53)]
public sealed class CubemapShaderProperty : AbstractShaderProperty<SerializableCubemap>
{
internal CubemapShaderProperty()
{
displayName = "Cubemap";
value = new SerializableCubemap();
}
public override PropertyType propertyType => PropertyType.Cubemap;
internal override bool isExposable => true;
internal override bool isRenamable => true;
internal string modifiableTagString => modifiable ? "" : "[NonModifiableTextureData]";
internal override string GetPropertyBlockString()
{
return $"{hideTagString}{modifiableTagString}[NoScaleOffset]{referenceName}(\"{displayName}\", CUBE) = \"\" {{}}";
}
internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => false; // disable UI, nothing to choose
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
action(new HLSLProperty(HLSLType._TextureCube, referenceName, HLSLDeclaration.Global));
action(new HLSLProperty(HLSLType._SamplerState, "sampler" + referenceName, HLSLDeclaration.Global));
}
internal override string GetPropertyAsArgumentString()
{
return "UnityTextureCube " + referenceName;
}
internal override string GetPropertyAsArgumentStringForVFX()
{
return "TEXTURECUBE(" + referenceName + ")";
}
internal override string GetHLSLVariableName(bool isSubgraphProperty)
{
if (isSubgraphProperty)
return referenceName;
else
return $"UnityBuildTextureCubeStruct({referenceName})";
}
[SerializeField]
bool m_Modifiable = true;
internal bool modifiable
{
get => m_Modifiable;
set => m_Modifiable = value;
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new CubemapAssetNode { cubemap = value.cubemap };
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
cubemapValue = value.cubemap
};
}
internal override ShaderInput Copy()
{
return new CubemapShaderProperty()
{
displayName = displayName,
value = value,
};
}
}
}

View File

@@ -0,0 +1,129 @@
using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class DynamicMatrixMaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
{
[SerializeField]
private Matrix4x4 m_Value = Matrix4x4.identity;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
private ConcreteSlotValueType m_ConcreteValueType = ConcreteSlotValueType.Matrix4;
public DynamicMatrixMaterialSlot()
{
}
public DynamicMatrixMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Identity");
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
public override SlotValueType valueType { get { return SlotValueType.DynamicMatrix; } }
public override ConcreteSlotValueType concreteValueType
{
get { return m_ConcreteValueType; }
}
public void SetConcreteType(ConcreteSlotValueType valueType)
{
m_ConcreteValueType = valueType;
}
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 override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
AbstractShaderProperty property;
switch (concreteValueType)
{
case ConcreteSlotValueType.Matrix4:
property = new Matrix4ShaderProperty();
break;
case ConcreteSlotValueType.Matrix3:
property = new Matrix3ShaderProperty();
break;
case ConcreteSlotValueType.Matrix2:
property = new Matrix2ShaderProperty();
break;
default:
throw new ArgumentOutOfRangeException();
}
property.overrideReferenceName = matOwner.GetVariableNameForSlot(id);
property.generatePropertyBlock = false;
properties.AddShaderProperty(property);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as DynamicMatrixMaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Matrix4x4> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class DynamicValueMaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
{
[SerializeField]
private Matrix4x4 m_Value;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
static readonly string[] k_Labels = {"X", "Y", "Z", "W"};
private ConcreteSlotValueType m_ConcreteValueType = ConcreteSlotValueType.Vector4;
public DynamicValueMaterialSlot()
{
}
public DynamicValueMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Matrix4x4 value,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
public override VisualElement InstantiateControl()
{
var labels = k_Labels.Take(concreteValueType.GetChannelCount()).ToArray();
return new MultiFloatSlotControlView(owner, labels, () => value.GetRow(0), (newValue) =>
value = new Matrix4x4()
{
m00 = newValue.x, m01 = newValue.y, m02 = newValue.z, m03 = newValue.w,
m10 = value.m10, m11 = value.m11, m12 = value.m12, m13 = value.m13,
m20 = value.m20, m21 = value.m21, m22 = value.m22, m23 = value.m23,
m30 = value.m30, m31 = value.m31, m32 = value.m32, m33 = value.m33,
});
}
public override SlotValueType valueType { get { return SlotValueType.Dynamic; } }
public override ConcreteSlotValueType concreteValueType
{
get { return m_ConcreteValueType; }
}
public void SetConcreteType(ConcreteSlotValueType valueType)
{
m_ConcreteValueType = valueType;
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var propType = concreteValueType.ToPropertyType();
var pp = new PreviewProperty(propType) { name = name };
if (propType == PropertyType.Float)
pp.floatValue = value.m00;
else
pp.vector4Value = new Vector4(value.m00, value.m01, value.m02, value.m03);
properties.Add(pp);
}
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 override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
AbstractShaderProperty property;
switch (concreteValueType)
{
case ConcreteSlotValueType.Vector4:
property = new Vector4ShaderProperty();
break;
case ConcreteSlotValueType.Vector3:
property = new Vector3ShaderProperty();
break;
case ConcreteSlotValueType.Vector2:
property = new Vector2ShaderProperty();
break;
case ConcreteSlotValueType.Vector1:
property = new Vector1ShaderProperty();
break;
case ConcreteSlotValueType.Matrix4:
property = new Matrix4ShaderProperty();
break;
case ConcreteSlotValueType.Matrix3:
property = new Matrix3ShaderProperty();
break;
case ConcreteSlotValueType.Matrix2:
property = new Matrix2ShaderProperty();
break;
default:
throw new ArgumentOutOfRangeException();
}
property.overrideReferenceName = matOwner.GetVariableNameForSlot(id);
property.generatePropertyBlock = false;
properties.AddShaderProperty(property);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as DynamicValueMaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Matrix4x4> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class DynamicVectorMaterialSlot : MaterialSlot, IMaterialSlotHasValue<Vector4>
{
[SerializeField]
private Vector4 m_Value;
[SerializeField]
private Vector4 m_DefaultValue = Vector4.zero;
static readonly string[] k_Labels = {"X", "Y", "Z", "W"};
private ConcreteSlotValueType m_ConcreteValueType = ConcreteSlotValueType.Vector4;
public DynamicVectorMaterialSlot()
{
}
public DynamicVectorMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
}
public Vector4 defaultValue { get { return m_DefaultValue; } }
public Vector4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
public override VisualElement InstantiateControl()
{
var labels = k_Labels.Take(concreteValueType.GetChannelCount()).ToArray();
return new MultiFloatSlotControlView(owner, labels, () => value, (newValue) => value = newValue);
}
public override SlotValueType valueType { get { return SlotValueType.DynamicVector; } }
public override ConcreteSlotValueType concreteValueType
{
get { return m_ConcreteValueType; }
}
public void SetConcreteType(ConcreteSlotValueType valueType)
{
m_ConcreteValueType = valueType;
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var propType = concreteValueType.ToPropertyType();
var pp = new PreviewProperty(propType) { name = name };
if (propType == PropertyType.Float)
pp.floatValue = value.x;
else
pp.vector4Value = new Vector4(value.x, value.y, value.z, value.w);
properties.Add(pp);
}
protected override string ConcreteSlotValueAsVariable()
{
var channelCount = SlotValueHelper.GetChannelCount(concreteValueType);
string values = NodeUtils.FloatToShaderValue(value.x);
if (channelCount == 1)
return values;
for (var i = 1; i < channelCount; i++)
values += ", " + NodeUtils.FloatToShaderValue(value[i]);
return string.Format("$precision{0}({1})", channelCount, values);
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
AbstractShaderProperty property;
switch (concreteValueType)
{
case ConcreteSlotValueType.Vector4:
property = new Vector4ShaderProperty();
break;
case ConcreteSlotValueType.Vector3:
property = new Vector3ShaderProperty();
break;
case ConcreteSlotValueType.Vector2:
property = new Vector2ShaderProperty();
break;
case ConcreteSlotValueType.Vector1:
property = new Vector1ShaderProperty();
break;
default:
// This shouldn't happen due to edge validation. The generated shader will
// have errors.
Debug.LogError($"Invalid value type {concreteValueType} passed to Vector Slot {displayName}. Value will be ignored, please plug in an edge with a vector type.");
return;
}
property.overrideReferenceName = matOwner.GetVariableNameForSlot(id);
property.generatePropertyBlock = false;
properties.AddShaderProperty(property);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as DynamicVectorMaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Vector4> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class GradientInputMaterialSlot : GradientMaterialSlot, IMaterialSlotHasValue<Gradient>
{
[SerializeField]
Gradient m_Value = new Gradient();
[SerializeField]
Gradient m_DefaultValue = new Gradient();
public GradientInputMaterialSlot()
{
}
public GradientInputMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{
}
public Gradient value
{
get { return m_Value; }
set { m_Value = value; }
}
public Gradient defaultValue { get { return m_DefaultValue; } }
public override bool isDefaultValue => value.Equals(defaultValue);
public override VisualElement InstantiateControl()
{
return new GradientSlotControlView(this);
}
public override string GetDefaultValue(GenerationMode generationMode)
{
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
if (generationMode.IsPreview())
return GradientUtil.GetGradientForPreview(matOwner.GetVariableNameForSlot(id));
return ConcreteSlotValueAsVariable();
}
protected override string ConcreteSlotValueAsVariable()
{
return GradientUtil.GetGradientValue(value, "");
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
if (generationMode != GenerationMode.Preview)
return;
GradientUtil.GetGradientPropertiesForPreview(properties, matOwner.GetVariableNameForSlot(id), value);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
properties.Add(new PreviewProperty(PropertyType.Gradient)
{
name = name,
gradientValue = value
});
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as GradientInputMaterialSlot;
if (slot != null)
value = slot.value;
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using UnityEditor.Graphing;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class GradientMaterialSlot : MaterialSlot
{
public GradientMaterialSlot()
{}
public GradientMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{}
public override SlotValueType valueType { get { return SlotValueType.Gradient; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Gradient; } }
public override bool isDefaultValue => true;
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{}
}
}

View File

@@ -0,0 +1,112 @@
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.ShaderGraph.Drawing.Controls;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[BlackboardInputInfo(30)]
class GradientShaderProperty : AbstractShaderProperty<Gradient>
{
public GradientShaderProperty()
{
displayName = "Gradient";
value = new Gradient();
}
public override PropertyType propertyType => PropertyType.Gradient;
internal override bool isExposable => false;
internal override bool isRenamable => true;
internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => false; // disable UI, nothing to choose
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
Action<ShaderStringBuilder> customDecl = (builder) =>
{
builder.AppendLine("Gradient {0}_Definition()", referenceName);
using (builder.BlockScope())
{
string[] colors = new string[8];
for (int i = 0; i < colors.Length; i++)
colors[i] = string.Format("g.colors[{0}] = {1}4(0, 0, 0, 0);", i, concretePrecision.ToShaderString());
for (int i = 0; i < value.colorKeys.Length; i++)
colors[i] = string.Format("g.colors[{0}] = {1}4({2}, {3}, {4}, {5});"
, i
, concretePrecision.ToShaderString()
, NodeUtils.FloatToShaderValue(value.colorKeys[i].color.r)
, NodeUtils.FloatToShaderValue(value.colorKeys[i].color.g)
, NodeUtils.FloatToShaderValue(value.colorKeys[i].color.b)
, NodeUtils.FloatToShaderValue(value.colorKeys[i].time));
string[] alphas = new string[8];
for (int i = 0; i < alphas.Length; i++)
alphas[i] = string.Format("g.alphas[{0}] = {1}2(0, 0);", i, concretePrecision.ToShaderString());
for (int i = 0; i < value.alphaKeys.Length; i++)
alphas[i] = string.Format("g.alphas[{0}] = {1}2({2}, {3});"
, i
, concretePrecision.ToShaderString()
, NodeUtils.FloatToShaderValue(value.alphaKeys[i].alpha)
, NodeUtils.FloatToShaderValue(value.alphaKeys[i].time));
builder.AppendLine("Gradient g;");
builder.AppendLine("g.type = {0};",
(int)value.mode);
builder.AppendLine("g.colorsLength = {0};",
value.colorKeys.Length);
builder.AppendLine("g.alphasLength = {0};",
value.alphaKeys.Length);
for (int i = 0; i < colors.Length; i++)
builder.AppendLine(colors[i]);
for (int i = 0; i < alphas.Length; i++)
builder.AppendLine(alphas[i]);
builder.AppendLine("return g;", true);
}
builder.AppendIndentation();
builder.Append("#define {0} {0}_Definition()", referenceName);
};
action(
new HLSLProperty(HLSLType._CUSTOM, referenceName, HLSLDeclaration.Global, concretePrecision)
{
customDeclaration = customDecl
});
}
internal override string GetPropertyAsArgumentString()
{
return "Gradient " + referenceName;
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new GradientNode { gradient = value };
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
gradientValue = value
};
}
internal override ShaderInput Copy()
{
return new GradientShaderProperty
{
displayName = displayName,
value = value,
};
}
}
}

View File

@@ -0,0 +1,29 @@
using System.Linq;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
sealed partial class GraphData : ISerializationCallbackReceiver
{
public static class GraphConcretization
{
public static void ConcretizeNode(AbstractMaterialNode node)
{
node.Concretize();
}
public static void ConcretizeProperties(GraphData graph)
{
var propertyNodes = graph.GetNodes<PropertyNode>().Where(n => !graph.m_Properties.Any(p => p == n.property)).ToArray();
foreach (var pNode in propertyNodes)
graph.ReplacePropertyNodeWithConcreteNodeNoValidate(pNode);
}
public static void ConcretizeGraph(GraphData graph)
{
ConcretizeProperties(graph);
GraphDataUtils.ApplyActionLeafFirst(graph, ConcretizeNode);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
using System;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEngine.Pool;
namespace UnityEditor.ShaderGraph
{
sealed partial class GraphData : ISerializationCallbackReceiver
{
public static class GraphDataUtils
{
public static void ApplyActionLeafFirst(GraphData graph, Action<AbstractMaterialNode> action)
{
var temporaryMarks = PooledHashSet<string>.Get();
var permanentMarks = PooledHashSet<string>.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 graph.GetNodes<AbstractMaterialNode>())
{
stack.Push(node);
}
while (stack.Count > 0)
{
var node = stack.Pop();
if (permanentMarks.Contains(node.objectId))
{
continue;
}
if (temporaryMarks.Contains(node.objectId))
{
action.Invoke(node);
permanentMarks.Add(node.objectId);
}
else
{
temporaryMarks.Add(node.objectId);
stack.Push(node);
node.GetInputSlots(slots);
foreach (var inputSlot in slots)
{
var nodeEdges = graph.GetEdges(inputSlot.slotReference);
foreach (var edge in nodeEdges)
{
var fromSocketRef = edge.outputSlot;
var childNode = fromSocketRef.node;
if (childNode != null)
{
stack.Push(childNode);
}
}
}
slots.Clear();
}
}
StackPool<AbstractMaterialNode>.Release(stack);
ListPool<MaterialSlot>.Release(slots);
temporaryMarks.Dispose();
permanentMarks.Dispose();
}
}
}
}

View File

@@ -0,0 +1,20 @@
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
sealed partial class GraphData : ISerializationCallbackReceiver
{
public static class GraphSetup
{
public static void SetupNode(AbstractMaterialNode node)
{
node.Setup();
}
public static void SetupGraph(GraphData graph)
{
GraphDataUtils.ApplyActionLeafFirst(graph, SetupNode);
}
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
sealed partial class GraphData : ISerializationCallbackReceiver
{
public static class GraphValidation
{
public static void ValidateNode(AbstractMaterialNode node)
{
Type t = node.GetType();
node.ValidateNode();
if (!(node is BlockNode))
{
bool disallowedByAnyTargets = false;
bool disallowedByAllTargets = true;
IEnumerable<Target> targets = node.owner.activeTargets;
if (node.owner.isSubGraph)
{
targets = node.owner.allPotentialTargets;
}
foreach (var target in targets)
{
//if at least one target doesn't allow a node, it is considered invalid
if (!target.IsNodeAllowedByTarget(t))
{
disallowedByAnyTargets = true;
node.isValid = false;
node.owner.AddValidationError(node.objectId, $"{node.name} Node is not allowed by {target.displayName} implementation", Rendering.ShaderCompilerMessageSeverity.Warning);
node.owner.m_UnsupportedTargets.Add(target);
}
//at least one target does allow node, not going to be explicitly set inactive
else
{
disallowedByAllTargets = false;
}
}
if (!disallowedByAnyTargets)
{
node.isValid = true;
}
//Set ActiveState based on if all targets disallow this node
if (disallowedByAllTargets)
{
node.SetOverrideActiveState(AbstractMaterialNode.ActiveState.ExplicitInactive);
node.owner.AddValidationError(node.objectId, $"{node.name} Node is not allowed by any active targets, and will not be used in generation", Rendering.ShaderCompilerMessageSeverity.Warning);
}
else
{
node.SetOverrideActiveState(AbstractMaterialNode.ActiveState.Implicit);
}
}
}
public static void ValidateGraph(GraphData graph)
{
graph.m_UnsupportedTargets.Clear();
GraphDataUtils.ApplyActionLeafFirst(graph, ValidateNode);
}
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
public class GroupData : JsonObject
{
[SerializeField]
string m_Title;
public string title
{
get { return m_Title; }
set { m_Title = value; }
}
[SerializeField]
Vector2 m_Position;
public Vector2 position
{
get { return m_Position; }
set { m_Position = value; }
}
public GroupData() : base() {}
public GroupData(string title, Vector2 position)
{
m_Title = title;
m_Position = position;
}
}
}

View File

@@ -0,0 +1,3 @@
namespace UnityEditor.ShaderGraph
{
}

View File

@@ -0,0 +1,8 @@
namespace UnityEditor.ShaderGraph
{
interface IMaterialSlotHasValue<T>
{
T defaultValue { get; }
T value { get; }
}
}

View File

@@ -0,0 +1,56 @@
using System;
namespace UnityEditor.ShaderGraph.Internal
{
internal static class LightmappingShaderProperties
{
public class LightmapTextureArrayProperty : Texture2DArrayShaderProperty
{
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
// no declaration from ShaderGraph side -- declared by SRP internal include files
}
internal override string GetPropertyAsArgumentString()
{
return String.Empty;
}
}
public static readonly LightmapTextureArrayProperty kLightmapsArray = new LightmapTextureArrayProperty()
{
displayName = "unity_Lightmaps",
generatePropertyBlock = true,
overrideHLSLDeclaration = false,
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
hidden = true,
modifiable = true,
overrideReferenceName = "unity_Lightmaps",
precision = Precision.Single
};
public static readonly LightmapTextureArrayProperty kLightmapsIndirectionArray = new LightmapTextureArrayProperty()
{
displayName = "unity_LightmapsInd",
generatePropertyBlock = true,
overrideHLSLDeclaration = false,
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
hidden = true,
modifiable = true,
overrideReferenceName = "unity_LightmapsInd",
precision = Precision.Single
};
public static readonly LightmapTextureArrayProperty kShadowMasksArray = new LightmapTextureArrayProperty()
{
displayName = "unity_ShadowMasks",
generatePropertyBlock = true,
overrideHLSLDeclaration = false,
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
hidden = true,
modifiable = true,
overrideReferenceName = "unity_ShadowMasks",
precision = Precision.Single
};
}
}

View File

@@ -0,0 +1,338 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
abstract class MaterialSlot : JsonObject
{
const string k_NotInit = "Not Initilaized";
[SerializeField]
int m_Id;
[SerializeField]
string m_DisplayName = k_NotInit;
[SerializeField]
SlotType m_SlotType = SlotType.Input;
[SerializeField]
bool m_Hidden;
[SerializeField]
string m_ShaderOutputName;
[SerializeField]
ShaderStageCapability m_StageCapability;
bool m_HasError;
protected MaterialSlot() {}
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
{
m_Id = slotId;
m_DisplayName = displayName;
m_SlotType = slotType;
m_Hidden = hidden;
m_ShaderOutputName = shaderOutputName;
this.stageCapability = stageCapability;
}
internal void SetInternalData(SlotType slotType, string shaderOutputName)
{
this.m_SlotType = slotType;
this.shaderOutputName = shaderOutputName;
}
public virtual VisualElement InstantiateControl()
{
return null;
}
static string ConcreteSlotValueTypeAsString(ConcreteSlotValueType type)
{
switch (type)
{
case ConcreteSlotValueType.Vector1:
return "(1)";
case ConcreteSlotValueType.Vector2:
return "(2)";
case ConcreteSlotValueType.Vector3:
return "(3)";
case ConcreteSlotValueType.Vector4:
return "(4)";
case ConcreteSlotValueType.Boolean:
return "(B)";
case ConcreteSlotValueType.Matrix2:
return "(2x2)";
case ConcreteSlotValueType.Matrix3:
return "(3x3)";
case ConcreteSlotValueType.Matrix4:
return "(4x4)";
case ConcreteSlotValueType.SamplerState:
return "(SS)";
case ConcreteSlotValueType.Texture2D:
return "(T2)";
case ConcreteSlotValueType.Texture2DArray:
return "(T2A)";
case ConcreteSlotValueType.Texture3D:
return "(T3)";
case ConcreteSlotValueType.Cubemap:
return "(C)";
case ConcreteSlotValueType.Gradient:
return "(G)";
case ConcreteSlotValueType.VirtualTexture:
return "(VT)";
default:
return "(E)";
}
}
public virtual string displayName
{
get { return m_DisplayName + ConcreteSlotValueTypeAsString(concreteValueType); }
set { m_DisplayName = value; }
}
public string RawDisplayName()
{
return m_DisplayName;
}
public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStageCapability shaderStageCapability = ShaderStageCapability.All, bool hidden = false)
{
switch (type)
{
case SlotValueType.SamplerState:
return new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.DynamicMatrix:
return new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.Matrix4:
return new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.Matrix3:
return new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.Matrix2:
return new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.Texture2D:
return slotType == SlotType.Input
? new Texture2DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.Texture2DArray:
return slotType == SlotType.Input
? new Texture2DArrayInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new Texture2DArrayMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.Texture3D:
return slotType == SlotType.Input
? new Texture3DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new Texture3DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.Cubemap:
return slotType == SlotType.Input
? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.VirtualTexture:
return slotType == SlotType.Input
? new VirtualTextureInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new VirtualTextureMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.Gradient:
return slotType == SlotType.Input
? new GradientInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden)
: new GradientMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden);
case SlotValueType.DynamicVector:
return new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden);
case SlotValueType.Vector4:
return new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
case SlotValueType.Vector3:
return new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
case SlotValueType.Vector2:
return new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden);
case SlotValueType.Vector1:
return new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStageCapability, hidden: hidden);
case SlotValueType.Dynamic:
return new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStageCapability, hidden);
case SlotValueType.Boolean:
return new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStageCapability, hidden);
}
throw new ArgumentOutOfRangeException("type", type, null);
}
public SlotReference slotReference
{
get { return new SlotReference(owner, m_Id); }
}
public AbstractMaterialNode owner { get; set; }
// if hidden, the slot does not create a port in the UI
public bool hidden
{
get { return m_Hidden; }
set { m_Hidden = value; }
}
public int id
{
get { return m_Id; }
}
public bool isInputSlot
{
get { return m_SlotType == SlotType.Input; }
}
public bool isOutputSlot
{
get { return m_SlotType == SlotType.Output; }
}
public SlotType slotType
{
get { return m_SlotType; }
}
public bool isConnected
{
get
{
// node and graph respectivly
if (owner == null || owner.owner == null)
return false;
var graph = owner.owner;
var edges = graph.GetEdges(slotReference);
return edges.Any();
}
}
public abstract bool isDefaultValue { get; }
public abstract SlotValueType valueType { get; }
public abstract ConcreteSlotValueType concreteValueType { get; }
public string shaderOutputName
{
get { return m_ShaderOutputName; }
private set { m_ShaderOutputName = value; }
}
public ShaderStageCapability stageCapability
{
get { return m_StageCapability; }
set { m_StageCapability = value; }
}
public bool hasError
{
get { return m_HasError; }
set { m_HasError = value; }
}
public bool IsUsingDefaultValue()
{
if (!isConnected && isDefaultValue)
return true;
else
return false;
}
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)));
}
public bool IsCompatibleStageWith(MaterialSlot otherSlot)
{
var candidateStage = otherSlot.stageCapability;
return stageCapability == ShaderStageCapability.All || candidateStage == stageCapability;
}
public string GetDefaultValue(GenerationMode generationMode, ConcretePrecision concretePrecision)
{
string defaultValue = GetDefaultValue(generationMode);
return defaultValue.Replace(PrecisionUtil.Token, concretePrecision.ToShaderString());
}
public virtual string GetDefaultValue(GenerationMode generationMode)
{
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
if (generationMode.IsPreview() && matOwner.isActive)
return matOwner.GetVariableNameForSlot(id);
return ConcreteSlotValueAsVariable();
}
protected virtual string ConcreteSlotValueAsVariable()
{
return "error";
}
public abstract void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode);
public virtual void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
properties.Add(default(PreviewProperty));
}
public virtual void AppendHLSLParameterDeclaration(ShaderStringBuilder sb, string paramName)
{
sb.Append(concreteValueType.ToShaderString());
sb.Append(" ");
sb.Append(paramName);
}
public abstract void CopyValuesFrom(MaterialSlot foundSlot);
public bool Equals(MaterialSlot other)
{
return m_Id == other.m_Id && owner == other.owner;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((MaterialSlot)obj);
}
public override int GetHashCode()
{
unchecked
{
return (m_Id * 397) ^ (owner != null ? owner.GetHashCode() : 0);
}
}
// this tracks old CustomFunctionNode slots that are expecting the old bare resource inputs
// rather than the new structure-based inputs
internal virtual bool bareResource { get { return false; } set {} }
public virtual void CopyDefaultValue(MaterialSlot other)
{
m_Id = other.m_Id;
m_DisplayName = other.m_DisplayName;
m_SlotType = other.m_SlotType;
m_Hidden = other.m_Hidden;
m_ShaderOutputName = other.m_ShaderOutputName;
m_StageCapability = other.m_StageCapability;
}
}
}

View File

@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Matrix2MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
{
[SerializeField]
private Matrix4x4 m_Value = Matrix4x4.identity;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
public Matrix2MaterialSlot()
{
}
public Matrix2MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Identity");
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
protected override string ConcreteSlotValueAsVariable()
{
return "$precision2x2 (1,0,0,1)";
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new Matrix2ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Matrix2)
{
name = name,
matrixValue = value
};
properties.Add(pp);
}
public override SlotValueType valueType { get { return SlotValueType.Matrix2; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Matrix2; } }
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Matrix2MaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Matrix4x4> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,65 @@
using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[BlackboardInputInfo(70)]
class Matrix2ShaderProperty : MatrixShaderProperty
{
public Matrix2ShaderProperty()
{
displayName = "Matrix2x2";
value = Matrix4x4.identity;
}
public override PropertyType propertyType => PropertyType.Matrix2;
internal override string GetPropertyAsArgumentString()
{
return $"{concretePrecision.ToShaderString()}2x2 {referenceName}";
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new Matrix2Node
{
row0 = new Vector2(value.m00, value.m01),
row1 = new Vector2(value.m10, value.m11)
};
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
matrixValue = value
};
}
internal override ShaderInput Copy()
{
return new Matrix2ShaderProperty()
{
displayName = displayName,
value = value,
};
}
public override int latestVersion => 1;
public override void OnAfterDeserialize(string json)
{
if (sgVersion == 0)
{
// all old matrices were declared global; yes even if flagged hybrid!
// maintain old behavior on versioning, users can always change the override if they wish
overrideHLSLDeclaration = true;
hlslDeclarationOverride = HLSLDeclaration.Global;
ChangeVersion(1);
}
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Matrix3MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
{
[SerializeField]
private Matrix4x4 m_Value = Matrix4x4.identity;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
public Matrix3MaterialSlot()
{
}
public Matrix3MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Identity");
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
protected override string ConcreteSlotValueAsVariable()
{
return "$precision3x3 (1,0,0,0,1,0,0,0,1)";
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new Matrix3ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Matrix3)
{
name = name,
matrixValue = value
};
properties.Add(pp);
}
public override SlotValueType valueType { get { return SlotValueType.Matrix3; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Matrix3; } }
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Matrix3MaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Matrix4x4> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[BlackboardInputInfo(71)]
class Matrix3ShaderProperty : MatrixShaderProperty
{
public Matrix3ShaderProperty()
{
displayName = "Matrix3x3";
value = Matrix4x4.identity;
}
public override PropertyType propertyType => PropertyType.Matrix3;
internal override string GetPropertyAsArgumentString()
{
return $"{concretePrecision.ToShaderString()}3x3 {referenceName}";
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new Matrix3Node
{
row0 = new Vector3(value.m00, value.m01, value.m02),
row1 = new Vector3(value.m10, value.m11, value.m12),
row2 = new Vector3(value.m20, value.m21, value.m22)
};
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
matrixValue = value
};
}
internal override ShaderInput Copy()
{
return new Matrix3ShaderProperty()
{
displayName = displayName,
value = value,
};
}
public override int latestVersion => 1;
public override void OnAfterDeserialize(string json)
{
if (sgVersion == 0)
{
// all old matrices were declared global; yes even if flagged hybrid!
// maintain old behavior on versioning, users can always change the override if they wish
overrideHLSLDeclaration = true;
hlslDeclarationOverride = HLSLDeclaration.Global;
ChangeVersion(1);
}
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Matrix4MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Matrix4x4>
{
[SerializeField]
private Matrix4x4 m_Value = Matrix4x4.identity;
[SerializeField]
private Matrix4x4 m_DefaultValue = Matrix4x4.identity;
public Matrix4MaterialSlot()
{
}
public Matrix4MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Identity");
}
public Matrix4x4 defaultValue { get { return m_DefaultValue; } }
public Matrix4x4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
protected override string ConcreteSlotValueAsVariable()
{
return "$precision4x4 (1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)";
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new Matrix4ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Matrix4)
{
name = name,
matrixValue = value
};
properties.Add(pp);
}
public override SlotValueType valueType { get { return SlotValueType.Matrix4; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Matrix4; } }
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Matrix4MaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Matrix4x4> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[BlackboardInputInfo(72)]
class Matrix4ShaderProperty : MatrixShaderProperty
{
public Matrix4ShaderProperty()
{
displayName = "Matrix4x4";
value = Matrix4x4.identity;
}
public override PropertyType propertyType => PropertyType.Matrix4;
internal override string GetPropertyAsArgumentString()
{
return $"{concretePrecision.ToShaderString()}4x4 {referenceName}";
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new Matrix4Node
{
row0 = new Vector4(value.m00, value.m01, value.m02, value.m03),
row1 = new Vector4(value.m10, value.m11, value.m12, value.m13),
row2 = new Vector4(value.m20, value.m21, value.m22, value.m23),
row3 = new Vector4(value.m30, value.m31, value.m32, value.m33)
};
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
matrixValue = value
};
}
internal override ShaderInput Copy()
{
return new Matrix4ShaderProperty()
{
displayName = displayName,
value = value,
};
}
public override int latestVersion => 1;
public override void OnAfterDeserialize(string json)
{
if (sgVersion == 0)
{
// all old matrices were declared global; yes even if flagged hybrid!
// maintain old behavior on versioning, users can always change the override if they wish
overrideHLSLDeclaration = true;
hlslDeclarationOverride = HLSLDeclaration.Global;
ChangeVersion(1);
}
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
abstract class MatrixShaderProperty : AbstractShaderProperty<Matrix4x4>
{
internal override bool isExposable => false;
internal override bool isRenamable => true;
internal override HLSLDeclaration GetDefaultHLSLDeclaration()
{
if (overrideHLSLDeclaration)
return hlslDeclarationOverride;
// Since Matrices cannot be exposed, the default declaration rules would set them to Global.
// However, this means new Matrix properties would be different from all other float-based property types
// (all others use UnityPerMaterial by default, because they are exposed).
// So instead, we override the default rules so that Matrices always default to UnityPerMaterial
return HLSLDeclaration.UnityPerMaterial;
}
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
HLSLDeclaration decl = GetDefaultHLSLDeclaration();
// HLSL decl is always 4x4 even if matrix smaller
action(new HLSLProperty(HLSLType._matrix4x4, referenceName, decl, concretePrecision));
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Legacy;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
/// <summary>
/// Minimal version of <see cref="GraphData"/> used for gathering dependencies. This allows us to not deserialize
/// all the nodes, ports, edges, groups etc., which is important as we cannot share data between
/// <see cref="ShaderSubGraphImporter.GatherDependenciesFromSourceFile"/> and
/// <see cref="ShaderSubGraphImporter.OnImportAsset"/>. The latter must always import fully, but for the former we
/// want to avoid the extra GC pressure.
/// </summary>
[Serializable]
class MinimalGraphData
{
static Dictionary<string, Type> s_MinimalTypeMap = CreateMinimalTypeMap();
static Dictionary<string, Type> CreateMinimalTypeMap()
{
var types = new Dictionary<string, Type>();
foreach (var type in TypeCache.GetTypesWithAttribute<HasDependenciesAttribute>())
{
var dependencyAttribute = (HasDependenciesAttribute)type.GetCustomAttributes(typeof(HasDependenciesAttribute), false)[0];
if (!typeof(IHasDependencies).IsAssignableFrom(dependencyAttribute.minimalType))
{
Debug.LogError($"{type} must implement {typeof(IHasDependencies)} to be used in {typeof(HasDependenciesAttribute)}");
continue;
}
types.Add(type.FullName, dependencyAttribute.minimalType);
var formerNameAttributes = (FormerNameAttribute[])type.GetCustomAttributes(typeof(FormerNameAttribute), false);
foreach (var formerNameAttribute in formerNameAttributes)
{
types.Add(formerNameAttribute.fullName, dependencyAttribute.minimalType);
}
}
return types;
}
[SerializeField]
List<SerializationHelper.JSONSerializedElement> m_SerializableNodes = new List<SerializationHelper.JSONSerializedElement>();
// gather all asset dependencies declared by nodes in the given (shadergraph or shadersubgraph) asset
// by reading the source file from disk, and doing a minimal parse
// returns true if it successfully gathered the dependencies, false if there was an error
public static bool GatherMinimalDependenciesFromFile(string assetPath, AssetCollection assetCollection)
{
var textGraph = FileUtilities.SafeReadAllText(assetPath);
// if we can't read the file, no dependencies can be gathered
if (string.IsNullOrEmpty(textGraph))
return false;
var entries = MultiJsonInternal.Parse(textGraph);
if (string.IsNullOrWhiteSpace(entries[0].type))
{
var minimalGraphData = JsonUtility.FromJson<MinimalGraphData>(textGraph);
entries.Clear();
foreach (var node in minimalGraphData.m_SerializableNodes)
{
entries.Add(new MultiJsonEntry(node.typeInfo.fullName, null, node.JSONnodeData));
AbstractMaterialNode0 amn = new AbstractMaterialNode0();
JsonUtility.FromJsonOverwrite(node.JSONnodeData, amn);
foreach (var slot in amn.m_SerializableSlots)
{
entries.Add(new MultiJsonEntry(slot.typeInfo.fullName, null, slot.JSONnodeData));
}
}
}
foreach (var entry in entries)
{
if (s_MinimalTypeMap.TryGetValue(entry.type, out var minimalType))
{
var instance = (IHasDependencies)Activator.CreateInstance(minimalType);
JsonUtility.FromJsonOverwrite(entry.json, instance);
instance.GetSourceAssetDependencies(assetCollection);
}
}
return true;
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class NormalMaterialSlot : SpaceMaterialSlot, IMayRequireNormal
{
public NormalMaterialSlot()
{}
public NormalMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView(space + " Space");
}
public override string GetDefaultValue(GenerationMode generationMode)
{
return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Normal));
}
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;
return space.ToNeededCoordinateSpace();
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
struct ParentGroupChange
{
public IGroupItem groupItem;
public GroupData oldGroup;
public GroupData newGroup;
}
}

View File

@@ -0,0 +1,36 @@
using System;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class PositionMaterialSlot : SpaceMaterialSlot, IMayRequirePosition
{
public PositionMaterialSlot()
{}
public PositionMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView(space + " Space");
}
public override string GetDefaultValue(GenerationMode generationMode)
{
return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Position));
}
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;
return space.ToNeededCoordinateSpace();
}
}
}

View File

@@ -0,0 +1,9 @@
namespace UnityEditor.ShaderGraph
{
enum PreviewMode
{
Inherit, // this usually means: 2D, unless a connected input node is 3D, in which case it is 3D
Preview2D,
Preview3D
}
}

View File

@@ -0,0 +1,283 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
struct PreviewProperty
{
public string name { get; set; }
public PropertyType propType { get; private set; }
public PreviewProperty(PropertyType type) : this()
{
propType = type;
}
[StructLayout(LayoutKind.Explicit)]
struct ClassData
{
[FieldOffset(0)]
public Texture textureValue;
[FieldOffset(0)]
public Cubemap cubemapValue;
[FieldOffset(0)]
public Gradient gradientValue;
[FieldOffset(0)]
public VirtualTextureShaderProperty vtProperty;
}
[StructLayout(LayoutKind.Explicit)]
struct StructData
{
[FieldOffset(0)]
public Color colorValue;
[FieldOffset(0)]
public Vector4 vector4Value;
[FieldOffset(0)]
public float floatValue;
[FieldOffset(0)]
public bool booleanValue;
[FieldOffset(0)]
public Matrix4x4 matrixValue;
}
ClassData m_ClassData;
StructData m_StructData;
Texture2DShaderProperty.DefaultType m_texture2dDefaultType;
public Color colorValue
{
get
{
if (propType != PropertyType.Color)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Color, propType));
return m_StructData.colorValue;
}
set
{
if (propType != PropertyType.Color)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Color, propType));
m_StructData.colorValue = value;
}
}
public Texture textureValue
{
get
{
if (propType != PropertyType.Texture2D && propType != PropertyType.Texture2DArray && propType != PropertyType.Texture3D)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Texture2D, propType));
return m_ClassData.textureValue;
}
set
{
if (propType != PropertyType.Texture2D && propType != PropertyType.Texture2DArray && propType != PropertyType.Texture3D)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Texture2D, propType));
m_ClassData.textureValue = value;
}
}
public Texture2DShaderProperty.DefaultType texture2DDefaultType
{
get
{
if (propType != PropertyType.Texture2D)
throw new ArgumentException(string.Format(k_GetErrorMessage, "Texture2DShaderProperty.DefaultType", propType));
return m_texture2dDefaultType;
}
set
{
if (propType != PropertyType.Texture2D)
throw new ArgumentException(string.Format(k_GetErrorMessage, "Texture2DShaderProperty.DefaultType", propType));
m_texture2dDefaultType = value;
}
}
public Cubemap cubemapValue
{
get
{
if (propType != PropertyType.Cubemap)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Cubemap, propType));
return m_ClassData.cubemapValue;
}
set
{
if (propType != PropertyType.Cubemap)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Cubemap, propType));
m_ClassData.cubemapValue = value;
}
}
public Gradient gradientValue
{
get
{
if (propType != PropertyType.Gradient)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Gradient, propType));
return m_ClassData.gradientValue;
}
set
{
if (propType != PropertyType.Gradient)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Gradient, propType));
m_ClassData.gradientValue = value;
}
}
public VirtualTextureShaderProperty vtProperty
{
get
{
if (propType != PropertyType.VirtualTexture)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Gradient, propType));
return m_ClassData.vtProperty;
}
set
{
if (propType != PropertyType.VirtualTexture)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Gradient, propType));
m_ClassData.vtProperty = value;
}
}
public Vector4 vector4Value
{
get
{
if (propType != PropertyType.Vector2 && propType != PropertyType.Vector3 && propType != PropertyType.Vector4)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Vector4, propType));
return m_StructData.vector4Value;
}
set
{
if (propType != PropertyType.Vector2 && propType != PropertyType.Vector3 && propType != PropertyType.Vector4
&& propType != PropertyType.Matrix2 && propType != PropertyType.Matrix3 && propType != PropertyType.Matrix4)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Vector4, propType));
m_StructData.vector4Value = value;
}
}
public float floatValue
{
get
{
if (propType != PropertyType.Float)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Float, propType));
return m_StructData.floatValue;
}
set
{
if (propType != PropertyType.Float)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Float, propType));
m_StructData.floatValue = value;
}
}
public bool booleanValue
{
get
{
if (propType != PropertyType.Boolean)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Boolean, propType));
return m_StructData.booleanValue;
}
set
{
if (propType != PropertyType.Boolean)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Boolean, propType));
m_StructData.booleanValue = value;
}
}
public Matrix4x4 matrixValue
{
get
{
if (propType != PropertyType.Matrix2 && propType != PropertyType.Matrix3 && propType != PropertyType.Matrix4)
throw new ArgumentException(string.Format(k_GetErrorMessage, PropertyType.Boolean, propType));
return m_StructData.matrixValue;
}
set
{
if (propType != PropertyType.Matrix2 && propType != PropertyType.Matrix3 && propType != PropertyType.Matrix4)
throw new ArgumentException(string.Format(k_SetErrorMessage, PropertyType.Boolean, propType));
m_StructData.matrixValue = value;
}
}
const string k_SetErrorMessage = "Cannot set a {0} property on a PreviewProperty with type {1}.";
const string k_GetErrorMessage = "Cannot get a {0} property on a PreviewProperty with type {1}.";
public void SetValueOnMaterialPropertyBlock(MaterialPropertyBlock mat)
{
if ((propType == PropertyType.Texture2D || propType == PropertyType.Texture2DArray || propType == PropertyType.Texture3D))
{
if (m_ClassData.textureValue == null)
{
// there's no way to set the texture back to NULL
// and no way to delete the property either
// so instead we set the value to what we know the default will be
// (all textures in ShaderGraph default to white)
switch (m_texture2dDefaultType)
{
case Texture2DShaderProperty.DefaultType.White:
mat.SetTexture(name, Texture2D.whiteTexture);
break;
case Texture2DShaderProperty.DefaultType.Black:
mat.SetTexture(name, Texture2D.blackTexture);
break;
case Texture2DShaderProperty.DefaultType.Grey:
mat.SetTexture(name, Texture2D.grayTexture);
break;
case Texture2DShaderProperty.DefaultType.Bump:
mat.SetTexture(name, Texture2D.normalTexture);
break;
}
}
else
mat.SetTexture(name, m_ClassData.textureValue);
}
else if (propType == PropertyType.Cubemap)
{
if (m_ClassData.cubemapValue == null)
{
// there's no way to set the texture back to NULL
// and no way to delete the property either
// so instead we set the value to what we know the default will be
// (all textures in ShaderGraph default to white)
// there's no Cubemap.whiteTexture, but this seems to work
mat.SetTexture(name, Texture2D.whiteTexture);
}
else
mat.SetTexture(name, m_ClassData.cubemapValue);
}
else if (propType == PropertyType.Color)
mat.SetColor(name, m_StructData.colorValue);
else if (propType == PropertyType.Vector2 || propType == PropertyType.Vector3 || propType == PropertyType.Vector4)
mat.SetVector(name, m_StructData.vector4Value);
else if (propType == PropertyType.Float)
mat.SetFloat(name, m_StructData.floatValue);
else if (propType == PropertyType.Boolean)
mat.SetFloat(name, m_StructData.booleanValue ? 1 : 0);
else if (propType == PropertyType.Matrix2 || propType == PropertyType.Matrix3 || propType == PropertyType.Matrix4)
mat.SetMatrix(name, m_StructData.matrixValue);
else if (propType == PropertyType.Gradient)
{
mat.SetFloat(string.Format("{0}_Type", name), (int)m_ClassData.gradientValue.mode);
mat.SetFloat(string.Format("{0}_ColorsLength", name), m_ClassData.gradientValue.colorKeys.Length);
mat.SetFloat(string.Format("{0}_AlphasLength", name), m_ClassData.gradientValue.alphaKeys.Length);
for (int i = 0; i < 8; i++)
mat.SetVector(string.Format("{0}_ColorKey{1}", name, i), i < m_ClassData.gradientValue.colorKeys.Length ? GradientUtil.ColorKeyToVector(m_ClassData.gradientValue.colorKeys[i]) : Vector4.zero);
for (int i = 0; i < 8; i++)
mat.SetVector(string.Format("{0}_AlphaKey{1}", name, i), i < m_ClassData.gradientValue.alphaKeys.Length ? GradientUtil.AlphaKeyToVector(m_ClassData.gradientValue.alphaKeys[i]) : Vector2.zero);
}
else if (propType == PropertyType.VirtualTexture)
{
// virtual texture assignments are not supported via the material property block, we must assign them to the materials
}
}
}
}

View File

@@ -0,0 +1,81 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class SamplerStateMaterialSlot : MaterialSlot
{
public SamplerStateMaterialSlot()
{
}
public SamplerStateMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
}
[SerializeField]
bool m_BareResource = false;
internal override bool bareResource
{
get { return m_BareResource; }
set { m_BareResource = value; }
}
public override void AppendHLSLParameterDeclaration(ShaderStringBuilder sb, string paramName)
{
if (m_BareResource)
{
// we have to use our modified macro declaration here, to ensure that something is declared for GLES2 platforms
// (the standard SAMPLER macro doesn't declare anything, so the commas will be messed up in the parameter list)
sb.Append("UNITY_BARE_SAMPLER(");
sb.Append(paramName);
sb.Append(")");
}
else
base.AppendHLSLParameterDeclaration(sb, paramName);
}
public override string GetDefaultValue(GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
return "UnityBuildSamplerStateStruct(SamplerState_Linear_Repeat)";
}
public override SlotValueType valueType { get { return SlotValueType.SamplerState; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.SamplerState; } }
public override bool isDefaultValue => true;
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
properties.AddShaderProperty(new SamplerStateShaderProperty()
{
value = new TextureSamplerState()
{
filter = TextureSamplerState.FilterMode.Linear,
wrap = TextureSamplerState.WrapMode.Repeat
},
overrideReferenceName = "SamplerState_Linear_Repeat",
generatePropertyBlock = false,
});
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[BlackboardInputInfo(80)]
class SamplerStateShaderProperty : AbstractShaderProperty<TextureSamplerState>
{
public SamplerStateShaderProperty()
{
displayName = "SamplerState";
value = new TextureSamplerState();
}
public override PropertyType propertyType => PropertyType.SamplerState;
internal override bool isExposable => false;
internal override bool isRenamable => false;
public override TextureSamplerState value
{
get => base.value;
set
{
overrideReferenceName = $"SamplerState_{value.filter}_{value.wrap}";
base.value = value;
}
}
internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => false; // disable UI, nothing to choose
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
action(new HLSLProperty(HLSLType._SamplerState, referenceName, HLSLDeclaration.Global));
}
internal override string GetPropertyAsArgumentString()
{
return $"UnitySamplerState {referenceName}";
}
internal override string GetHLSLVariableName(bool isSubgraphProperty)
{
if (isSubgraphProperty)
return referenceName;
else
return $"UnityBuildSamplerStateStruct({referenceName})";
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new SamplerStateNode()
{
filter = value.filter,
wrap = value.wrap
};
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return default(PreviewProperty);
}
internal override ShaderInput Copy()
{
return new SamplerStateShaderProperty()
{
displayName = displayName,
value = value,
};
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class ScreenPositionMaterialSlot : Vector4MaterialSlot, IMayRequireScreenPosition
{
[SerializeField]
ScreenSpaceType m_ScreenSpaceType;
public ScreenSpaceType screenSpaceType
{
get { return m_ScreenSpaceType; }
set { m_ScreenSpaceType = value; }
}
public override bool isDefaultValue => screenSpaceType == ScreenSpaceType.Default;
public ScreenPositionMaterialSlot()
{}
public ScreenPositionMaterialSlot(int slotId, string displayName, string shaderOutputName, ScreenSpaceType screenSpaceType,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{
this.screenSpaceType = screenSpaceType;
}
public override VisualElement InstantiateControl()
{
return new ScreenPositionSlotControlView(this);
}
public override string GetDefaultValue(GenerationMode generationMode)
{
return m_ScreenSpaceType.ToValueAsVariable();
}
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
return !isConnected;
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as ScreenPositionMaterialSlot;
if (slot != null)
screenSpaceType = slot.screenSpaceType;
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
public sealed class SerializableCubemap : ISerializationCallbackReceiver
{
[SerializeField]
string m_SerializedCubemap;
[SerializeField]
string m_Guid;
[NonSerialized]
Cubemap m_Cubemap;
[Serializable]
class CubemapHelper
{
#pragma warning disable 649
public Cubemap cubemap;
#pragma warning restore 649
}
// used to get a Cubemap ref guid without loading the cubemap asset itself into memory
[Serializable]
class MinimalCubemapHelper
{
// these variables are only ever populated by serialization, disable the C# warning that checks if they are ever assigned
#pragma warning disable 0649
[Serializable]
public struct MinimalTextureRef
{
public string guid;
}
public MinimalTextureRef cubemap;
#pragma warning restore 0649
}
internal string guid
{
get
{
if (!string.IsNullOrEmpty(m_SerializedCubemap))
{
var textureHelper = new MinimalCubemapHelper();
EditorJsonUtility.FromJsonOverwrite(m_SerializedCubemap, textureHelper);
if (!string.IsNullOrEmpty(textureHelper.cubemap.guid))
return textureHelper.cubemap.guid;
}
if (!string.IsNullOrEmpty(m_Guid))
{
return m_Guid;
}
if (m_Cubemap != null)
{
if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(m_Cubemap, out string guid, out long localId))
return guid;
}
return null;
}
}
public Cubemap cubemap
{
get
{
if (!string.IsNullOrEmpty(m_SerializedCubemap))
{
var textureHelper = new CubemapHelper();
EditorJsonUtility.FromJsonOverwrite(m_SerializedCubemap, textureHelper);
m_SerializedCubemap = null;
m_Guid = null;
m_Cubemap = textureHelper.cubemap;
}
else if (!string.IsNullOrEmpty(m_Guid) && m_Cubemap == null)
{
m_Cubemap = AssetDatabase.LoadAssetAtPath<Cubemap>(AssetDatabase.GUIDToAssetPath(m_Guid));
m_Guid = null;
}
return m_Cubemap;
}
set
{
m_Cubemap = value;
m_Guid = null;
m_SerializedCubemap = null;
}
}
public void OnBeforeSerialize()
{
m_SerializedCubemap = EditorJsonUtility.ToJson(new CubemapHelper { cubemap = cubemap }, false);
}
public void OnAfterDeserialize()
{
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class SerializableGuid : ISerializationCallbackReceiver
{
public SerializableGuid()
{
m_Guid = Guid.NewGuid();
}
public SerializableGuid(Guid guid)
{
m_Guid = guid;
}
[NonSerialized]
private Guid m_Guid;
[SerializeField]
private string m_GuidSerialized;
public Guid guid
{
get { return m_Guid; }
internal set { m_Guid = value; } // allow id to be overwritten when necessary
}
public virtual void OnBeforeSerialize()
{
m_GuidSerialized = m_Guid.ToString();
}
public virtual void OnAfterDeserialize()
{
if (!string.IsNullOrEmpty(m_GuidSerialized))
m_Guid = new Guid(m_GuidSerialized);
else
m_Guid = Guid.NewGuid();
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class SerializableMesh : ISerializationCallbackReceiver
{
[SerializeField]
string m_SerializedMesh;
[SerializeField]
string m_Guid;
[NonSerialized]
Mesh m_Mesh;
[Serializable]
class MeshHelper
{
#pragma warning disable 649
public Mesh mesh;
#pragma warning restore 649
}
public Mesh mesh
{
get
{
if (!string.IsNullOrEmpty(m_SerializedMesh))
{
var textureHelper = new MeshHelper();
EditorJsonUtility.FromJsonOverwrite(m_SerializedMesh, textureHelper);
m_SerializedMesh = null;
m_Guid = null;
m_Mesh = textureHelper.mesh;
}
else if (!string.IsNullOrEmpty(m_Guid) && m_Mesh == null)
{
m_Mesh = AssetDatabase.LoadAssetAtPath<Mesh>(AssetDatabase.GUIDToAssetPath(m_Guid));
m_Guid = null;
}
return m_Mesh;
}
set
{
m_Mesh = value;
m_Guid = null;
m_SerializedMesh = null;
}
}
public void OnBeforeSerialize()
{
m_SerializedMesh = EditorJsonUtility.ToJson(new MeshHelper { mesh = mesh }, false);
}
public void OnAfterDeserialize()
{
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
public sealed class SerializableTexture : ISerializationCallbackReceiver
{
[SerializeField]
string m_SerializedTexture;
[SerializeField]
string m_Guid;
[NonSerialized]
Texture m_Texture;
[Serializable]
class TextureHelper
{
#pragma warning disable 649
public Texture texture;
#pragma warning restore 649
}
// used to get a Texture ref guid without loading the texture asset itself into memory
[Serializable]
class MinimalTextureHelper
{
// these variables are only ever populated by serialization, disable the C# warning that checks if they are ever assigned
#pragma warning disable 0649
[Serializable]
public struct MinimalTextureRef
{
public string guid;
}
public MinimalTextureRef texture;
#pragma warning restore 0649
}
internal string guid
{
get
{
if (!string.IsNullOrEmpty(m_SerializedTexture))
{
var textureHelper = new MinimalTextureHelper();
EditorJsonUtility.FromJsonOverwrite(m_SerializedTexture, textureHelper);
if (!string.IsNullOrEmpty(textureHelper.texture.guid))
return textureHelper.texture.guid;
}
if (!string.IsNullOrEmpty(m_Guid))
{
return m_Guid;
}
if (m_Texture != null)
{
if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(m_Texture, out string guid, out long localId))
return guid;
}
return null;
}
}
public Texture texture
{
get
{
if (!string.IsNullOrEmpty(m_SerializedTexture))
{
var textureHelper = new TextureHelper();
EditorJsonUtility.FromJsonOverwrite(m_SerializedTexture, textureHelper);
m_SerializedTexture = null;
m_Guid = null;
m_Texture = textureHelper.texture;
}
else if (!string.IsNullOrEmpty(m_Guid) && m_Texture == null)
{
m_Texture = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(m_Guid));
m_Guid = null;
}
return m_Texture;
}
set
{
m_Texture = value;
m_Guid = null;
m_SerializedTexture = null;
}
}
public void OnBeforeSerialize()
{
m_SerializedTexture = EditorJsonUtility.ToJson(new TextureHelper { texture = texture }, false);
}
public void OnAfterDeserialize()
{
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
public sealed class SerializableTextureArray : ISerializationCallbackReceiver
{
[SerializeField]
string m_SerializedTexture;
[SerializeField]
string m_Guid;
[NonSerialized]
Texture2DArray m_TextureArray;
[Serializable]
class TextureHelper
{
#pragma warning disable 649
public Texture2DArray textureArray;
#pragma warning restore 649
}
// used to get a Texture2DArray ref guid without loading the Texture2dArray asset itself into memory
[Serializable]
class MinimalTextureHelper
{
// these variables are only ever populated by serialization, disable the C# warning that checks if they are ever assigned
#pragma warning disable 0649
[Serializable]
public struct MinimalTextureRef
{
public string guid;
}
public MinimalTextureRef textureArray;
#pragma warning restore 0649
}
internal string guid
{
get
{
if (!string.IsNullOrEmpty(m_SerializedTexture))
{
var textureHelper = new MinimalTextureHelper();
EditorJsonUtility.FromJsonOverwrite(m_SerializedTexture, textureHelper);
if (!string.IsNullOrEmpty(textureHelper.textureArray.guid))
return textureHelper.textureArray.guid;
}
if (!string.IsNullOrEmpty(m_Guid))
{
return m_Guid;
}
if (m_TextureArray != null)
{
if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(m_TextureArray, out string guid, out long localId))
return guid;
}
return null;
}
}
public Texture2DArray textureArray
{
get
{
if (!string.IsNullOrEmpty(m_SerializedTexture))
{
var textureHelper = new TextureHelper();
EditorJsonUtility.FromJsonOverwrite(m_SerializedTexture, textureHelper);
m_SerializedTexture = null;
m_Guid = null;
m_TextureArray = textureHelper.textureArray;
}
else if (!string.IsNullOrEmpty(m_Guid) && m_TextureArray == null)
{
m_TextureArray = AssetDatabase.LoadAssetAtPath<Texture2DArray>(AssetDatabase.GUIDToAssetPath(m_Guid));
m_Guid = null;
}
return m_TextureArray;
}
set
{
m_TextureArray = value;
m_Guid = null;
m_SerializedTexture = null;
}
}
public void OnBeforeSerialize()
{
m_SerializedTexture = EditorJsonUtility.ToJson(new TextureHelper { textureArray = textureArray }, false);
}
public void OnAfterDeserialize()
{
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
enum LayerTextureType
{
Default,
NormalTangentSpace,
NormalObjectSpace
};
[Serializable]
internal class SerializableVirtualTextureLayer
{
public string layerName;
public string layerRefName;
public SerializableTexture layerTexture;
public LayerTextureType layerTextureType;
[SerializeField]
private Guid guid;
public SerializableVirtualTextureLayer(string name, string refName, SerializableTexture texture)
{
this.layerName = name; this.layerName = name;
this.guid = Guid.NewGuid();
this.layerRefName = refName; this.layerRefName = refName;
this.layerTexture = texture; this.layerTexture = texture;
this.layerTextureType = LayerTextureType.Default; this.layerTextureType = LayerTextureType.Default;
}
public SerializableVirtualTextureLayer(string name, SerializableTexture texture)
{
this.layerName = name;
this.guid = Guid.NewGuid();
this.layerRefName = $"Layer_{GuidEncoder.Encode(this.guid)}";
this.layerTexture = texture;
this.layerTextureType = LayerTextureType.Default;
}
public SerializableVirtualTextureLayer(SerializableVirtualTextureLayer other)
{
this.layerName = other.layerName;
this.guid = Guid.NewGuid();
this.layerRefName = $"Layer_{GuidEncoder.Encode(this.guid)}";
this.layerTexture = other.layerTexture;
this.layerTextureType = LayerTextureType.Default;
}
}
[Serializable]
internal sealed class SerializableVirtualTexture
{
[SerializeField]
public List<SerializableVirtualTextureLayer> layers = new List<SerializableVirtualTextureLayer>();
[SerializeField]
public bool procedural;
}
}

View File

@@ -0,0 +1,218 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
public struct ShaderGraphRequirements
{
[SerializeField] NeededCoordinateSpace m_RequiresNormal;
[SerializeField] NeededCoordinateSpace m_RequiresBitangent;
[SerializeField] NeededCoordinateSpace m_RequiresTangent;
[SerializeField] NeededCoordinateSpace m_RequiresViewDir;
[SerializeField] NeededCoordinateSpace m_RequiresPosition;
[SerializeField] bool m_RequiresScreenPosition;
[SerializeField] bool m_RequiresVertexColor;
[SerializeField] bool m_RequiresFaceSign;
[SerializeField] List<UVChannel> m_RequiresMeshUVs;
[SerializeField] bool m_RequiresDepthTexture;
[SerializeField] bool m_RequiresCameraOpaqueTexture;
[SerializeField] bool m_RequiresTime;
[SerializeField] bool m_RequiresVertexSkinning;
[SerializeField] bool m_RequiresVertexID;
internal static ShaderGraphRequirements none
{
get
{
return new ShaderGraphRequirements
{
m_RequiresMeshUVs = new List<UVChannel>()
};
}
}
public NeededCoordinateSpace requiresNormal
{
get { return m_RequiresNormal; }
internal set { m_RequiresNormal = value; }
}
public NeededCoordinateSpace requiresBitangent
{
get { return m_RequiresBitangent; }
internal set { m_RequiresBitangent = value; }
}
public NeededCoordinateSpace requiresTangent
{
get { return m_RequiresTangent; }
internal set { m_RequiresTangent = value; }
}
public NeededCoordinateSpace requiresViewDir
{
get { return m_RequiresViewDir; }
internal set { m_RequiresViewDir = value; }
}
public NeededCoordinateSpace requiresPosition
{
get { return m_RequiresPosition; }
internal set { m_RequiresPosition = value; }
}
public bool requiresScreenPosition
{
get { return m_RequiresScreenPosition; }
internal set { m_RequiresScreenPosition = value; }
}
public bool requiresVertexColor
{
get { return m_RequiresVertexColor; }
internal set { m_RequiresVertexColor = value; }
}
public bool requiresFaceSign
{
get { return m_RequiresFaceSign; }
internal set { m_RequiresFaceSign = value; }
}
public List<UVChannel> requiresMeshUVs
{
get { return m_RequiresMeshUVs; }
internal set { m_RequiresMeshUVs = value; }
}
public bool requiresDepthTexture
{
get { return m_RequiresDepthTexture; }
internal set { m_RequiresDepthTexture = value; }
}
public bool requiresCameraOpaqueTexture
{
get { return m_RequiresCameraOpaqueTexture; }
internal set { m_RequiresCameraOpaqueTexture = value; }
}
public bool requiresTime
{
get { return m_RequiresTime; }
internal set { m_RequiresTime = value; }
}
public bool requiresVertexSkinning
{
get { return m_RequiresVertexSkinning; }
internal set { m_RequiresVertexSkinning = value; }
}
public bool requiresVertexID
{
get { return m_RequiresVertexID; }
internal set { m_RequiresVertexID = value; }
}
internal bool NeedsTangentSpace()
{
var compoundSpaces = m_RequiresBitangent | m_RequiresNormal | m_RequiresPosition
| m_RequiresTangent | m_RequiresViewDir | m_RequiresPosition
| m_RequiresNormal;
return (compoundSpaces & NeededCoordinateSpace.Tangent) > 0;
}
internal ShaderGraphRequirements Union(ShaderGraphRequirements other)
{
var newReqs = new ShaderGraphRequirements();
newReqs.m_RequiresNormal = other.m_RequiresNormal | m_RequiresNormal;
newReqs.m_RequiresTangent = other.m_RequiresTangent | m_RequiresTangent;
newReqs.m_RequiresBitangent = other.m_RequiresBitangent | m_RequiresBitangent;
newReqs.m_RequiresViewDir = other.m_RequiresViewDir | m_RequiresViewDir;
newReqs.m_RequiresPosition = other.m_RequiresPosition | m_RequiresPosition;
newReqs.m_RequiresScreenPosition = other.m_RequiresScreenPosition | m_RequiresScreenPosition;
newReqs.m_RequiresVertexColor = other.m_RequiresVertexColor | m_RequiresVertexColor;
newReqs.m_RequiresFaceSign = other.m_RequiresFaceSign | m_RequiresFaceSign;
newReqs.m_RequiresDepthTexture = other.m_RequiresDepthTexture | m_RequiresDepthTexture;
newReqs.m_RequiresCameraOpaqueTexture = other.m_RequiresCameraOpaqueTexture | m_RequiresCameraOpaqueTexture;
newReqs.m_RequiresTime = other.m_RequiresTime | m_RequiresTime;
newReqs.m_RequiresVertexSkinning = other.m_RequiresVertexSkinning | m_RequiresVertexSkinning;
newReqs.m_RequiresVertexID = other.m_RequiresVertexID | m_RequiresVertexID;
newReqs.m_RequiresMeshUVs = new List<UVChannel>();
if (m_RequiresMeshUVs != null)
newReqs.m_RequiresMeshUVs.AddRange(m_RequiresMeshUVs);
if (other.m_RequiresMeshUVs != null)
newReqs.m_RequiresMeshUVs.AddRange(other.m_RequiresMeshUVs);
return newReqs;
}
internal static ShaderGraphRequirements FromNodes<T>(List<T> nodes, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool includeIntermediateSpaces = true)
where T : AbstractMaterialNode
{
NeededCoordinateSpace requiresNormal = nodes.OfType<IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal(stageCapability));
NeededCoordinateSpace requiresBitangent = nodes.OfType<IMayRequireBitangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresBitangent(stageCapability));
NeededCoordinateSpace requiresTangent = nodes.OfType<IMayRequireTangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresTangent(stageCapability));
NeededCoordinateSpace requiresViewDir = nodes.OfType<IMayRequireViewDirection>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresViewDirection(stageCapability));
NeededCoordinateSpace requiresPosition = nodes.OfType<IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability));
bool requiresScreenPosition = nodes.OfType<IMayRequireScreenPosition>().Any(x => x.RequiresScreenPosition(stageCapability));
bool requiresVertexColor = nodes.OfType<IMayRequireVertexColor>().Any(x => x.RequiresVertexColor());
bool requiresFaceSign = nodes.OfType<IMayRequireFaceSign>().Any(x => x.RequiresFaceSign());
bool requiresDepthTexture = nodes.OfType<IMayRequireDepthTexture>().Any(x => x.RequiresDepthTexture());
bool requiresCameraOpaqueTexture = nodes.OfType<IMayRequireCameraOpaqueTexture>().Any(x => x.RequiresCameraOpaqueTexture());
bool requiresTime = nodes.Any(x => x.RequiresTime());
bool requiresVertexSkinning = nodes.OfType<IMayRequireVertexSkinning>().Any(x => x.RequiresVertexSkinning(stageCapability));
bool requiresVertexID = nodes.OfType<IMayRequireVertexID>().Any(x => x.RequiresVertexID(stageCapability));
var meshUV = new List<UVChannel>();
for (int uvIndex = 0; uvIndex < ShaderGeneratorNames.UVCount; ++uvIndex)
{
var channel = (UVChannel)uvIndex;
if (nodes.OfType<IMayRequireMeshUV>().Any(x => x.RequiresMeshUV(channel)))
meshUV.Add(channel);
}
// if anything needs tangentspace we have make
// sure to have our othonormal basis!
if (includeIntermediateSpaces)
{
var compoundSpaces = requiresBitangent | requiresNormal | requiresPosition
| requiresTangent | requiresViewDir | requiresPosition
| requiresNormal;
var needsTangentSpace = (compoundSpaces & NeededCoordinateSpace.Tangent) > 0;
if (needsTangentSpace)
{
requiresBitangent |= NeededCoordinateSpace.World;
requiresNormal |= NeededCoordinateSpace.World;
requiresTangent |= NeededCoordinateSpace.World;
}
}
var reqs = new ShaderGraphRequirements()
{
m_RequiresNormal = requiresNormal,
m_RequiresBitangent = requiresBitangent,
m_RequiresTangent = requiresTangent,
m_RequiresViewDir = requiresViewDir,
m_RequiresPosition = requiresPosition,
m_RequiresScreenPosition = requiresScreenPosition,
m_RequiresVertexColor = requiresVertexColor,
m_RequiresFaceSign = requiresFaceSign,
m_RequiresMeshUVs = meshUV,
m_RequiresDepthTexture = requiresDepthTexture,
m_RequiresCameraOpaqueTexture = requiresCameraOpaqueTexture,
m_RequiresTime = requiresTime,
m_RequiresVertexSkinning = requiresVertexSkinning,
m_RequiresVertexID = requiresVertexID,
};
return reqs;
}
}
}

View File

@@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
public abstract class ShaderInput : JsonObject
{
[SerializeField]
SerializableGuid m_Guid = new SerializableGuid();
internal Guid guid => m_Guid.guid;
internal void OverrideGuid(string namespaceId, string name) { m_Guid.guid = GenerateNamespaceUUID(namespaceId, name); }
[SerializeField]
string m_Name;
public string displayName
{
get
{
if (string.IsNullOrEmpty(m_Name))
return $"{concreteShaderValueType}_{objectId}";
return m_Name;
}
set
{
// this is a raw set of the display name
// if you want to a fully graph-connected set-and-sanitize-and-update,
// call SetDisplayNameAndSanitizeForGraph() instead
m_Name = value;
}
}
// This delegate and the associated callback can be bound to in order for any one that cares about display name changes to be notified
internal delegate void ChangeDisplayNameCallback(string newDisplayName);
ChangeDisplayNameCallback m_displayNameUpdateTrigger;
internal ChangeDisplayNameCallback displayNameUpdateTrigger
{
get => m_displayNameUpdateTrigger;
set => m_displayNameUpdateTrigger = value;
}
// sanitizes the desired name according to the current graph, and assigns it as the display name
// also calls the update trigger to update other bits of the graph UI that use the name
internal void SetDisplayNameAndSanitizeForGraph(GraphData graphData, string desiredName = null)
{
string originalDisplayName = displayName;
// if no desired name passed in, sanitize the current name
if (desiredName == null)
desiredName = originalDisplayName;
var sanitizedName = graphData.SanitizeGraphInputName(this, desiredName);
bool changed = (originalDisplayName != sanitizedName);
// only assign if it was changed
if (changed)
m_Name = sanitizedName;
// update the default reference name
UpdateDefaultReferenceName(graphData);
// Updates any views associated with this input so that display names stay up to date
// NOTE: we call this even when the name has not changed, because there may be fields
// that were user-edited and still have the temporary desired name -- those must update
if (m_displayNameUpdateTrigger != null)
{
m_displayNameUpdateTrigger.Invoke(m_Name);
}
}
internal void SetReferenceNameAndSanitizeForGraph(GraphData graphData, string desiredRefName = null)
{
string originalRefName = referenceName;
// if no desired ref name, use the current name
if (string.IsNullOrEmpty(desiredRefName))
desiredRefName = originalRefName;
// sanitize and deduplicate the desired name
var sanitizedRefName = graphData.SanitizeGraphInputReferenceName(this, desiredRefName);
// check if the final result is different from the current name
bool changed = (originalRefName != sanitizedRefName);
// if changed, then set the new name up as an override
if (changed)
overrideReferenceName = sanitizedRefName;
}
// resets the reference name to a "default" value (deduplicated against existing reference names)
// returns the new default reference name
internal string ResetReferenceName(GraphData graphData)
{
overrideReferenceName = null;
// because we are clearing an override, we must force a sanitization pass on the default ref name
// as there may now be collisions that didn't previously exist
UpdateDefaultReferenceName(graphData, true);
return referenceName;
}
internal void UpdateDefaultReferenceName(GraphData graphData, bool forceSanitize = false)
{
if (m_DefaultRefNameVersion <= 0)
return; // old version is updated in the getter
var dispName = displayName;
if (forceSanitize ||
string.IsNullOrEmpty(m_DefaultReferenceName) ||
(m_RefNameGeneratedByDisplayName != dispName))
{
m_DefaultReferenceName = graphData.SanitizeGraphInputReferenceName(this, dispName);
m_RefNameGeneratedByDisplayName = dispName;
}
}
const int k_LatestDefaultRefNameVersion = 1;
// this is used to know whether this shader input is using:
// 0) the "old" default reference naming scheme (type + GUID)
// 1) the new default reference naming scheme (make it similar to the display name)
[SerializeField]
int m_DefaultRefNameVersion = k_LatestDefaultRefNameVersion;
[SerializeField]
string m_RefNameGeneratedByDisplayName; // used to tell what was the display name used to generate the default reference name
[SerializeField]
string m_DefaultReferenceName; // NOTE: this can be NULL for old graphs, or newly created properties
public string referenceName
{
get
{
if (string.IsNullOrEmpty(overrideReferenceName))
{
if (m_DefaultRefNameVersion == 0)
{
if (string.IsNullOrEmpty(m_DefaultReferenceName))
m_DefaultReferenceName = GetOldDefaultReferenceName();
return m_DefaultReferenceName;
}
else // version 1
{
// default reference name is updated elsewhere in the new naming scheme
return m_DefaultReferenceName;
}
}
return overrideReferenceName;
}
}
public override void OnBeforeDeserialize()
{
// if serialization doesn't write to m_DefaultRefNameVersion, then it is an old shader input, and should use the old default naming scheme
m_DefaultRefNameVersion = 0;
base.OnBeforeDeserialize();
}
// This is required to handle Material data serialized with "_Color_GUID" reference names
// m_DefaultReferenceName expects to match the material data and previously used PropertyType
// ColorShaderProperty is the only case where PropertyType doesn't match ConcreteSlotValueType
public virtual string GetOldDefaultReferenceName()
{
return $"{concreteShaderValueType.ToString()}_{objectId}";
}
// returns true if this shader input is CURRENTLY using the old default reference name
public bool IsUsingOldDefaultRefName()
{
return string.IsNullOrEmpty(overrideReferenceName) && (m_DefaultRefNameVersion == 0);
}
// returns true if this shader input is CURRENTLY using the new default reference name
public bool IsUsingNewDefaultRefName()
{
return string.IsNullOrEmpty(overrideReferenceName) && (m_DefaultRefNameVersion >= 1);
}
// upgrades the default reference name to use the new naming scheme
internal string UpgradeDefaultReferenceName(GraphData graphData)
{
m_DefaultRefNameVersion = k_LatestDefaultRefNameVersion;
m_DefaultReferenceName = null;
m_RefNameGeneratedByDisplayName = null;
UpdateDefaultReferenceName(graphData, true); // make sure to sanitize the new default
return referenceName;
}
[SerializeField]
string m_OverrideReferenceName;
internal string overrideReferenceName
{
get => m_OverrideReferenceName;
set => m_OverrideReferenceName = value;
}
[SerializeField]
bool m_GeneratePropertyBlock = true;
internal bool generatePropertyBlock // this is basically the "exposed" toggle
{
get => m_GeneratePropertyBlock;
set => m_GeneratePropertyBlock = value;
}
internal bool isExposed => isExposable && generatePropertyBlock;
internal abstract ConcreteSlotValueType concreteShaderValueType { get; }
internal abstract bool isExposable { get; }
internal virtual bool isAlwaysExposed => false;
// this controls whether the UI allows the user to rename the display and reference names
internal abstract bool isRenamable { get; }
internal abstract ShaderInput Copy();
}
}

View File

@@ -0,0 +1,219 @@
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine.Serialization;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class ShaderKeyword : ShaderInput
{
public const string kVariantLimitWarning = "Graph is generating too many variants. Either delete Keywords, reduce Keyword variants or increase the Shader Variant Limit in Preferences > Shader Graph.";
public ShaderKeyword()
{
}
public ShaderKeyword(KeywordType keywordType)
{
this.displayName = keywordType.ToString();
this.keywordType = keywordType;
// Add sensible default entries for Enum type
if (keywordType == KeywordType.Enum)
{
m_Entries = new List<KeywordEntry>();
m_Entries.Add(new KeywordEntry(1, "A", "A"));
m_Entries.Add(new KeywordEntry(2, "B", "B"));
m_Entries.Add(new KeywordEntry(3, "C", "C"));
}
}
public static ShaderKeyword CreateBuiltInKeyword(KeywordDescriptor descriptor)
{
if (descriptor.entries != null)
{
for (int i = 0; i < descriptor.entries.Length; i++)
{
if (descriptor.entries[i].id == -1)
descriptor.entries[i].id = i + 1;
}
}
return new ShaderKeyword()
{
isBuiltIn = true,
displayName = descriptor.displayName,
overrideReferenceName = descriptor.referenceName,
keywordType = descriptor.type,
keywordDefinition = descriptor.definition,
keywordScope = descriptor.scope,
value = descriptor.value,
entries = descriptor.entries.ToList(),
};
}
[SerializeField]
private KeywordType m_KeywordType = KeywordType.Boolean;
public KeywordType keywordType
{
get => m_KeywordType;
set => m_KeywordType = value;
}
[SerializeField]
private KeywordDefinition m_KeywordDefinition = KeywordDefinition.ShaderFeature;
public KeywordDefinition keywordDefinition
{
get => m_KeywordDefinition;
set => m_KeywordDefinition = value;
}
[SerializeField]
private KeywordScope m_KeywordScope = KeywordScope.Local;
public KeywordScope keywordScope
{
get => m_KeywordScope;
set => m_KeywordScope = value;
}
[SerializeField]
private List<KeywordEntry> m_Entries;
public List<KeywordEntry> entries
{
get => m_Entries;
set => m_Entries = value;
}
[SerializeField]
private int m_Value;
public int value
{
get => m_Value;
set => m_Value = value;
}
[SerializeField]
private bool m_IsEditable = true; // this serializes !isBuiltIn
public bool isBuiltIn
{
get => !m_IsEditable;
set => m_IsEditable = !value;
}
internal override bool isExposable => !isBuiltIn && (keywordDefinition != KeywordDefinition.Predefined);
internal override bool isRenamable => !isBuiltIn;
internal override ConcreteSlotValueType concreteShaderValueType => keywordType.ToConcreteSlotValueType();
public override string GetOldDefaultReferenceName()
{
// _ON suffix is required for exposing Boolean type to Material
var suffix = string.Empty;
if (keywordType == KeywordType.Boolean)
{
suffix = "_ON";
}
return $"{keywordType.ToString()}_{objectId}{suffix}".ToUpper();
}
public void AppendPropertyBlockStrings(ShaderStringBuilder builder)
{
if (isExposed)
{
switch (keywordType)
{
case KeywordType.Enum:
string enumTagString = $"[KeywordEnum({string.Join(", ", entries.Select(x => x.displayName))})]";
builder.AppendLine($"{enumTagString}{referenceName}(\"{displayName}\", Float) = {value}");
break;
case KeywordType.Boolean:
if (referenceName.EndsWith("_ON"))
builder.AppendLine($"[Toggle]{referenceName.Remove(referenceName.Length - 3, 3)}(\"{displayName}\", Float) = {value}");
else
builder.AppendLine($"[Toggle({referenceName})]{referenceName}(\"{displayName}\", Float) = {value}");
break;
default:
break;
}
}
}
public string GetKeywordDeclarationString()
{
// Predefined keywords do not need to be defined
if (keywordDefinition == KeywordDefinition.Predefined)
return string.Empty;
// Get definition type using scope
string scopeString = keywordScope == KeywordScope.Local ? "_local" : string.Empty;
string definitionString = $"{keywordDefinition.ToDeclarationString()}{scopeString}";
switch (keywordType)
{
case KeywordType.Boolean:
return $"#pragma {definitionString} _ {referenceName}";
case KeywordType.Enum:
var enumEntryDefinitions = entries.Select(x => $"{referenceName}_{x.referenceName}");
string enumEntriesString = string.Join(" ", enumEntryDefinitions);
return $"#pragma {definitionString} {enumEntriesString}";
default:
throw new ArgumentOutOfRangeException();
}
}
public string GetKeywordPreviewDeclarationString()
{
switch (keywordType)
{
case KeywordType.Boolean:
return value == 1 ? $"#define {referenceName}" : string.Empty;
case KeywordType.Enum:
return $"#define {referenceName}_{entries[value].referenceName}";
default:
throw new ArgumentOutOfRangeException();
}
}
internal override ShaderInput Copy()
{
// Keywords copy reference name
// This is because keywords are copied between graphs
// When copying dependent nodes
return new ShaderKeyword()
{
displayName = displayName,
value = value,
isBuiltIn = isBuiltIn,
keywordType = keywordType,
keywordDefinition = keywordDefinition,
keywordScope = keywordScope,
entries = entries,
};
}
public override int latestVersion => 1;
public override void OnAfterDeserialize(string json)
{
if (sgVersion == 0)
{
// we now allow keywords to control whether they are exposed (for Material control) or not.
// old exposable keywords set their exposed state to maintain previous behavior
// (where only keywords ending in "_ON" showed up in the material)
if (isExposable)
generatePropertyBlock = referenceName.EndsWith("_ON");
ChangeVersion(1);
}
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
abstract class SpaceMaterialSlot : Vector3MaterialSlot
{
[SerializeField]
private CoordinateSpace m_Space = CoordinateSpace.World;
public CoordinateSpace space
{
get { return m_Space; }
set { m_Space = value; }
}
protected SpaceMaterialSlot()
{}
protected SpaceMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{
this.space = space;
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as SpaceMaterialSlot;
if (slot != null)
space = slot.space;
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class StickyNoteData : JsonObject, IGroupItem
{
[SerializeField]
string m_Title;
public string title
{
get => m_Title;
set => m_Title = value;
}
[SerializeField]
string m_Content;
public string content
{
get => m_Content;
set => m_Content = value;
}
[SerializeField]
int m_TextSize;
public int textSize
{
get => m_TextSize;
set => m_TextSize = value;
}
[SerializeField]
int m_Theme;
public int theme
{
get => m_Theme;
set => m_Theme = value;
}
[SerializeField]
Rect m_Position;
public Rect position
{
get => m_Position;
set => m_Position = value;
}
[SerializeField]
JsonRef<GroupData> m_Group = null;
public GroupData group
{
get => m_Group;
set
{
if (m_Group == value)
return;
m_Group = value;
}
}
public StickyNoteData() : base() {}
public StickyNoteData(string title, string content, Rect position)
{
m_Title = title;
m_Position = position;
m_Content = content;
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class TangentMaterialSlot : SpaceMaterialSlot, IMayRequireTangent
{
public TangentMaterialSlot()
{}
public TangentMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView(space + " Space");
}
public override string GetDefaultValue(GenerationMode generationMode)
{
return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.Tangent));
}
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;
return space.ToNeededCoordinateSpace();
}
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[HasDependencies(typeof(MinimalTexture2DArrayInputMaterialSlot))]
class Texture2DArrayInputMaterialSlot : Texture2DArrayMaterialSlot
{
[SerializeField]
private SerializableTextureArray m_TextureArray = new SerializableTextureArray();
public Texture2DArray textureArray
{
get { return m_TextureArray.textureArray; }
set { m_TextureArray.textureArray = value; }
}
public override bool isDefaultValue => textureArray == null;
public Texture2DArrayInputMaterialSlot()
{}
public Texture2DArrayInputMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
ShaderStageCapability shaderStageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new TextureArraySlotControlView(this);
}
public override string GetDefaultValue(GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
return $"UnityBuildTexture2DArrayStruct({nodeOwner.GetVariableNameForSlot(id)})";
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var prop = new Texture2DArrayShaderProperty();
prop.overrideReferenceName = nodeOwner.GetVariableNameForSlot(id);
prop.modifiable = false;
prop.generatePropertyBlock = true;
prop.value.textureArray = textureArray;
properties.AddShaderProperty(prop);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Texture2DArray)
{
name = name,
textureValue = textureArray,
};
properties.Add(pp);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Texture2DArrayInputMaterialSlot;
if (slot != null)
{
m_TextureArray = slot.m_TextureArray;
bareResource = slot.bareResource;
}
}
}
class MinimalTexture2DArrayInputMaterialSlot : IHasDependencies
{
[SerializeField]
private SerializableTextureArray m_TextureArray = null;
public void GetSourceAssetDependencies(AssetCollection assetCollection)
{
var guidString = m_TextureArray.guid;
if (!string.IsNullOrEmpty(guidString) && GUID.TryParse(guidString, out var guid))
{
assetCollection.AddAssetDependency(guid, AssetCollection.Flags.IncludeInExportPackage);
}
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Texture2DArrayMaterialSlot : MaterialSlot
{
public Texture2DArrayMaterialSlot()
{}
public Texture2DArrayMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability shaderStageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)
{}
[SerializeField]
bool m_BareResource = false;
internal override bool bareResource
{
get { return m_BareResource; }
set { m_BareResource = value; }
}
public override void AppendHLSLParameterDeclaration(ShaderStringBuilder sb, string paramName)
{
if (m_BareResource)
{
sb.Append("TEXTURE2D_ARRAY(");
sb.Append(paramName);
sb.Append(")");
}
else
base.AppendHLSLParameterDeclaration(sb, paramName);
}
public override SlotValueType valueType { get { return SlotValueType.Texture2DArray; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Texture2DArray; } }
public override bool isDefaultValue => true;
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Texture2DArrayMaterialSlot;
if (slot != null)
{
m_BareResource = slot.m_BareResource;
}
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.Texture2DArrayShaderProperty")]
[BlackboardInputInfo(51)]
public class Texture2DArrayShaderProperty : AbstractShaderProperty<SerializableTextureArray>
{
internal Texture2DArrayShaderProperty()
{
displayName = "Texture2D Array";
value = new SerializableTextureArray();
}
public override PropertyType propertyType => PropertyType.Texture2DArray;
internal override bool isExposable => true;
internal override bool isRenamable => true;
internal string modifiableTagString => modifiable ? "" : "[NonModifiableTextureData]";
internal override string GetPropertyBlockString()
{
return $"{hideTagString}{modifiableTagString}[NoScaleOffset]{referenceName}(\"{displayName}\", 2DArray) = \"\" {{}}";
}
internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => false; // disable UI, nothing to choose
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
action(new HLSLProperty(HLSLType._Texture2DArray, referenceName, HLSLDeclaration.Global));
action(new HLSLProperty(HLSLType._SamplerState, "sampler" + referenceName, HLSLDeclaration.Global));
}
internal override string GetPropertyAsArgumentString()
{
return "UnityTexture2DArray " + referenceName;
}
internal override string GetPropertyAsArgumentStringForVFX()
{
return "TEXTURE2D_ARRAY(" + referenceName + ")";
}
internal override string GetHLSLVariableName(bool isSubgraphProperty)
{
if (isSubgraphProperty)
return referenceName;
else
return $"UnityBuildTexture2DArrayStruct({referenceName})";
}
[SerializeField]
bool m_Modifiable = true;
internal bool modifiable
{
get => m_Modifiable;
set => m_Modifiable = value;
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new Texture2DArrayAssetNode { texture = value.textureArray };
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
textureValue = value.textureArray
};
}
internal override ShaderInput Copy()
{
return new Texture2DArrayShaderProperty()
{
displayName = displayName,
value = value,
};
}
}
}

View File

@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[HasDependencies(typeof(MinimalTexture2DInputMaterialSlot))]
class Texture2DInputMaterialSlot : Texture2DMaterialSlot
{
[SerializeField]
private SerializableTexture m_Texture = new SerializableTexture();
[SerializeField]
private Texture2DShaderProperty.DefaultType m_DefaultType = Texture2DShaderProperty.DefaultType.White;
public Texture texture
{
get { return m_Texture.texture; }
set { m_Texture.texture = value; }
}
public Texture2DShaderProperty.DefaultType defaultType
{
get { return m_DefaultType; }
set { m_DefaultType = value; }
}
public override bool isDefaultValue => texture == null;
public Texture2DInputMaterialSlot()
{}
public Texture2DInputMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new TextureSlotControlView(this);
}
public override string GetDefaultValue(GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
return $"UnityBuildTexture2DStructNoScale({nodeOwner.GetVariableNameForSlot(id)})";
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var prop = new Texture2DShaderProperty();
prop.overrideReferenceName = nodeOwner.GetVariableNameForSlot(id);
prop.modifiable = false;
prop.generatePropertyBlock = true;
prop.value.texture = texture;
prop.defaultType = defaultType;
properties.AddShaderProperty(prop);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Texture2D)
{
name = name,
textureValue = texture,
texture2DDefaultType = defaultType
};
properties.Add(pp);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Texture2DInputMaterialSlot;
if (slot != null)
{
m_Texture = slot.m_Texture;
bareResource = slot.bareResource;
}
}
}
class MinimalTexture2DInputMaterialSlot : IHasDependencies
{
[SerializeField]
private SerializableTexture m_Texture = null;
public void GetSourceAssetDependencies(AssetCollection assetCollection)
{
var guidString = m_Texture.guid;
if (!string.IsNullOrEmpty(guidString) && GUID.TryParse(guidString, out var guid))
{
assetCollection.AddAssetDependency(guid, AssetCollection.Flags.IncludeInExportPackage);
}
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Texture2DMaterialSlot : MaterialSlot
{
public Texture2DMaterialSlot()
{}
public Texture2DMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{}
[SerializeField]
bool m_BareResource = false;
internal override bool bareResource
{
get { return m_BareResource; }
set { m_BareResource = value; }
}
public override void AppendHLSLParameterDeclaration(ShaderStringBuilder sb, string paramName)
{
if (m_BareResource)
{
sb.Append("TEXTURE2D(");
sb.Append(paramName);
sb.Append(")");
}
else
base.AppendHLSLParameterDeclaration(sb, paramName);
}
public override SlotValueType valueType { get { return SlotValueType.Texture2D; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Texture2D; } }
public override bool isDefaultValue => true;
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Texture2DMaterialSlot;
if (slot != null)
{
m_BareResource = slot.m_BareResource;
}
}
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Text;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.TextureShaderProperty")]
[BlackboardInputInfo(50)]
public sealed class Texture2DShaderProperty : AbstractShaderProperty<SerializableTexture>
{
public enum DefaultType { White, Black, Grey, Bump }
internal Texture2DShaderProperty()
{
displayName = "Texture2D";
value = new SerializableTexture();
}
public override PropertyType propertyType => PropertyType.Texture2D;
internal override bool isExposable => true;
internal override bool isRenamable => true;
internal string modifiableTagString => modifiable ? "" : "[NonModifiableTextureData]";
internal override string GetPropertyBlockString()
{
return $"{hideTagString}{modifiableTagString}[NoScaleOffset]{referenceName}(\"{displayName}\", 2D) = \"{defaultType.ToString().ToLower()}\" {{}}";
}
// Texture2D properties cannot be set via Hybrid path at the moment; disallow that choice
internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => (decl != HLSLDeclaration.HybridPerInstance) && (decl != HLSLDeclaration.DoNotDeclare);
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
HLSLDeclaration decl = (generatePropertyBlock ? HLSLDeclaration.UnityPerMaterial : HLSLDeclaration.Global);
action(new HLSLProperty(HLSLType._Texture2D, referenceName, HLSLDeclaration.Global));
action(new HLSLProperty(HLSLType._SamplerState, "sampler" + referenceName, HLSLDeclaration.Global));
action(new HLSLProperty(HLSLType._float4, referenceName + "_TexelSize", decl));
// action(new HLSLProperty(HLSLType._float4, referenceName + "_ST", decl)); // TODO: allow users to make use of the ST values
}
internal override string GetPropertyAsArgumentString()
{
return "UnityTexture2D " + referenceName;
}
internal override string GetPropertyAsArgumentStringForVFX()
{
return "TEXTURE2D(" + referenceName + ")";
}
internal override string GetHLSLVariableName(bool isSubgraphProperty)
{
if (isSubgraphProperty)
return referenceName;
else
return $"UnityBuildTexture2DStructNoScale({referenceName})";
}
[SerializeField]
bool m_Modifiable = true;
internal bool modifiable
{
get => m_Modifiable;
set => m_Modifiable = value;
}
[SerializeField]
DefaultType m_DefaultType = DefaultType.White;
public DefaultType defaultType
{
get { return m_DefaultType; }
set { m_DefaultType = value; }
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new Texture2DAssetNode { texture = value.texture };
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
textureValue = value.texture,
texture2DDefaultType = defaultType
};
}
internal override ShaderInput Copy()
{
return new Texture2DShaderProperty()
{
displayName = displayName,
value = value,
defaultType = defaultType,
};
}
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[HasDependencies(typeof(MinimalTexture3DInputMaterialSlot))]
class Texture3DInputMaterialSlot : Texture3DMaterialSlot
{
[SerializeField]
private SerializableTexture m_Texture = new SerializableTexture();
public Texture texture
{
get { return m_Texture.texture; }
set { m_Texture.texture = value; }
}
public override bool isDefaultValue => texture == null;
public Texture3DInputMaterialSlot()
{}
public Texture3DInputMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
ShaderStageCapability shaderStageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, shaderStageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new Texture3DSlotControlView(this);
}
public override string GetDefaultValue(GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
return $"UnityBuildTexture3DStruct({nodeOwner.GetVariableNameForSlot(id)})";
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
var nodeOwner = owner as AbstractMaterialNode;
if (nodeOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var prop = new Texture3DShaderProperty();
prop.overrideReferenceName = nodeOwner.GetVariableNameForSlot(id);
prop.modifiable = false;
prop.generatePropertyBlock = true;
prop.value.texture = texture;
properties.AddShaderProperty(prop);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Texture3D)
{
name = name,
textureValue = texture,
};
properties.Add(pp);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Texture3DInputMaterialSlot;
if (slot != null)
{
m_Texture = slot.m_Texture;
bareResource = slot.bareResource;
}
}
}
class MinimalTexture3DInputMaterialSlot : IHasDependencies
{
[SerializeField]
private SerializableTexture m_Texture = null;
public void GetSourceAssetDependencies(AssetCollection assetCollection)
{
var guidString = m_Texture.guid;
if (!string.IsNullOrEmpty(guidString) && GUID.TryParse(guidString, out var guid))
{
assetCollection.AddAssetDependency(guid, AssetCollection.Flags.IncludeInExportPackage);
}
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Texture3DMaterialSlot : MaterialSlot
{
public Texture3DMaterialSlot()
{}
public Texture3DMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability shaderStageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)
{}
[SerializeField]
bool m_BareResource = false;
internal override bool bareResource
{
get { return m_BareResource; }
set { m_BareResource = value; }
}
public override void AppendHLSLParameterDeclaration(ShaderStringBuilder sb, string paramName)
{
if (m_BareResource)
{
sb.Append("TEXTURE3D(");
sb.Append(paramName);
sb.Append(")");
}
else
base.AppendHLSLParameterDeclaration(sb, paramName);
}
public override SlotValueType valueType { get { return SlotValueType.Texture3D; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Texture3D; } }
public override bool isDefaultValue => true;
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Texture3DMaterialSlot;
if (slot != null)
{
m_BareResource = slot.m_BareResource;
}
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.Texture3DShaderProperty")]
[BlackboardInputInfo(52)]
public sealed class Texture3DShaderProperty : AbstractShaderProperty<SerializableTexture>
{
internal Texture3DShaderProperty()
{
displayName = "Texture3D";
value = new SerializableTexture();
}
public override PropertyType propertyType => PropertyType.Texture3D;
internal override bool isExposable => true;
internal override bool isRenamable => true;
internal string modifiableTagString => modifiable ? "" : "[NonModifiableTextureData]";
internal override string GetPropertyBlockString()
{
return $"{hideTagString}{modifiableTagString}[NoScaleOffset]{referenceName}(\"{displayName}\", 3D) = \"white\" {{}}";
}
internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => false; // disable UI, nothing to choose
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
action(new HLSLProperty(HLSLType._Texture3D, referenceName, HLSLDeclaration.Global));
action(new HLSLProperty(HLSLType._SamplerState, "sampler" + referenceName, HLSLDeclaration.Global));
}
internal override string GetPropertyAsArgumentString()
{
return "UnityTexture3D " + referenceName;
}
internal override string GetPropertyAsArgumentStringForVFX()
{
return "TEXTURE3D(" + referenceName + ")";
}
internal override string GetHLSLVariableName(bool isSubgraphProperty)
{
if (isSubgraphProperty)
return referenceName;
else
return $"UnityBuildTexture3DStruct({referenceName})";
}
[SerializeField]
bool m_Modifiable = true;
public bool modifiable
{
get => m_Modifiable;
set => m_Modifiable = value;
}
internal override AbstractMaterialNode ToConcreteNode()
{
return new Texture3DAssetNode { texture = value.texture as Texture3D };
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
textureValue = value.texture
};
}
internal override ShaderInput Copy()
{
return new Texture3DShaderProperty()
{
displayName = displayName,
value = value,
};
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class TextureSamplerState
{
public enum FilterMode
{
Linear,
Point,
Trilinear
}
public enum WrapMode
{
Repeat,
Clamp,
Mirror,
MirrorOnce
}
[SerializeField] private FilterMode m_filter = FilterMode.Linear;
public FilterMode filter
{
get { return m_filter; }
set
{
if (m_filter == value)
return;
m_filter = value;
}
}
[SerializeField] private WrapMode m_wrap = WrapMode.Repeat;
public WrapMode wrap
{
get { return m_wrap; }
set
{
if (m_wrap == value)
return;
m_wrap = value;
}
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class UVMaterialSlot : Vector2MaterialSlot, IMayRequireMeshUV
{
[SerializeField]
UVChannel m_Channel = UVChannel.UV0;
public UVChannel channel
{
get { return m_Channel; }
set { m_Channel = value; }
}
public override bool isDefaultValue => channel == UVChannel.UV0;
public UVMaterialSlot()
{}
public UVMaterialSlot(int slotId, string displayName, string shaderOutputName, UVChannel channel,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector2.zero, stageCapability, hidden: hidden)
{
this.channel = channel;
}
public override VisualElement InstantiateControl()
{
return new UVSlotControlView(this);
}
public override string GetDefaultValue(GenerationMode generationMode)
{
return string.Format("IN.{0}.xy", channel.GetUVName());
}
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
{
if (isConnected)
return false;
return m_Channel == channel;
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as UVMaterialSlot;
if (slot != null)
channel = slot.channel;
}
}
}

View File

@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Vector1MaterialSlot : MaterialSlot, IMaterialSlotHasValue<float>
{
[SerializeField]
float m_Value;
[SerializeField]
float m_DefaultValue;
[SerializeField]
string[] m_Labels; // this can be null, which means fallback to k_LabelDefaults
static readonly string[] k_LabelDefaults = { "X" };
string[] labels
{
get
{
if ((m_Labels == null) || (m_Labels.Length != k_LabelDefaults.Length))
return k_LabelDefaults;
return m_Labels;
}
}
public Vector1MaterialSlot()
{
}
public Vector1MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
float value,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
string label1 = null,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_DefaultValue = value;
m_Value = value;
if (label1 != null)
m_Labels = new[] { label1 };
}
public float defaultValue { get { return m_DefaultValue; } }
public float value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
public override VisualElement InstantiateControl()
{
return new MultiFloatSlotControlView(owner, labels, () => new Vector4(value, 0f, 0f, 0f), (newValue) => value = newValue.x);
}
protected override string ConcreteSlotValueAsVariable()
{
return NodeUtils.FloatToShaderValue(value);
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new Vector1ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override SlotValueType valueType { get { return SlotValueType.Vector1; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Vector1; } }
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Float)
{
name = name,
floatValue = value,
};
properties.Add(pp);
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Vector1MaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<float> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Linq;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.FloatShaderProperty")]
[FormerName("UnityEditor.ShaderGraph.Vector1ShaderProperty")]
[BlackboardInputInfo(0, "Float")]
public sealed class Vector1ShaderProperty : AbstractShaderProperty<float>
{
internal Vector1ShaderProperty()
{
displayName = "Float";
}
public override PropertyType propertyType => PropertyType.Float;
internal override bool isExposable => true;
internal override bool isRenamable => true;
string enumTagString
{
get
{
switch (enumType)
{
case EnumType.CSharpEnum:
return $"[Enum({m_CSharpEnumType.ToString()})]";
case EnumType.KeywordEnum:
return $"[KeywordEnum({string.Join(", ", enumNames)})]";
default:
string enumValuesString = "";
for (int i = 0; i < enumNames.Count; i++)
{
int value = (i < enumValues.Count) ? enumValues[i] : i;
enumValuesString += (enumNames[i] + ", " + value + ((i != enumNames.Count - 1) ? ", " : ""));
}
return $"[Enum({enumValuesString})]";
}
}
}
internal override string GetPropertyBlockString()
{
string valueString = NodeUtils.FloatToShaderValueShaderLabSafe(value);
switch (floatType)
{
case FloatType.Slider:
return $"{hideTagString}{referenceName}(\"{displayName}\", Range({NodeUtils.FloatToShaderValue(m_RangeValues.x)}, {NodeUtils.FloatToShaderValue(m_RangeValues.y)})) = {valueString}";
case FloatType.Integer:
return $"{hideTagString}{referenceName}(\"{displayName}\", Int) = {((int)value).ToString(CultureInfo.InvariantCulture)}";
case FloatType.Enum:
return $"{hideTagString}{enumTagString}{referenceName}(\"{displayName}\", Float) = {valueString}";
default:
return $"{hideTagString}{referenceName}(\"{displayName}\", Float) = {valueString}";
}
}
internal override string GetPropertyAsArgumentString()
{
return $"{concreteShaderValueType.ToShaderString(concretePrecision.ToShaderString())} {referenceName}";
}
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
HLSLDeclaration decl = GetDefaultHLSLDeclaration();
action(new HLSLProperty(HLSLType._float, referenceName, decl, concretePrecision));
}
[SerializeField]
FloatType m_FloatType = FloatType.Default;
public FloatType floatType
{
get => m_FloatType;
set => m_FloatType = value;
}
[SerializeField]
Vector2 m_RangeValues = new Vector2(0, 1);
public Vector2 rangeValues
{
get => m_RangeValues;
set => m_RangeValues = value;
}
EnumType m_EnumType = EnumType.Enum;
public EnumType enumType
{
get => m_EnumType;
set => m_EnumType = value;
}
Type m_CSharpEnumType;
public Type cSharpEnumType
{
get => m_CSharpEnumType;
set => m_CSharpEnumType = value;
}
List<string> m_EnumNames = new List<string>();
public List<string> enumNames
{
get => m_EnumNames;
set => m_EnumNames = value;
}
List<int> m_EnumValues = new List<int>();
public List<int> enumValues
{
get => m_EnumValues;
set => m_EnumValues = value;
}
internal override AbstractMaterialNode ToConcreteNode()
{
switch (m_FloatType)
{
case FloatType.Slider:
return new SliderNode { value = new Vector3(value, m_RangeValues.x, m_RangeValues.y) };
case FloatType.Integer:
return new IntegerNode { value = (int)value };
default:
var node = new Vector1Node();
node.FindInputSlot<Vector1MaterialSlot>(Vector1Node.InputSlotXId).value = value;
return node;
}
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
floatValue = value
};
}
internal override ShaderInput Copy()
{
return new Vector1ShaderProperty()
{
displayName = displayName,
value = value,
floatType = floatType,
rangeValues = rangeValues,
enumType = enumType,
enumNames = enumNames,
enumValues = enumValues,
};
}
public override int latestVersion => 1;
public override void OnAfterDeserialize(string json)
{
if (sgVersion == 0)
{
LegacyShaderPropertyData.UpgradeToHLSLDeclarationOverride(json, this);
ChangeVersion(1);
}
}
}
public enum FloatType { Default, Slider, Integer, Enum }
public enum EnumType { Enum, CSharpEnum, KeywordEnum, }
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Vector2MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Vector2>
{
[SerializeField]
Vector2 m_Value;
[SerializeField]
Vector2 m_DefaultValue = Vector2.zero;
[SerializeField]
string[] m_Labels; // this can be null, which means fallback to k_LabelDefaults
static readonly string[] k_LabelDefaults = { "X", "Y" };
string[] labels
{
get
{
if ((m_Labels == null) || (m_Labels.Length != k_LabelDefaults.Length))
return k_LabelDefaults;
return m_Labels;
}
}
public Vector2MaterialSlot()
{
}
public Vector2MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector2 value,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
string label1 = null,
string label2 = null,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
if ((label1 != null) || (label2 != null))
{
m_Labels = new[]
{
label1 ?? k_LabelDefaults[0],
label2 ?? k_LabelDefaults[1]
};
}
}
public Vector2 defaultValue { get { return m_DefaultValue; } }
public Vector2 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
public override VisualElement InstantiateControl()
{
return new MultiFloatSlotControlView(owner, labels, () => value, (newValue) => value = newValue);
}
protected override string ConcreteSlotValueAsVariable()
{
return string.Format("$precision2 ({0}, {1})"
, NodeUtils.FloatToShaderValue(value.x)
, NodeUtils.FloatToShaderValue(value.y));
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new Vector2ShaderProperty
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Vector2)
{
name = name,
vector4Value = new Vector4(value.x, value.y, 0, 0),
};
properties.Add(pp);
}
public override SlotValueType valueType { get { return SlotValueType.Vector2; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Vector2; } }
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Vector2MaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Vector2> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.Vector2ShaderProperty")]
[BlackboardInputInfo(1)]
public sealed class Vector2ShaderProperty : VectorShaderProperty
{
internal Vector2ShaderProperty()
{
displayName = "Vector2";
}
public override PropertyType propertyType => PropertyType.Vector2;
internal override AbstractMaterialNode ToConcreteNode()
{
var node = new Vector2Node();
node.FindInputSlot<Vector1MaterialSlot>(Vector2Node.InputSlotXId).value = value.x;
node.FindInputSlot<Vector1MaterialSlot>(Vector2Node.InputSlotYId).value = value.y;
return node;
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
vector4Value = value
};
}
internal override ShaderInput Copy()
{
return new Vector2ShaderProperty()
{
displayName = displayName,
value = value,
};
}
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
HLSLDeclaration decl = GetDefaultHLSLDeclaration();
action(new HLSLProperty(HLSLType._float2, referenceName, decl, concretePrecision));
}
public override int latestVersion => 1;
public override void OnAfterDeserialize(string json)
{
if (sgVersion == 0)
{
LegacyShaderPropertyData.UpgradeToHLSLDeclarationOverride(json, this);
ChangeVersion(1);
}
}
}
}

View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Vector3MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Vector3>
{
[SerializeField]
private Vector3 m_Value;
[SerializeField]
private Vector3 m_DefaultValue = Vector3.zero;
[SerializeField]
string[] m_Labels; // this can be null, which means fallback to k_LabelDefaults
static readonly string[] k_LabelDefaults = { "X", "Y", "Z" };
string[] labels
{
get
{
if ((m_Labels == null) || (m_Labels.Length != k_LabelDefaults.Length))
return k_LabelDefaults;
return m_Labels;
}
}
public Vector3MaterialSlot()
{
}
public Vector3MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector3 value,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
string label1 = null,
string label2 = null,
string label3 = null,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
if ((label1 != null) || (label2 != null) || (label3 != null))
{
m_Labels = new[]
{
label1 ?? k_LabelDefaults[0],
label2 ?? k_LabelDefaults[1],
label3 ?? k_LabelDefaults[2]
};
}
}
public Vector3 defaultValue { get { return m_DefaultValue; } }
public Vector3 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
public override VisualElement InstantiateControl()
{
return new MultiFloatSlotControlView(owner, labels, () => value, (newValue) => value = newValue);
}
protected override string ConcreteSlotValueAsVariable()
{
return string.Format("$precision3 ({0}, {1}, {2})"
, NodeUtils.FloatToShaderValue(value.x)
, NodeUtils.FloatToShaderValue(value.y)
, NodeUtils.FloatToShaderValue(value.z));
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new Vector3ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Vector3)
{
name = name,
vector4Value = new Vector4(value.x, value.y, value.z, 0)
};
properties.Add(pp);
}
public override SlotValueType valueType { get { return SlotValueType.Vector3; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Vector3; } }
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Vector3MaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Vector3> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.Vector3ShaderProperty")]
[BlackboardInputInfo(3)]
public sealed class Vector3ShaderProperty : VectorShaderProperty
{
internal Vector3ShaderProperty()
{
displayName = "Vector3";
}
public override PropertyType propertyType => PropertyType.Vector3;
internal override AbstractMaterialNode ToConcreteNode()
{
var node = new Vector3Node();
node.FindInputSlot<Vector1MaterialSlot>(Vector3Node.InputSlotXId).value = value.x;
node.FindInputSlot<Vector1MaterialSlot>(Vector3Node.InputSlotYId).value = value.y;
node.FindInputSlot<Vector1MaterialSlot>(Vector3Node.InputSlotZId).value = value.z;
return node;
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
vector4Value = value
};
}
internal override ShaderInput Copy()
{
return new Vector3ShaderProperty()
{
displayName = displayName,
value = value,
};
}
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
HLSLDeclaration decl = GetDefaultHLSLDeclaration();
action(new HLSLProperty(HLSLType._float3, referenceName, decl, concretePrecision));
}
public override int latestVersion => 1;
public override void OnAfterDeserialize(string json)
{
if (sgVersion == 0)
{
LegacyShaderPropertyData.UpgradeToHLSLDeclarationOverride(json, this);
ChangeVersion(1);
}
}
}
}

View File

@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class Vector4MaterialSlot : MaterialSlot, IMaterialSlotHasValue<Vector4>
{
[SerializeField]
private Vector4 m_Value;
[SerializeField]
private Vector4 m_DefaultValue = Vector4.zero;
[SerializeField]
string[] m_Labels; // this can be null, which means fallback to k_LabelDefaults
static readonly string[] k_LabelDefaults = { "X", "Y", "Z", "W" };
string[] labels
{
get
{
if ((m_Labels == null) || (m_Labels.Length != k_LabelDefaults.Length))
return k_LabelDefaults;
return m_Labels;
}
}
public Vector4MaterialSlot()
{
}
public Vector4MaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
Vector4 value,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
string label1 = null,
string label2 = null,
string label3 = null,
string label4 = null,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{
m_Value = value;
if ((label1 != null) || (label2 != null) || (label3 != null) || (label4 != null))
{
m_Labels = new[]
{
label1 ?? k_LabelDefaults[0],
label2 ?? k_LabelDefaults[1],
label3 ?? k_LabelDefaults[2],
label4 ?? k_LabelDefaults[3]
};
}
}
public Vector4 defaultValue { get { return m_DefaultValue; } }
public Vector4 value
{
get { return m_Value; }
set { m_Value = value; }
}
public override bool isDefaultValue => value.Equals(defaultValue);
public override VisualElement InstantiateControl()
{
return new MultiFloatSlotControlView(owner, labels, () => value, (newValue) => value = newValue);
}
protected override string ConcreteSlotValueAsVariable()
{
return string.Format("$precision4 ({0}, {1}, {2}, {3})"
, NodeUtils.FloatToShaderValue(value.x)
, NodeUtils.FloatToShaderValue(value.y)
, NodeUtils.FloatToShaderValue(value.z)
, NodeUtils.FloatToShaderValue(value.w));
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
if (!generationMode.IsPreview())
return;
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
var property = new Vector4ShaderProperty()
{
overrideReferenceName = matOwner.GetVariableNameForSlot(id),
generatePropertyBlock = false,
value = value
};
properties.AddShaderProperty(property);
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
var pp = new PreviewProperty(PropertyType.Vector4)
{
name = name,
vector4Value = new Vector4(value.x, value.y, value.z, value.w),
};
properties.Add(pp);
}
public override SlotValueType valueType { get { return SlotValueType.Vector4; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.Vector4; } }
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
var slot = foundSlot as Vector4MaterialSlot;
if (slot != null)
value = slot.value;
}
public override void CopyDefaultValue(MaterialSlot other)
{
base.CopyDefaultValue(other);
if (other is IMaterialSlotHasValue<Vector4> ms)
{
m_DefaultValue = ms.defaultValue;
}
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
[FormerName("UnityEditor.ShaderGraph.Vector4ShaderProperty")]
[BlackboardInputInfo(4)]
public sealed class Vector4ShaderProperty : VectorShaderProperty
{
internal Vector4ShaderProperty()
{
displayName = "Vector4";
}
public override PropertyType propertyType => PropertyType.Vector4;
internal override AbstractMaterialNode ToConcreteNode()
{
var node = new Vector4Node();
node.FindInputSlot<Vector1MaterialSlot>(Vector4Node.InputSlotXId).value = value.x;
node.FindInputSlot<Vector1MaterialSlot>(Vector4Node.InputSlotYId).value = value.y;
node.FindInputSlot<Vector1MaterialSlot>(Vector4Node.InputSlotZId).value = value.z;
node.FindInputSlot<Vector1MaterialSlot>(Vector4Node.InputSlotWId).value = value.w;
return node;
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
vector4Value = value
};
}
internal override ShaderInput Copy()
{
return new Vector4ShaderProperty()
{
displayName = displayName,
value = value,
};
}
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
HLSLDeclaration decl = GetDefaultHLSLDeclaration();
action(new HLSLProperty(HLSLType._float4, referenceName, decl, concretePrecision));
}
public override int latestVersion => 1;
public override void OnAfterDeserialize(string json)
{
if (sgVersion == 0)
{
LegacyShaderPropertyData.UpgradeToHLSLDeclarationOverride(json, this);
ChangeVersion(1);
}
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Text;
using UnityEditor.Graphing;
using UnityEngine;
namespace UnityEditor.ShaderGraph.Internal
{
[Serializable]
public abstract class VectorShaderProperty : AbstractShaderProperty<Vector4>
{
internal override bool isExposable => true;
internal override bool isRenamable => true;
internal override string GetPropertyBlockString()
{
return $"{hideTagString}{referenceName}(\"{displayName}\", Vector) = ({NodeUtils.FloatToShaderValueShaderLabSafe(value.x)}, {NodeUtils.FloatToShaderValueShaderLabSafe(value.y)}, {NodeUtils.FloatToShaderValueShaderLabSafe(value.z)}, {NodeUtils.FloatToShaderValueShaderLabSafe(value.w)})";
}
internal override string GetPropertyAsArgumentString()
{
return $"{concreteShaderValueType.ToShaderString(concretePrecision.ToShaderString())} {referenceName}";
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using UnityEditor.Graphing;
using UnityEngine;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class VertexColorMaterialSlot : Vector4MaterialSlot, IMayRequireScreenPosition
{
public VertexColorMaterialSlot(int slotId, string displayName, string shaderOutputName,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden)
{}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView("Vertex Color");
}
public override string GetDefaultValue(GenerationMode generationMode)
{
return string.Format("IN.{0}", ShaderGeneratorNames.VertexColor);
}
public bool RequiresScreenPosition(ShaderStageCapability stageCapability)
{
return !isConnected;
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class ViewDirectionMaterialSlot : SpaceMaterialSlot, IMayRequireViewDirection
{
public ViewDirectionMaterialSlot()
{}
public ViewDirectionMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space,
ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false)
: base(slotId, displayName, shaderOutputName, space, stageCapability, hidden)
{}
public override VisualElement InstantiateControl()
{
return new LabelSlotControlView(space + " Space");
}
public override string GetDefaultValue(GenerationMode generationMode)
{
return string.Format("IN.{0}", space.ToVariableName(InterpolatorType.ViewDirection));
}
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability)
{
if (isConnected)
return NeededCoordinateSpace.None;
return space.ToNeededCoordinateSpace();
}
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Drawing.Slots;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class VirtualTextureInputMaterialSlot : VirtualTextureMaterialSlot
{
public VirtualTextureInputMaterialSlot()
{
}
public VirtualTextureInputMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, SlotType.Input, stageCapability, hidden)
{
}
public override VisualElement InstantiateControl()
{
return null;
}
public override string GetDefaultValue(GenerationMode generationMode)
{
var matOwner = owner as AbstractMaterialNode;
if (matOwner == null)
throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
return matOwner.GetVariableNameForSlot(id);
}
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
}
public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
{
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using UnityEditor.Graphing;
namespace UnityEditor.ShaderGraph
{
[Serializable]
class VirtualTextureMaterialSlot : MaterialSlot
{
public VirtualTextureMaterialSlot()
{}
public VirtualTextureMaterialSlot(
int slotId,
string displayName,
string shaderOutputName,
SlotType slotType,
ShaderStageCapability stageCapability = ShaderStageCapability.All,
bool hidden = false)
: base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
{}
public override SlotValueType valueType { get { return SlotValueType.VirtualTexture; } }
public override ConcreteSlotValueType concreteValueType { get { return ConcreteSlotValueType.VirtualTexture; } }
public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
{
}
public override void CopyValuesFrom(MaterialSlot foundSlot)
{
}
public override bool isDefaultValue => throw new Exception();
}
}

View File

@@ -0,0 +1,208 @@
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.ShaderGraph.Drawing.Controls;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
[Serializable]
[BlackboardInputInfo(60)]
class VirtualTextureShaderProperty : AbstractShaderProperty<SerializableVirtualTexture>
{
public VirtualTextureShaderProperty()
{
displayName = "VirtualTexture";
value = new SerializableVirtualTexture();
// add at least one layer
value.layers = new List<SerializableVirtualTextureLayer>();
value.layers.Add(new SerializableVirtualTextureLayer("Layer0", new SerializableTexture()));
value.layers.Add(new SerializableVirtualTextureLayer("Layer1", new SerializableTexture()));
}
public override PropertyType propertyType => PropertyType.VirtualTexture;
internal override bool isExposable => true; // the textures are exposable at least..
internal override bool isRenamable => true;
internal override void GetPropertyReferenceNames(List<string> result)
{
result.Add(referenceName);
for (int layer = 0; layer < value.layers.Count; layer++)
{
result.Add(value.layers[layer].layerRefName);
}
}
internal override void GetPropertyDisplayNames(List<string> result)
{
result.Add(displayName);
for (int layer = 0; layer < value.layers.Count; layer++)
{
result.Add(value.layers[layer].layerName);
}
}
// this is used for properties exposed to the Material in the shaderlab Properties{} block
internal override void AppendPropertyBlockStrings(ShaderStringBuilder builder)
{
if (!value.procedural)
{
// adds properties in this format so: [TextureStack.MyStack(0)] [NoScaleOffset] Layer0("Layer0", 2D) = "white" {}
for (int layer = 0; layer < value.layers.Count; layer++)
{
string layerName = value.layers[layer].layerName;
string layerRefName = value.layers[layer].layerRefName;
builder.AppendLine($"{hideTagString}[TextureStack.{referenceName}({layer})][NoScaleOffset]{layerRefName}(\"{layerName}\", 2D) = \"white\" {{}}");
}
}
}
internal override string GetPropertyBlockString()
{
// this should not be called, as it is replaced by the Append*PropertyBlockStrings function above
throw new NotSupportedException();
}
internal override bool AllowHLSLDeclaration(HLSLDeclaration decl) => false; // disable UI, nothing to choose
internal override void ForeachHLSLProperty(Action<HLSLProperty> action)
{
int numLayers = value.layers.Count;
if (numLayers > 0)
{
action(new HLSLProperty(HLSLType._CUSTOM, referenceName, HLSLDeclaration.UnityPerMaterial, concretePrecision)
{
customDeclaration = (ssb) =>
{
ssb.AppendIndentation();
ssb.Append("DECLARE_STACK_CB(");
ssb.Append(referenceName);
ssb.Append(");");
ssb.AppendNewLine();
}
});
if (!value.procedural)
{
// declare regular texture properties (for fallback case)
for (int i = 0; i < numLayers; i++)
{
string layerRefName = value.layers[i].layerRefName;
action(new HLSLProperty(HLSLType._Texture2D, layerRefName, HLSLDeclaration.Global));
action(new HLSLProperty(HLSLType._SamplerState, "sampler" + layerRefName, HLSLDeclaration.Global));
}
}
Action<ShaderStringBuilder> customDecl = (builder) =>
{
// declare texture stack
builder.AppendIndentation();
builder.Append("DECLARE_STACK");
builder.Append((numLayers <= 1) ? "" : numLayers.ToString());
builder.Append("(");
builder.Append(referenceName);
builder.Append(",");
for (int i = 0; i < value.layers.Count; i++)
{
if (i != 0) builder.Append(",");
builder.Append(value.layers[i].layerRefName);
}
builder.Append(");");
builder.AppendNewLine();
// declare the actual virtual texture property "variable" as a macro define to the BuildVTProperties function
builder.AppendIndentation();
builder.Append("#define ");
builder.Append(referenceName);
builder.Append(" AddTextureType(BuildVTProperties_");
builder.Append(referenceName);
builder.Append("()");
for (int i = 0; i < value.layers.Count; i++)
{
builder.Append(",");
builder.Append("TEXTURETYPE_");
builder.Append(value.layers[i].layerTextureType.ToString().ToUpper());
}
builder.Append(")");
builder.AppendNewLine();
};
action(new HLSLProperty(HLSLType._CUSTOM, referenceName, HLSLDeclaration.Global, concretePrecision)
{
customDeclaration = customDecl
});
}
}
// argument string used to pass this property to a subgraph
internal override string GetPropertyAsArgumentString()
{
return "VTPropertyWithTextureType " + referenceName;
}
// if a blackboard property is deleted, or copy/pasted, all node instances of it are replaced with this:
internal override AbstractMaterialNode ToConcreteNode()
{
return null; // return null to indicate there is NO concrete form of a VT property
}
internal override PreviewProperty GetPreviewMaterialProperty()
{
return new PreviewProperty(propertyType)
{
name = referenceName,
vtProperty = this
};
}
internal override ShaderInput Copy()
{
var vt = new VirtualTextureShaderProperty
{
displayName = displayName,
value = new SerializableVirtualTexture(),
};
// duplicate layer data, but reset reference names (they should be unique)
for (int layer = 0; layer < value.layers.Count; layer++)
{
var guid = Guid.NewGuid();
vt.value.layers.Add(new SerializableVirtualTextureLayer(value.layers[layer]));
}
return vt;
}
internal void AddTextureInfo(List<PropertyCollector.TextureInfo> infos)
{
for (int layer = 0; layer < value.layers.Count; layer++)
{
string layerRefName = value.layers[layer].layerRefName;
var layerTexture = value.layers[layer].layerTexture;
var texture = layerTexture != null ? layerTexture.texture : null;
var textureInfo = new PropertyCollector.TextureInfo
{
name = layerRefName,
textureId = texture != null ? texture.GetInstanceID() : 0,
dimension = texture != null ? texture.dimension : UnityEngine.Rendering.TextureDimension.Any,
modifiable = true
};
infos.Add(textureInfo);
}
}
internal override bool isAlwaysExposed => true;
public override void OnAfterDeserialize(string json)
{
// VT shader properties must always be exposed
generatePropertyBlock = true;
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using UnityEngine;
namespace UnityEditor.Graphing
{
[Serializable]
class Edge : IEdge, IComparable<Edge>
{
[SerializeField]
private SlotReference m_OutputSlot;
[SerializeField]
private SlotReference m_InputSlot;
public Edge()
{}
public Edge(SlotReference outputSlot, SlotReference inputSlot)
{
m_OutputSlot = outputSlot;
m_InputSlot = inputSlot;
}
public SlotReference outputSlot
{
get { return m_OutputSlot; }
}
public SlotReference inputSlot
{
get { return m_InputSlot; }
}
protected bool Equals(Edge other)
{
return Equals(m_OutputSlot, other.m_OutputSlot) && Equals(m_InputSlot, other.m_InputSlot);
}
public bool Equals(IEdge other)
{
return Equals(other as object);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Edge)obj);
}
public override int GetHashCode()
{
unchecked
{
// Can't make fields readonly due to Unity serialization
return (m_OutputSlot.GetHashCode() * 397) ^ m_InputSlot.GetHashCode();
}
}
public int CompareTo(Edge other)
{
if (ReferenceEquals(this, other)) return 0;
if (ReferenceEquals(null, other)) return 1;
var outputSlotComparison = m_OutputSlot.CompareTo(other.m_OutputSlot);
if (outputSlotComparison != 0) return outputSlotComparison;
return m_InputSlot.CompareTo(other.m_InputSlot);
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine;
namespace UnityEditor.Graphing
{
class GraphObject : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField]
SerializationHelper.JSONSerializedElement m_SerializedGraph;
[SerializeField]
int m_SerializedVersion;
[SerializeField]
bool m_IsDirty;
[SerializeField]
bool m_IsSubGraph;
[SerializeField]
string m_AssetGuid;
[NonSerialized]
GraphData m_Graph;
[NonSerialized]
int m_DeserializedVersion;
public GraphData graph
{
get { return m_Graph; }
set
{
if (m_Graph != null)
m_Graph.owner = null;
m_Graph = value;
if (m_Graph != null)
m_Graph.owner = this;
}
}
// this value stores whether an undo operation has been registered (which indicates a change has been made to the graph)
// and is used to trigger the MaterialGraphEditWindow to update it's title
public bool isDirty
{
get { return m_IsDirty; }
set { m_IsDirty = value; }
}
public virtual void RegisterCompleteObjectUndo(string actionName)
{
Undo.RegisterCompleteObjectUndo(this, actionName);
m_SerializedVersion++;
m_DeserializedVersion++;
m_IsDirty = true;
}
public void OnBeforeSerialize()
{
if (graph != null)
{
var json = MultiJson.Serialize(graph);
m_SerializedGraph = new SerializationHelper.JSONSerializedElement { JSONnodeData = json };
m_IsSubGraph = graph.isSubGraph;
m_AssetGuid = graph.assetGuid;
}
}
public void OnAfterDeserialize()
{
}
public bool wasUndoRedoPerformed => m_DeserializedVersion != m_SerializedVersion;
public void HandleUndoRedo()
{
Debug.Assert(wasUndoRedoPerformed);
var deserializedGraph = DeserializeGraph();
m_Graph.ReplaceWith(deserializedGraph);
}
GraphData DeserializeGraph()
{
var json = m_SerializedGraph.JSONnodeData;
var deserializedGraph = new GraphData {isSubGraph = m_IsSubGraph, assetGuid = m_AssetGuid};
MultiJson.Deserialize(deserializedGraph, json);
m_DeserializedVersion = m_SerializedVersion;
m_SerializedGraph = default;
return deserializedGraph;
}
public void Validate()
{
if (graph != null)
{
graph.OnEnable();
graph.ValidateGraph();
}
}
void OnEnable()
{
if (graph == null && m_SerializedGraph.JSONnodeData != null)
{
graph = DeserializeGraph();
}
Validate();
}
void OnDestroy()
{
graph?.OnDisable();
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace UnityEditor.ShaderGraph
{
[AttributeUsage(AttributeTargets.Class)]
class HasDependenciesAttribute : Attribute
{
public HasDependenciesAttribute(Type minimalType)
{
this.minimalType = minimalType;
}
public Type minimalType { get; }
}
}

View File

@@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace UnityEditor.ShaderGraph
{
interface IHasDependencies
{
void GetSourceAssetDependencies(AssetCollection assetCollection);
}
}

View File

@@ -0,0 +1,998 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using UnityEditor.ShaderGraph;
using UnityEngine;
using UnityEngine.Pool;
using UnityEngine.Rendering.ShaderGraph;
namespace UnityEditor.Graphing
{
class SlotConfigurationException : Exception
{
public SlotConfigurationException(string message)
: base(message)
{}
}
static class NodeUtils
{
static string NodeDocSuffix = "-Node";
public static void SlotConfigurationExceptionIfBadConfiguration(AbstractMaterialNode node, IEnumerable<int> expectedInputSlots, IEnumerable<int> expectedOutputSlots)
{
var missingSlots = new List<int>();
var inputSlots = expectedInputSlots as IList<int> ?? expectedInputSlots.ToList();
missingSlots.AddRange(inputSlots.Except(node.GetInputSlots<MaterialSlot>().Select(x => x.id)));
var outputSlots = expectedOutputSlots as IList<int> ?? expectedOutputSlots.ToList();
missingSlots.AddRange(outputSlots.Except(node.GetOutputSlots<MaterialSlot>().Select(x => x.id)));
if (missingSlots.Count == 0)
return;
var toPrint = missingSlots.Select(x => x.ToString());
throw new SlotConfigurationException(string.Format("Missing slots {0} on node {1}", string.Join(", ", toPrint.ToArray()), node));
}
public static IEnumerable<IEdge> GetAllEdges(AbstractMaterialNode node)
{
var result = new List<IEdge>();
var validSlots = ListPool<MaterialSlot>.Get();
validSlots.AddRange(node.GetInputSlots<MaterialSlot>());
for (int index = 0; index < validSlots.Count; index++)
{
var inputSlot = validSlots[index];
result.AddRange(node.owner.GetEdges(inputSlot.slotReference));
}
validSlots.Clear();
validSlots.AddRange(node.GetOutputSlots<MaterialSlot>());
for (int index = 0; index < validSlots.Count; index++)
{
var outputSlot = validSlots[index];
result.AddRange(node.owner.GetEdges(outputSlot.slotReference));
}
ListPool<MaterialSlot>.Release(validSlots);
return result;
}
public static string GetDuplicateSafeNameForSlot(AbstractMaterialNode node, int slotId, string name)
{
List<MaterialSlot> slots = new List<MaterialSlot>();
node.GetSlots(slots);
name = name.Trim();
return GraphUtil.SanitizeName(slots.Where(p => p.id != slotId).Select(p => p.RawDisplayName()), "{0} ({1})", name);
}
// CollectNodesNodeFeedsInto looks at the current node and calculates
// which child nodes it depends on for it's calculation.
// Results are returned depth first so by processing each node in
// order you can generate a valid code block.
public enum IncludeSelf
{
Include,
Exclude
}
public static SlotReference DepthFirstCollectRedirectNodeFromNode(RedirectNodeData node)
{
var inputSlot = node.FindSlot<MaterialSlot>(RedirectNodeData.kInputSlotID);
foreach (var edge in node.owner.GetEdges(inputSlot.slotReference))
{
// get the input details
var outputSlotRef = edge.outputSlot;
var inputNode = outputSlotRef.node;
// If this is a redirect node we continue to look for the top one
if (inputNode is RedirectNodeData redirectNode)
{
return DepthFirstCollectRedirectNodeFromNode(redirectNode);
}
return outputSlotRef;
}
// If no edges it is the first redirect node without an edge going into it and we should return the slot ref
return node.GetSlotReference(RedirectNodeData.kInputSlotID);
}
public static void DepthFirstCollectNodesFromNode(List<AbstractMaterialNode> nodeList, AbstractMaterialNode node,
IncludeSelf includeSelf = IncludeSelf.Include, List<KeyValuePair<ShaderKeyword, int>> keywordPermutation = null, bool ignoreActiveState = false)
{
// no where to start
if (node == null)
return;
// already added this node
if (nodeList.Contains(node))
return;
IEnumerable<int> ids;
// If this node is a keyword node and we have an active keyword permutation
// The only valid port id is the port that corresponds to that keywords value in the active permutation
if (node is KeywordNode keywordNode && keywordPermutation != null)
{
var valueInPermutation = keywordPermutation.Where(x => x.Key == keywordNode.keyword).FirstOrDefault();
ids = new int[] { keywordNode.GetSlotIdForPermutation(valueInPermutation) };
}
else
{
ids = node.GetInputSlots<MaterialSlot>().Select(x => x.id);
}
foreach (var slot in ids)
{
foreach (var edge in node.owner.GetEdges(node.GetSlotReference(slot)))
{
var outputNode = edge.outputSlot.node;
if (outputNode != null)
DepthFirstCollectNodesFromNode(nodeList, outputNode, keywordPermutation: keywordPermutation, ignoreActiveState: ignoreActiveState);
}
}
if (includeSelf == IncludeSelf.Include && (node.isActive || ignoreActiveState))
nodeList.Add(node);
}
private static List<AbstractMaterialNode> GetParentNodes(AbstractMaterialNode node)
{
List<AbstractMaterialNode> nodeList = new List<AbstractMaterialNode>();
var ids = node.GetInputSlots<MaterialSlot>().Select(x => x.id);
foreach (var slot in ids)
{
if (node.owner == null)
break;
foreach (var edge in node.owner.GetEdges(node.FindSlot<MaterialSlot>(slot).slotReference))
{
var outputNode = ((Edge)edge).outputSlot.node;
if (outputNode != null)
{
nodeList.Add(outputNode);
}
}
}
return nodeList;
}
private static bool ActiveLeafExists(AbstractMaterialNode node)
{
//if our active state has been explicitly set to a value use it
switch (node.activeState)
{
case AbstractMaterialNode.ActiveState.Implicit:
break;
case AbstractMaterialNode.ActiveState.ExplicitInactive:
return false;
case AbstractMaterialNode.ActiveState.ExplicitActive:
return true;
}
List<AbstractMaterialNode> parentNodes = GetParentNodes(node);
//at this point we know we are not explicitly set to a state,
//so there is no reason to be inactive
if (parentNodes.Count == 0)
{
return true;
}
bool output = false;
foreach (var parent in parentNodes)
{
output |= ActiveLeafExists(parent);
if (output)
{
break;
}
}
return output;
}
private static List<AbstractMaterialNode> GetChildNodes(AbstractMaterialNode node)
{
List<AbstractMaterialNode> nodeList = new List<AbstractMaterialNode>();
var ids = node.GetOutputSlots<MaterialSlot>().Select(x => x.id);
foreach (var slot in ids)
{
foreach (var edge in node.owner.GetEdges(node.FindSlot<MaterialSlot>(slot).slotReference))
{
var inputNode = ((Edge)edge).inputSlot.node;
if (inputNode != null)
{
nodeList.Add(inputNode);
}
}
}
return nodeList;
}
private static bool ActiveRootExists(AbstractMaterialNode node)
{
//if our active state has been explicitly set to a value use it
switch (node.activeState)
{
case AbstractMaterialNode.ActiveState.Implicit:
break;
case AbstractMaterialNode.ActiveState.ExplicitInactive:
return false;
case AbstractMaterialNode.ActiveState.ExplicitActive:
return true;
}
List<AbstractMaterialNode> childNodes = GetChildNodes(node);
//at this point we know we are not explicitly set to a state,
//so there is no reason to be inactive
if (childNodes.Count == 0)
{
return true;
}
bool output = false;
foreach (var child in childNodes)
{
output |= ActiveRootExists(child);
if (output)
{
break;
}
}
return output;
}
private static void ActiveTreeExists(AbstractMaterialNode node, out bool activeLeaf, out bool activeRoot, out bool activeTree)
{
activeLeaf = ActiveLeafExists(node);
activeRoot = ActiveRootExists(node);
activeTree = activeRoot && activeLeaf;
}
//First pass check if node is now active after a change, so just check if there is a valid "tree" : a valid upstream input path,
// and a valid downstream output path, or "leaf" and "root". If this changes the node's active state, then anything connected may
// change as well, so update the "forrest" or all connectected trees of this nodes leaves.
// NOTE: I cannot think if there is any case where the entirety of the connected graph would need to change, but if there are bugs
// on certain nodes farther away from the node not updating correctly, a possible solution may be to get the entirety of the connected
// graph instead of just what I have declared as the "local" connected graph
public static void ReevaluateActivityOfConnectedNodes(AbstractMaterialNode node, PooledHashSet<AbstractMaterialNode> changedNodes = null)
{
List<AbstractMaterialNode> forest = GetForest(node);
ReevaluateActivityOfNodeList(forest, changedNodes);
}
public static void ReevaluateActivityOfNodeList(IEnumerable<AbstractMaterialNode> nodes, PooledHashSet<AbstractMaterialNode> changedNodes = null)
{
bool getChangedNodes = changedNodes != null;
foreach (AbstractMaterialNode n in nodes)
{
if (n.activeState != AbstractMaterialNode.ActiveState.Implicit)
continue;
ActiveTreeExists(n, out _, out _, out bool at);
if (n.isActive != at && getChangedNodes)
{
changedNodes.Add(n);
}
n.SetActive(at, false);
}
}
//Go to the leaves of the node, then get all trees with those leaves
private static List<AbstractMaterialNode> GetForest(AbstractMaterialNode node)
{
List<AbstractMaterialNode> leaves = GetLeaves(node);
List<AbstractMaterialNode> forrest = new List<AbstractMaterialNode>();
foreach (var leaf in leaves)
{
if (!forrest.Contains(leaf))
{
forrest.Add(leaf);
}
foreach (var child in GetChildNodesRecursive(leaf))
{
if (!forrest.Contains(child))
{
forrest.Add(child);
}
}
}
return forrest;
}
private static List<AbstractMaterialNode> GetChildNodesRecursive(AbstractMaterialNode node)
{
List<AbstractMaterialNode> output = new List<AbstractMaterialNode>() { node };
List<AbstractMaterialNode> children = GetChildNodes(node);
foreach (var child in children)
{
if (!output.Contains(child))
{
output.Add(child);
}
foreach (var descendent in GetChildNodesRecursive(child))
{
if (!output.Contains(descendent))
{
output.Add(descendent);
}
}
}
return output;
}
private static List<AbstractMaterialNode> GetLeaves(AbstractMaterialNode node)
{
List<AbstractMaterialNode> parents = GetParentNodes(node);
List<AbstractMaterialNode> output = new List<AbstractMaterialNode>();
if (parents.Count == 0)
{
output.Add(node);
}
else
{
foreach (var parent in parents)
{
foreach (var leaf in GetLeaves(parent))
{
if (!output.Contains(leaf))
{
output.Add(leaf);
}
}
}
}
return output;
}
public static void GetDownsteamNodesForNode(List<AbstractMaterialNode> nodeList, AbstractMaterialNode node)
{
// no where to start
if (node == null)
return;
// Recursively traverse downstream from the original node
// Traverse down each edge and continue on any connected downstream nodes
// Only nodes with no nodes further downstream are added to node list
bool hasDownstream = false;
var ids = node.GetOutputSlots<MaterialSlot>().Select(x => x.id);
foreach (var slot in ids)
{
foreach (var edge in node.owner.GetEdges(node.FindSlot<MaterialSlot>(slot).slotReference))
{
var inputNode = ((Edge)edge).inputSlot.node;
if (inputNode != null)
{
hasDownstream = true;
GetDownsteamNodesForNode(nodeList, inputNode);
}
}
}
// No more nodes downstream from here
if (!hasDownstream)
nodeList.Add(node);
}
public static void CollectNodeSet(HashSet<AbstractMaterialNode> nodeSet, MaterialSlot slot)
{
var node = slot.owner;
var graph = node.owner;
foreach (var edge in graph.GetEdges(node.GetSlotReference(slot.id)))
{
var outputNode = edge.outputSlot.node;
if (outputNode != null)
{
CollectNodeSet(nodeSet, outputNode);
}
}
}
public static void CollectNodeSet(HashSet<AbstractMaterialNode> nodeSet, AbstractMaterialNode node)
{
if (!nodeSet.Add(node))
{
return;
}
using (ListPool<MaterialSlot>.Get(out var slots))
{
node.GetInputSlots(slots);
foreach (var slot in slots)
{
CollectNodeSet(nodeSet, slot);
}
}
}
public static void CollectNodesNodeFeedsInto(List<AbstractMaterialNode> nodeList, AbstractMaterialNode node, IncludeSelf includeSelf = IncludeSelf.Include)
{
if (node == null)
return;
if (nodeList.Contains(node))
return;
foreach (var slot in node.GetOutputSlots<MaterialSlot>())
{
foreach (var edge in node.owner.GetEdges(slot.slotReference))
{
var inputNode = edge.inputSlot.node;
CollectNodesNodeFeedsInto(nodeList, inputNode);
}
}
if (includeSelf == IncludeSelf.Include)
nodeList.Add(node);
}
public static string GetDocumentationString(string pageName)
{
return Documentation.GetPageLink(pageName.Replace(" ", "-") + NodeDocSuffix);
}
static Stack<MaterialSlot> s_SlotStack = new Stack<MaterialSlot>();
public static ShaderStage GetEffectiveShaderStage(MaterialSlot initialSlot, bool goingBackwards)
{
var graph = initialSlot.owner.owner;
s_SlotStack.Clear();
s_SlotStack.Push(initialSlot);
while (s_SlotStack.Any())
{
var slot = s_SlotStack.Pop();
ShaderStage stage;
if (slot.stageCapability.TryGetShaderStage(out stage))
return stage;
if (goingBackwards && slot.isInputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
{
var node = edge.outputSlot.node;
s_SlotStack.Push(node.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId));
}
}
else if (!goingBackwards && slot.isOutputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
{
var node = edge.inputSlot.node;
s_SlotStack.Push(node.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId));
}
}
else
{
var ownerSlots = Enumerable.Empty<MaterialSlot>();
if (goingBackwards && slot.isOutputSlot)
ownerSlots = slot.owner.GetInputSlots<MaterialSlot>();
else if (!goingBackwards && slot.isInputSlot)
ownerSlots = slot.owner.GetOutputSlots<MaterialSlot>();
foreach (var ownerSlot in ownerSlots)
s_SlotStack.Push(ownerSlot);
}
}
// We default to fragment shader stage if all connected nodes were compatible with both.
return ShaderStage.Fragment;
}
public static ShaderStageCapability GetEffectiveShaderStageCapability(MaterialSlot initialSlot, bool goingBackwards)
{
var graph = initialSlot.owner.owner;
s_SlotStack.Clear();
s_SlotStack.Push(initialSlot);
while (s_SlotStack.Any())
{
var slot = s_SlotStack.Pop();
ShaderStage stage;
if (slot.stageCapability.TryGetShaderStage(out stage))
return slot.stageCapability;
if (goingBackwards && slot.isInputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
{
var node = edge.outputSlot.node;
s_SlotStack.Push(node.FindOutputSlot<MaterialSlot>(edge.outputSlot.slotId));
}
}
else if (!goingBackwards && slot.isOutputSlot)
{
foreach (var edge in graph.GetEdges(slot.slotReference))
{
var node = edge.inputSlot.node;
s_SlotStack.Push(node.FindInputSlot<MaterialSlot>(edge.inputSlot.slotId));
}
}
else
{
var ownerSlots = Enumerable.Empty<MaterialSlot>();
if (goingBackwards && slot.isOutputSlot)
ownerSlots = slot.owner.GetInputSlots<MaterialSlot>();
else if (!goingBackwards && slot.isInputSlot)
ownerSlots = slot.owner.GetOutputSlots<MaterialSlot>();
foreach (var ownerSlot in ownerSlots)
s_SlotStack.Push(ownerSlot);
}
}
return ShaderStageCapability.All;
}
public static string GetSlotDimension(ConcreteSlotValueType slotValue)
{
switch (slotValue)
{
case ConcreteSlotValueType.Vector1:
return String.Empty;
case ConcreteSlotValueType.Vector2:
return "2";
case ConcreteSlotValueType.Vector3:
return "3";
case ConcreteSlotValueType.Vector4:
return "4";
case ConcreteSlotValueType.Matrix2:
return "2x2";
case ConcreteSlotValueType.Matrix3:
return "3x3";
case ConcreteSlotValueType.Matrix4:
return "4x4";
default:
return "Error";
}
}
// NOTE: there are several bugs here.. we should use ConvertToValidHLSLIdentifier() instead
public static string GetHLSLSafeName(string input)
{
char[] arr = input.ToCharArray();
arr = Array.FindAll<char>(arr, (c => (Char.IsLetterOrDigit(c))));
var safeName = new string(arr);
if (safeName.Length > 1 && char.IsDigit(safeName[0]))
{
safeName = $"var{safeName}";
}
return safeName;
}
static readonly string[] k_HLSLNumericKeywords =
{
"float",
"half", // not technically in HLSL spec, but prob should be
"real", // Unity thing, but included here
"int",
"uint",
"bool",
"min10float",
"min16float",
"min12int",
"min16int",
"min16uint"
};
static readonly string[] k_HLSLNumericKeywordSuffixes =
{
"",
"1", "2", "3", "4",
"1x1", "1x2", "1x3", "1x4",
"2x1", "2x2", "2x3", "2x4",
"3x1", "3x2", "3x3", "3x4",
"4x1", "4x2", "4x3", "4x4"
};
static HashSet<string> m_ShaderLabKeywords = new HashSet<string>()
{
// these should all be lowercase, as shaderlab keywords are case insensitive
"properties",
"range",
"bind",
"bindchannels",
"tags",
"lod",
"shader",
"subshader",
"category",
"fallback",
"dependency",
"customeditor",
"rect",
"any",
"float",
"color",
"int",
"integer",
"vector",
"matrix",
"2d",
"cube",
"3d",
"2darray",
"cubearray",
"name",
"settexture",
"true",
"false",
"on",
"off",
"separatespecular",
"offset",
"zwrite",
"zclip",
"conservative",
"ztest",
"alphatest",
"fog",
"stencil",
"colormask",
"alphatomask",
"cull",
"front",
"material",
"ambient",
"diffuse",
"specular",
"emission",
"shininess",
"blend",
"blendop",
"colormaterial",
"lighting",
"pass",
"grabpass",
"usepass",
"gpuprogramid",
"add",
"sub",
"revsub",
"min",
"max",
"logicalclear",
"logicalset",
"logicalcopy",
"logicalcopyinverted",
"logicalnoop",
"logicalinvert",
"logicaland",
"logicalnand",
"logicalor",
"logicalnor",
"logicalxor",
"logicalequiv",
"logicalandreverse",
"logicalandinverted",
"logicalorreverse",
"logicalorinverted",
"multiply",
"screen",
"overlay",
"darken",
"lighten",
"colordodge",
"colorburn",
"hardlight",
"softlight",
"difference",
"exclusion",
"hslhue",
"hslsaturation",
"hslcolor",
"hslluminosity",
"zero",
"one",
"dstcolor",
"srccolor",
"oneminusdstcolor",
"srcalpha",
"oneminussrccolor",
"dstalpha",
"oneminusdstalpha",
"srcalphasaturate",
"oneminussrcalpha",
"constantcolor",
"oneminusconstantcolor",
"constantalpha",
"oneminusconstantalpha",
};
static HashSet<string> m_HLSLKeywords = new HashSet<string>()
{
"AppendStructuredBuffer",
"asm",
"asm_fragment",
"auto",
"BlendState",
"break",
"Buffer",
"ByteAddressBuffer",
"case",
"catch",
"cbuffer",
"centroid",
"char",
"class",
"column_major",
"compile",
"compile_fragment",
"CompileShader",
"const",
"const_cast",
"continue",
"ComputeShader",
"ConsumeStructuredBuffer",
"default",
"delete",
"DepthStencilState",
"DepthStencilView",
"discard",
"do",
"double",
"DomainShader",
"dynamic_cast",
"dword",
"else",
"enum",
"explicit",
"export",
"extern",
"false",
"for",
"friend",
"fxgroup",
"GeometryShader",
"goto",
"groupshared",
"half",
"Hullshader",
"if",
"in",
"inline",
"inout",
"InputPatch",
"interface",
"line",
"lineadj",
"linear",
"LineStream",
"long",
"matrix",
"mutable",
"namespace",
"new",
"nointerpolation",
"noperspective",
"NULL",
"operator",
"out",
"OutputPatch",
"packoffset",
"pass",
"pixelfragment",
"PixelShader",
"point",
"PointStream",
"precise",
"private",
"protected",
"public",
"RasterizerState",
"reinterpret_cast",
"RenderTargetView",
"return",
"register",
"row_major",
"RWBuffer",
"RWByteAddressBuffer",
"RWStructuredBuffer",
"RWTexture1D",
"RWTexture1DArray",
"RWTexture2D",
"RWTexture2DArray",
"RWTexture3D",
"sample",
"sampler",
"SamplerState",
"SamplerComparisonState",
"shared",
"short",
"signed",
"sizeof",
"snorm",
"stateblock",
"stateblock_state",
"static",
"static_cast",
"string",
"struct",
"switch",
"StructuredBuffer",
"tbuffer",
"technique",
"technique10",
"technique11",
"template",
"texture",
"Texture1D",
"Texture1DArray",
"Texture2D",
"Texture2DArray",
"Texture2DMS",
"Texture2DMSArray",
"Texture3D",
"TextureCube",
"TextureCubeArray",
"this",
"throw",
"true",
"try",
"typedef",
"typename",
"triangle",
"triangleadj",
"TriangleStream",
"uniform",
"unorm",
"union",
"unsigned",
"using",
"vector",
"vertexfragment",
"VertexShader",
"virtual",
"void",
"volatile",
"while"
};
static bool m_HLSLKeywordDictionaryBuilt = false;
public static bool IsHLSLKeyword(string id)
{
if (!m_HLSLKeywordDictionaryBuilt)
{
foreach (var numericKeyword in k_HLSLNumericKeywords)
foreach (var suffix in k_HLSLNumericKeywordSuffixes)
m_HLSLKeywords.Add(numericKeyword + suffix);
m_HLSLKeywordDictionaryBuilt = true;
}
bool isHLSLKeyword = m_HLSLKeywords.Contains(id);
return isHLSLKeyword;
}
public static bool IsShaderLabKeyWord(string id)
{
bool isShaderLabKeyword = m_ShaderLabKeywords.Contains(id.ToLower());
return isShaderLabKeyword;
}
public static string ConvertToValidHLSLIdentifier(string originalId, Func<string, bool> isDisallowedIdentifier = null)
{
// Converts " 1 var * q-30 ( 0 ) (1) " to "_1_var_q_30_0_1"
if (originalId == null)
originalId = "";
StringBuilder hlslId = new StringBuilder(originalId.Length);
bool lastInvalid = false;
for (int i = 0; i < originalId.Length; i++)
{
char c = originalId[i];
bool isLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
bool isUnderscore = (c == '_');
bool isDigit = (c >= '0' && c <= '9');
bool validChar = isLetter || isUnderscore || isDigit;
if (!validChar)
{
// when we see an invalid character, we just record that we saw it and go to the next character
// this way we combine multiple invalid characters, and trailing ones just get dropped
lastInvalid = true;
}
else
{
// whenever we hit a valid character
// if the last character was invalid, append an underscore
// unless we're at the beginning of the string
if (lastInvalid && (hlslId.Length > 0))
hlslId.Append("_");
// HLSL ids can't start with a digit, prepend an underscore to prevent this
if (isDigit && (hlslId.Length == 0))
hlslId.Append("_");
hlslId.Append(c);
lastInvalid = false;
}
}
// empty strings not allowed -- append an underscore if it's empty
if (hlslId.Length <= 0)
hlslId.Append("_");
var result = hlslId.ToString();
while (IsHLSLKeyword(result))
result = "_" + result;
if (isDisallowedIdentifier != null)
while (isDisallowedIdentifier(result))
result = "_" + result;
return result;
}
private static string GetDisplaySafeName(string input)
{
//strip valid display characters from slot name
//current valid characters are whitespace and ( ) _ separators
StringBuilder cleanName = new StringBuilder();
foreach (var c in input)
{
if (c != ' ' && c != '(' && c != ')' && c != '_')
cleanName.Append(c);
}
return cleanName.ToString();
}
public static bool ValidateSlotName(string inName, out string errorMessage)
{
//check for invalid characters between display safe and hlsl safe name
if (GetDisplaySafeName(inName) != GetHLSLSafeName(inName))
{
errorMessage = "Slot name(s) found invalid character(s). Valid characters: A-Z, a-z, 0-9, _ ( ) ";
return true;
}
//if clean, return null and false
errorMessage = null;
return false;
}
public static string FloatToShaderValue(float value)
{
if (Single.IsPositiveInfinity(value))
{
return "1.#INF";
}
if (Single.IsNegativeInfinity(value))
{
return "-1.#INF";
}
if (Single.IsNaN(value))
{
return "NAN";
}
return value.ToString(CultureInfo.InvariantCulture);
}
// A number large enough to become Infinity (~FLOAT_MAX_VALUE * 10) + explanatory comment
private const string k_ShaderLabInfinityAlternatrive = "3402823500000000000000000000000000000000 /* Infinity */";
// ShaderLab doesn't support Scientific Notion nor Infinity. To stop from generating a broken shader we do this.
public static string FloatToShaderValueShaderLabSafe(float value)
{
if (Single.IsPositiveInfinity(value))
{
return k_ShaderLabInfinityAlternatrive;
}
if (Single.IsNegativeInfinity(value))
{
return "-" + k_ShaderLabInfinityAlternatrive;
}
if (Single.IsNaN(value))
{
return "NAN"; // A real error has occured, in this case we should break the shader.
}
// For single point precision, reserve 54 spaces (e-45 min + ~9 digit precision). See floating-point-numeric-types (Microsoft docs).
return value.ToString("0.######################################################", CultureInfo.InvariantCulture);
}
}
}

View File

@@ -0,0 +1,8 @@
namespace UnityEditor.Graphing
{
enum SlotType
{
Input,
Output
}
}

View File

@@ -0,0 +1,12 @@
namespace UnityEditor.ShaderGraph
{
enum GenerationMode
{
Preview,
ForReals
}
static class GenerationModeExtensions
{
public static bool IsPreview(this GenerationMode mode) { return mode == GenerationMode.Preview; }
}
}

View File

@@ -0,0 +1,27 @@
using System;
using UnityEngine;
namespace UnityEditor.Graphing
{
[Serializable]
struct DrawState
{
[SerializeField]
private bool m_Expanded;
[SerializeField]
private Rect m_Position;
public bool expanded
{
get { return m_Expanded; }
set { m_Expanded = value; }
}
public Rect position
{
get { return m_Position; }
set { m_Position = value; }
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEditor.Graphing
{
[Serializable]
class GraphDrawingData : ISerializationCallbackReceiver
{
[SerializeField]
private List<string> m_SerializableSelection = new List<string>();
[NonSerialized]
private List<Guid> m_Selection = new List<Guid>();
public IEnumerable<Guid> selection
{
get { return m_Selection; }
set
{
m_Selection.Clear();
m_Selection.AddRange(value);
}
}
public void OnBeforeSerialize()
{
m_SerializableSelection.Clear();
m_SerializableSelection.AddRange(m_Selection.Select(x => x.ToString()));
}
public void OnAfterDeserialize()
{
selection = m_SerializableSelection.Select(x => new Guid(x));
}
}
}

View File

@@ -0,0 +1,10 @@
using System;
namespace UnityEditor.Graphing
{
interface IEdge : IEquatable<IEdge>
{
SlotReference outputSlot { get; }
SlotReference inputSlot { get; }
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using UnityEditor.ShaderGraph;
namespace UnityEditor.Graphing
{
enum ModificationScope
{
Nothing = 0,
Node = 1,
Graph = 2,
Topological = 3,
Layout = 4
}
delegate void OnNodeModified(AbstractMaterialNode node, ModificationScope scope);
static class NodeExtensions
{
public static IEnumerable<T> GetSlots<T>(this AbstractMaterialNode node) where T : MaterialSlot
{
var slots = new List<T>();
node.GetSlots(slots);
return slots;
}
public static IEnumerable<T> GetInputSlots<T>(this AbstractMaterialNode node) where T : MaterialSlot
{
var slots = new List<T>();
node.GetInputSlots(slots);
return slots;
}
public static IEnumerable<T> GetOutputSlots<T>(this AbstractMaterialNode node) where T : MaterialSlot
{
var slots = new List<T>();
node.GetOutputSlots(slots);
return slots;
}
}
}

View File

@@ -0,0 +1,7 @@
namespace UnityEditor.Graphing
{
interface IOnAssetEnabled
{
void OnEnable();
}
}

Some files were not shown because too many files have changed in this diff Show More