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,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;
}
}
}