initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -0,0 +1,135 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
class FunctionSource
|
||||
{
|
||||
public string code;
|
||||
public HashSet<AbstractMaterialNode> nodes;
|
||||
public bool isGeneric;
|
||||
public int graphPrecisionFlags; // Flags<GraphPrecision>
|
||||
public int concretePrecisionFlags; // Flags<ConcretePrecision>
|
||||
}
|
||||
|
||||
class FunctionRegistry
|
||||
{
|
||||
Dictionary<string, FunctionSource> m_Sources = new Dictionary<string, FunctionSource>();
|
||||
bool m_Validate = false;
|
||||
ShaderStringBuilder m_Builder;
|
||||
IncludeCollection m_Includes;
|
||||
|
||||
public FunctionRegistry(ShaderStringBuilder builder, IncludeCollection includes, bool validate = false)
|
||||
{
|
||||
m_Builder = builder;
|
||||
m_Includes = includes;
|
||||
m_Validate = validate;
|
||||
}
|
||||
|
||||
internal ShaderStringBuilder builder => m_Builder;
|
||||
|
||||
public Dictionary<string, FunctionSource> sources => m_Sources;
|
||||
|
||||
public void RequiresIncludes(IncludeCollection includes)
|
||||
{
|
||||
m_Includes.Add(includes);
|
||||
}
|
||||
|
||||
public void RequiresIncludePath(string includePath)
|
||||
{
|
||||
m_Includes.Add(includePath, IncludeLocation.Graph);
|
||||
}
|
||||
|
||||
// this list is somewhat redundant, but it preserves function declaration ordering
|
||||
// (i.e. when nodes add multiple functions, they require being defined in a certain order)
|
||||
public List<string> names { get; } = new List<string>();
|
||||
|
||||
public void ProvideFunction(string name, GraphPrecision graphPrecision, ConcretePrecision concretePrecision, Action<ShaderStringBuilder> generator)
|
||||
{
|
||||
// appends code, construct the standalone code string
|
||||
var originalIndex = builder.length;
|
||||
builder.AppendNewLine();
|
||||
|
||||
var startIndex = builder.length;
|
||||
generator(builder);
|
||||
var length = builder.length - startIndex;
|
||||
|
||||
// trim fixes mismatched whitespace issue when nodes come from subgraphs
|
||||
var code = builder.ToString(startIndex, length).Trim();
|
||||
|
||||
// validate some assumptions around generics
|
||||
bool isGenericName = name.Contains("$");
|
||||
bool isGenericFunc = code.Contains("$");
|
||||
bool isGeneric = isGenericName || isGenericFunc;
|
||||
bool containsFunctionName = code.Contains(name);
|
||||
|
||||
var curNode = builder.currentNode;
|
||||
if (isGenericName != isGenericFunc)
|
||||
curNode.owner.AddValidationError(curNode.objectId, $"Function {name} provided by node {curNode.name} contains $precision tokens in the name or the code, but not both. This is very likely an error.");
|
||||
|
||||
if (!containsFunctionName)
|
||||
curNode.owner.AddValidationError(curNode.objectId, $"Function {name} provided by node {curNode.name} does not contain the name of the function. This is very likely an error.");
|
||||
|
||||
int graphPrecisionFlag = (1 << (int)graphPrecision);
|
||||
int concretePrecisionFlag = (1 << (int)concretePrecision);
|
||||
|
||||
FunctionSource existingSource;
|
||||
if (m_Sources.TryGetValue(name, out existingSource))
|
||||
{
|
||||
// function already provided
|
||||
existingSource.nodes.Add(builder.currentNode);
|
||||
|
||||
// let's check if the requested precision variant has already been provided (or if it's not generic there are no variants)
|
||||
bool concretePrecisionExists = ((existingSource.concretePrecisionFlags & concretePrecisionFlag) != 0) || !isGeneric;
|
||||
|
||||
// if this precision was already added -- remove the duplicate code from the builder
|
||||
if (concretePrecisionExists)
|
||||
builder.length -= (builder.length - originalIndex);
|
||||
|
||||
// save the flags
|
||||
existingSource.graphPrecisionFlags = existingSource.graphPrecisionFlags | graphPrecisionFlag;
|
||||
existingSource.concretePrecisionFlags = existingSource.concretePrecisionFlags | concretePrecisionFlag;
|
||||
|
||||
// if validate, we double check that the two function declarations are the same
|
||||
if (m_Validate)
|
||||
{
|
||||
if (code != existingSource.code)
|
||||
{
|
||||
var errorMessage = string.Format("Function `{0}` has conflicting implementations:{1}{1}{2}{1}{1}{3}", name, Environment.NewLine, code, existingSource.code);
|
||||
foreach (var n in existingSource.nodes)
|
||||
n.owner.AddValidationError(n.objectId, errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var newSource = new FunctionSource
|
||||
{
|
||||
code = code,
|
||||
isGeneric = isGeneric,
|
||||
graphPrecisionFlags = graphPrecisionFlag,
|
||||
concretePrecisionFlags = concretePrecisionFlag,
|
||||
nodes = new HashSet<AbstractMaterialNode> { builder.currentNode }
|
||||
};
|
||||
|
||||
m_Sources.Add(name, newSource);
|
||||
names.Add(name);
|
||||
}
|
||||
|
||||
// fully concretize any generic code by replacing any precision tokens by the node's concrete precision
|
||||
if (isGeneric && (builder.length > originalIndex))
|
||||
{
|
||||
int start = originalIndex;
|
||||
int count = builder.length - start;
|
||||
builder.Replace(PrecisionUtil.Token, concretePrecision.ToShaderString(), start, count);
|
||||
}
|
||||
}
|
||||
|
||||
public void ProvideFunction(string name, Action<ShaderStringBuilder> generator)
|
||||
{
|
||||
ProvideFunction(name, builder.currentNode.graphPrecision, builder.currentNode.concretePrecision, generator);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7e4fc6f4e30c408f9c0304cbed39a076
|
||||
timeCreated: 1513609614
|
|
@ -0,0 +1,145 @@
|
|||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
static class GradientUtil
|
||||
{
|
||||
public static string GetGradientValue(Gradient gradient, string delimiter = ";")
|
||||
{
|
||||
string colorKeys = "";
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (i < gradient.colorKeys.Length)
|
||||
colorKeys += $"$precision4({NodeUtils.FloatToShaderValue(gradient.colorKeys[i].color.r)}, " +
|
||||
$"{NodeUtils.FloatToShaderValue(gradient.colorKeys[i].color.g)}, " +
|
||||
$"{NodeUtils.FloatToShaderValue(gradient.colorKeys[i].color.b)}, " +
|
||||
$"{NodeUtils.FloatToShaderValue(gradient.colorKeys[i].time)})";
|
||||
else
|
||||
colorKeys += "$precision4(0, 0, 0, 0)";
|
||||
if (i < 7)
|
||||
colorKeys += ",";
|
||||
}
|
||||
|
||||
string alphaKeys = "";
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (i < gradient.alphaKeys.Length)
|
||||
alphaKeys += $"$precision2({NodeUtils.FloatToShaderValue(gradient.alphaKeys[i].alpha)}, {NodeUtils.FloatToShaderValue(gradient.alphaKeys[i].time)})";
|
||||
else
|
||||
alphaKeys += "$precision2(0, 0)";
|
||||
if (i < 7)
|
||||
alphaKeys += ",";
|
||||
}
|
||||
|
||||
return $"NewGradient({(int)gradient.mode}, {gradient.colorKeys.Length}, {gradient.alphaKeys.Length}, {colorKeys}, {alphaKeys}){delimiter}";
|
||||
}
|
||||
|
||||
public static string GetGradientForPreview(string name)
|
||||
{
|
||||
string colorKeys = "";
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
colorKeys += $"{name}_ColorKey{i}";
|
||||
if (i < 7)
|
||||
colorKeys += ",";
|
||||
}
|
||||
|
||||
string alphaKeys = "";
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
alphaKeys += $"{name}_AlphaKey{i}";
|
||||
if (i < 7)
|
||||
alphaKeys += ",";
|
||||
}
|
||||
|
||||
return $"NewGradient({name}_Type, {name}_ColorsLength, {name}_AlphasLength, {colorKeys}, {alphaKeys})";
|
||||
}
|
||||
|
||||
public static void GetGradientPropertiesForPreview(PropertyCollector properties, string name, Gradient value)
|
||||
{
|
||||
properties.AddShaderProperty(new Vector1ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = $"{name}_Type",
|
||||
value = (int)value.mode,
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
|
||||
properties.AddShaderProperty(new Vector1ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = $"{name}_ColorsLength",
|
||||
value = value.colorKeys.Length,
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
|
||||
properties.AddShaderProperty(new Vector1ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = $"{name}_AlphasLength",
|
||||
value = value.alphaKeys.Length,
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
properties.AddShaderProperty(new Vector4ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = $"{name}_ColorKey{i}",
|
||||
value = i < value.colorKeys.Length ? GradientUtil.ColorKeyToVector(value.colorKeys[i]) : Vector4.zero,
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
properties.AddShaderProperty(new Vector2ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = $"{name}_AlphaKey{i}",
|
||||
value = i < value.alphaKeys.Length ? GradientUtil.AlphaKeyToVector(value.alphaKeys[i]) : Vector2.zero,
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckEquivalency(Gradient A, Gradient B)
|
||||
{
|
||||
var currentMode = A.mode;
|
||||
var currentColorKeys = A.colorKeys;
|
||||
var currentAlphaKeys = A.alphaKeys;
|
||||
|
||||
var newMode = B.mode;
|
||||
var newColorKeys = B.colorKeys;
|
||||
var newAlphaKeys = B.alphaKeys;
|
||||
|
||||
if (currentMode != newMode || currentColorKeys.Length != newColorKeys.Length || currentAlphaKeys.Length != newAlphaKeys.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < currentColorKeys.Length; i++)
|
||||
{
|
||||
if (currentColorKeys[i].color != newColorKeys[i].color || Mathf.Abs(currentColorKeys[i].time - newColorKeys[i].time) > 1e-9)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < currentAlphaKeys.Length; i++)
|
||||
{
|
||||
if (Mathf.Abs(currentAlphaKeys[i].alpha - newAlphaKeys[i].alpha) > 1e-9 || Mathf.Abs(currentAlphaKeys[i].time - newAlphaKeys[i].time) > 1e-9)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Vector4 ColorKeyToVector(GradientColorKey key)
|
||||
{
|
||||
return new Vector4(key.color.r, key.color.g, key.color.b, key.time);
|
||||
}
|
||||
|
||||
public static Vector2 AlphaKeyToVector(GradientAlphaKey key)
|
||||
{
|
||||
return new Vector2(key.alpha, key.time);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b59f719ccd61c3348bcda608976bd9aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,437 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.IsolatedStorage;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.Graphing.Util;
|
||||
using UnityEditorInternal;
|
||||
using Debug = UnityEngine.Debug;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Remoting.Metadata.W3cXsd2001;
|
||||
using UnityEditor.ProjectWindowCallback;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using Object = System.Object;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
// a structure used to track active variable dependencies in the shader code
|
||||
// (i.e. the use of uv0 in the pixel shader means we need a uv0 interpolator, etc.)
|
||||
struct Dependency
|
||||
{
|
||||
public string name; // the name of the thing
|
||||
public string dependsOn; // the thing above depends on this -- it reads it / calls it / requires it to be defined
|
||||
|
||||
public Dependency(string name, string dependsOn)
|
||||
{
|
||||
this.name = name;
|
||||
this.dependsOn = dependsOn;
|
||||
}
|
||||
};
|
||||
|
||||
[System.AttributeUsage(System.AttributeTargets.Struct)]
|
||||
class InterpolatorPack : System.Attribute
|
||||
{
|
||||
public InterpolatorPack()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// attribute used to flag a field as needing an HLSL semantic applied
|
||||
// i.e. float3 position : POSITION;
|
||||
// ^ semantic
|
||||
[System.AttributeUsage(System.AttributeTargets.Field)]
|
||||
class Semantic : System.Attribute
|
||||
{
|
||||
public string semantic;
|
||||
|
||||
public Semantic(string semantic)
|
||||
{
|
||||
this.semantic = semantic;
|
||||
}
|
||||
}
|
||||
|
||||
// attribute used to flag a field as being optional
|
||||
// i.e. if it is not active, then we can omit it from the struct
|
||||
[System.AttributeUsage(System.AttributeTargets.Field)]
|
||||
class Optional : System.Attribute
|
||||
{
|
||||
public Optional()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// attribute used to override the HLSL type of a field with a custom type string
|
||||
[System.AttributeUsage(System.AttributeTargets.Field)]
|
||||
class OverrideType : System.Attribute
|
||||
{
|
||||
public string typeName;
|
||||
|
||||
public OverrideType(string typeName)
|
||||
{
|
||||
this.typeName = typeName;
|
||||
}
|
||||
}
|
||||
|
||||
// attribute used to force system generated fields to bottom of structs
|
||||
[System.AttributeUsage(System.AttributeTargets.Field)]
|
||||
class SystemGenerated : System.Attribute
|
||||
{
|
||||
public SystemGenerated()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// attribute used to disable a field using a preprocessor #if
|
||||
[System.AttributeUsage(System.AttributeTargets.Field)]
|
||||
class PreprocessorIf : System.Attribute
|
||||
{
|
||||
public string conditional;
|
||||
|
||||
public PreprocessorIf(string conditional)
|
||||
{
|
||||
this.conditional = conditional;
|
||||
}
|
||||
}
|
||||
|
||||
class NewGraphAction : EndNameEditAction
|
||||
{
|
||||
Target[] m_Targets;
|
||||
public Target[] targets
|
||||
{
|
||||
get => m_Targets;
|
||||
set => m_Targets = value;
|
||||
}
|
||||
|
||||
BlockFieldDescriptor[] m_Blocks;
|
||||
public BlockFieldDescriptor[] blocks
|
||||
{
|
||||
get => m_Blocks;
|
||||
set => m_Blocks = value;
|
||||
}
|
||||
|
||||
public override void Action(int instanceId, string pathName, string resourceFile)
|
||||
{
|
||||
var graph = new GraphData();
|
||||
graph.AddContexts();
|
||||
graph.InitializeOutputs(m_Targets, m_Blocks);
|
||||
|
||||
graph.path = "Shader Graphs";
|
||||
FileUtilities.WriteShaderGraphToDisk(pathName, graph);
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath<Shader>(pathName);
|
||||
Selection.activeObject = obj;
|
||||
}
|
||||
}
|
||||
|
||||
static class GraphUtil
|
||||
{
|
||||
internal static bool CheckForRecursiveDependencyOnPendingSave(string saveFilePath, IEnumerable<SubGraphNode> subGraphNodes, string context = null)
|
||||
{
|
||||
var overwriteGUID = AssetDatabase.AssetPathToGUID(saveFilePath);
|
||||
if (!string.IsNullOrEmpty(overwriteGUID))
|
||||
{
|
||||
foreach (var sgNode in subGraphNodes)
|
||||
{
|
||||
var asset = sgNode?.asset;
|
||||
if (asset == null)
|
||||
{
|
||||
// cannot read the asset; might be recursive but we can't tell... should we return "maybe"?
|
||||
// I think to be minimally intrusive to the user we can assume "No" in this case,
|
||||
// even though this may miss recursions in extraordinary cases.
|
||||
// it's more important to allow the user to save their files than to catch 100% of recursions
|
||||
continue;
|
||||
}
|
||||
else if ((asset.assetGuid == overwriteGUID) || asset.descendents.Contains(overwriteGUID))
|
||||
{
|
||||
if (context != null)
|
||||
{
|
||||
Debug.LogWarning(context + " CANCELLED to avoid a generating a reference loop: the SubGraph '" + sgNode.asset.name + "' references the target file '" + saveFilePath + "'");
|
||||
EditorUtility.DisplayDialog(
|
||||
context + " CANCELLED",
|
||||
"Saving the file would generate a reference loop, because the SubGraph '" + sgNode.asset.name + "' references the target file '" + saveFilePath + "'", "Cancel");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static string ConvertCamelCase(string text, bool preserveAcronyms)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return string.Empty;
|
||||
StringBuilder newText = new StringBuilder(text.Length * 2);
|
||||
newText.Append(text[0]);
|
||||
for (int i = 1; i < text.Length; i++)
|
||||
{
|
||||
if (char.IsUpper(text[i]))
|
||||
if ((text[i - 1] != ' ' && !char.IsUpper(text[i - 1])) ||
|
||||
(preserveAcronyms && char.IsUpper(text[i - 1]) &&
|
||||
i < text.Length - 1 && !char.IsUpper(text[i + 1])))
|
||||
newText.Append(' ');
|
||||
newText.Append(text[i]);
|
||||
}
|
||||
return newText.ToString();
|
||||
}
|
||||
|
||||
public static void CreateNewGraph()
|
||||
{
|
||||
var graphItem = ScriptableObject.CreateInstance<NewGraphAction>();
|
||||
graphItem.targets = null;
|
||||
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, graphItem,
|
||||
string.Format("New Shader Graph.{0}", ShaderGraphImporter.Extension), null, null);
|
||||
}
|
||||
|
||||
public static void CreateNewGraphWithOutputs(Target[] targets, BlockFieldDescriptor[] blockDescriptors)
|
||||
{
|
||||
var graphItem = ScriptableObject.CreateInstance<NewGraphAction>();
|
||||
graphItem.targets = targets;
|
||||
graphItem.blocks = blockDescriptors;
|
||||
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, graphItem,
|
||||
string.Format("New Shader Graph.{0}", ShaderGraphImporter.Extension), null, null);
|
||||
}
|
||||
|
||||
public static bool TryGetMetadataOfType<T>(this Shader shader, out T obj) where T : ScriptableObject
|
||||
{
|
||||
obj = null;
|
||||
if (!shader.IsShaderGraphAsset())
|
||||
return false;
|
||||
|
||||
var path = AssetDatabase.GetAssetPath(shader);
|
||||
foreach (var asset in AssetDatabase.LoadAllAssetsAtPath(path))
|
||||
{
|
||||
if (asset is T metadataAsset)
|
||||
{
|
||||
obj = metadataAsset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// this will work on ALL shadergraph-built shaders, in memory or asset based
|
||||
public static bool IsShaderGraph(this Material material)
|
||||
{
|
||||
var shaderGraphTag = material.GetTag("ShaderGraphShader", false, null);
|
||||
return !string.IsNullOrEmpty(shaderGraphTag);
|
||||
}
|
||||
|
||||
// NOTE: this ONLY works for ASSET based Shaders, if you created a temporary shader in memory, it won't work
|
||||
public static bool IsShaderGraphAsset(this Shader shader)
|
||||
{
|
||||
var path = AssetDatabase.GetAssetPath(shader);
|
||||
var importer = AssetImporter.GetAtPath(path);
|
||||
return importer is ShaderGraphImporter;
|
||||
}
|
||||
|
||||
[Obsolete("Use IsShaderGraphAsset instead", false)]
|
||||
public static bool IsShaderGraph(this Shader shader) => shader.IsShaderGraphAsset();
|
||||
|
||||
static void Visit(List<AbstractMaterialNode> outputList, Dictionary<string, AbstractMaterialNode> unmarkedNodes, AbstractMaterialNode node)
|
||||
{
|
||||
if (!unmarkedNodes.ContainsKey(node.objectId))
|
||||
return;
|
||||
foreach (var slot in node.GetInputSlots<MaterialSlot>())
|
||||
{
|
||||
foreach (var edge in node.owner.GetEdges(slot.slotReference))
|
||||
{
|
||||
var inputNode = edge.outputSlot.node;
|
||||
Visit(outputList, unmarkedNodes, inputNode);
|
||||
}
|
||||
}
|
||||
unmarkedNodes.Remove(node.objectId);
|
||||
outputList.Add(node);
|
||||
}
|
||||
|
||||
static Dictionary<SerializationHelper.TypeSerializationInfo, SerializationHelper.TypeSerializationInfo> s_LegacyTypeRemapping;
|
||||
|
||||
public static Dictionary<SerializationHelper.TypeSerializationInfo, SerializationHelper.TypeSerializationInfo> GetLegacyTypeRemapping()
|
||||
{
|
||||
if (s_LegacyTypeRemapping == null)
|
||||
{
|
||||
s_LegacyTypeRemapping = new Dictionary<SerializationHelper.TypeSerializationInfo, SerializationHelper.TypeSerializationInfo>();
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
foreach (var type in assembly.GetTypesOrNothing())
|
||||
{
|
||||
if (type.IsAbstract)
|
||||
continue;
|
||||
foreach (var attribute in type.GetCustomAttributes(typeof(FormerNameAttribute), false))
|
||||
{
|
||||
var legacyAttribute = (FormerNameAttribute)attribute;
|
||||
var serializationInfo = new SerializationHelper.TypeSerializationInfo { fullName = legacyAttribute.fullName };
|
||||
s_LegacyTypeRemapping[serializationInfo] = SerializationHelper.GetTypeSerializableAsString(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s_LegacyTypeRemapping;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sanitizes a supplied string such that it does not collide
|
||||
/// with any other name in a collection.
|
||||
/// </summary>
|
||||
/// <param name="existingNames">
|
||||
/// A collection of names that the new name should not collide with.
|
||||
/// </param>
|
||||
/// <param name="duplicateFormat">
|
||||
/// The format applied to the name if a duplicate exists.
|
||||
/// This must be a format string that contains `{0}` and `{1}`
|
||||
/// once each. An example could be `{0} ({1})`, which will append ` (n)`
|
||||
/// to the name for the n`th duplicate.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// The name to be sanitized.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A name that is distinct form any name in `existingNames`.
|
||||
/// </returns>
|
||||
internal static string SanitizeName(IEnumerable<string> existingNames, string duplicateFormat, string name, string disallowedPatternRegex = "\"")
|
||||
{
|
||||
name = Regex.Replace(name, disallowedPatternRegex, "_");
|
||||
return DeduplicateName(existingNames, duplicateFormat, name);
|
||||
}
|
||||
|
||||
internal static string SanitizeCategoryName(string categoryName, string disallowedPatternRegex = "\"")
|
||||
{
|
||||
return Regex.Replace(categoryName, disallowedPatternRegex, "_");
|
||||
}
|
||||
|
||||
internal static string DeduplicateName(IEnumerable<string> existingNames, string duplicateFormat, string name)
|
||||
{
|
||||
if (!existingNames.Contains(name))
|
||||
return name;
|
||||
|
||||
string escapedDuplicateFormat = Regex.Escape(duplicateFormat);
|
||||
|
||||
// Escaped format will escape string interpolation, so the escape characters must be removed for these.
|
||||
escapedDuplicateFormat = escapedDuplicateFormat.Replace(@"\{0}", @"{0}");
|
||||
escapedDuplicateFormat = escapedDuplicateFormat.Replace(@"\{1}", @"{1}");
|
||||
|
||||
var baseRegex = new Regex(string.Format(escapedDuplicateFormat, @"^(.*)", @"(\d+)"));
|
||||
|
||||
var baseMatch = baseRegex.Match(name);
|
||||
if (baseMatch.Success)
|
||||
name = baseMatch.Groups[1].Value;
|
||||
|
||||
string baseNameExpression = string.Format(@"^{0}", Regex.Escape(name));
|
||||
var regex = new Regex(string.Format(escapedDuplicateFormat, baseNameExpression, @"(\d+)") + "$");
|
||||
|
||||
var existingDuplicateNumbers = existingNames.Select(existingName => regex.Match(existingName)).Where(m => m.Success).Select(m => int.Parse(m.Groups[1].Value)).Where(n => n > 0).Distinct().ToList();
|
||||
|
||||
var duplicateNumber = 1;
|
||||
existingDuplicateNumbers.Sort();
|
||||
if (existingDuplicateNumbers.Any() && existingDuplicateNumbers.First() == 1)
|
||||
{
|
||||
duplicateNumber = existingDuplicateNumbers.Last() + 1;
|
||||
for (var i = 1; i < existingDuplicateNumbers.Count; i++)
|
||||
{
|
||||
if (existingDuplicateNumbers[i - 1] != existingDuplicateNumbers[i] - 1)
|
||||
{
|
||||
duplicateNumber = existingDuplicateNumbers[i - 1] + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Format(duplicateFormat, name, duplicateNumber);
|
||||
}
|
||||
|
||||
public static bool WriteToFile(string path, string content)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.WriteAllText(path, content);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenFile(string path)
|
||||
{
|
||||
string filePath = Path.GetFullPath(path);
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
Debug.LogError(string.Format("Path {0} doesn't exists", path));
|
||||
return;
|
||||
}
|
||||
|
||||
string externalScriptEditor = ScriptEditorUtility.GetExternalScriptEditor();
|
||||
if (externalScriptEditor != "internal")
|
||||
{
|
||||
InternalEditorUtility.OpenFileAtLineExternal(filePath, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process p = new Process();
|
||||
p.StartInfo.FileName = filePath;
|
||||
p.EnableRaisingEvents = true;
|
||||
p.Exited += (Object obj, EventArgs args) =>
|
||||
{
|
||||
if (p.ExitCode != 0)
|
||||
Debug.LogWarningFormat("Unable to open {0}: Check external editor in preferences", filePath);
|
||||
};
|
||||
p.Start();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Find all nodes of the given type downstream from the given node
|
||||
// Returns a unique list. So even if a node can be reached through different paths it will be present only once.
|
||||
//
|
||||
public static List<NodeType> FindDownStreamNodesOfType<NodeType>(AbstractMaterialNode node) where NodeType : AbstractMaterialNode
|
||||
{
|
||||
// Should never be called without a node
|
||||
Debug.Assert(node != null);
|
||||
|
||||
HashSet<AbstractMaterialNode> visitedNodes = new HashSet<AbstractMaterialNode>();
|
||||
List<NodeType> vtNodes = new List<NodeType>();
|
||||
Queue<AbstractMaterialNode> nodeStack = new Queue<AbstractMaterialNode>();
|
||||
nodeStack.Enqueue(node);
|
||||
visitedNodes.Add(node);
|
||||
|
||||
while (nodeStack.Count > 0)
|
||||
{
|
||||
AbstractMaterialNode visit = nodeStack.Dequeue();
|
||||
|
||||
// Flood fill through all the nodes
|
||||
foreach (var slot in visit.GetInputSlots<MaterialSlot>())
|
||||
{
|
||||
foreach (var edge in visit.owner.GetEdges(slot.slotReference))
|
||||
{
|
||||
var inputNode = edge.outputSlot.node;
|
||||
if (!visitedNodes.Contains(inputNode))
|
||||
{
|
||||
nodeStack.Enqueue(inputNode);
|
||||
visitedNodes.Add(inputNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract vt node
|
||||
if (visit is NodeType)
|
||||
{
|
||||
NodeType vtNode = visit as NodeType;
|
||||
vtNodes.Add(vtNode);
|
||||
}
|
||||
}
|
||||
|
||||
return vtNodes;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 130a64d32c054c5fb51b1e5e13f93fc2
|
||||
timeCreated: 1513590591
|
|
@ -0,0 +1,37 @@
|
|||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
struct Identifier
|
||||
{
|
||||
uint m_Version;
|
||||
int m_Index;
|
||||
|
||||
public Identifier(int index, uint version = 1)
|
||||
{
|
||||
m_Version = version;
|
||||
m_Index = index;
|
||||
}
|
||||
|
||||
public void IncrementVersion()
|
||||
{
|
||||
if (m_Version == uint.MaxValue)
|
||||
m_Version = 1;
|
||||
else
|
||||
m_Version++;
|
||||
}
|
||||
|
||||
public uint version
|
||||
{
|
||||
get { return m_Version; }
|
||||
}
|
||||
|
||||
public int index
|
||||
{
|
||||
get { return m_Index; }
|
||||
}
|
||||
|
||||
public bool valid
|
||||
{
|
||||
get { return m_Version != 0; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 084958a703164b0fa26e0667aaa1767f
|
||||
timeCreated: 1513937833
|
|
@ -0,0 +1,99 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
class KeywordCollector
|
||||
{
|
||||
public readonly List<ShaderKeyword> keywords;
|
||||
public readonly List<List<KeyValuePair<ShaderKeyword, int>>> permutations;
|
||||
|
||||
public KeywordCollector()
|
||||
{
|
||||
keywords = new List<ShaderKeyword>();
|
||||
permutations = new List<List<KeyValuePair<ShaderKeyword, int>>>();
|
||||
}
|
||||
|
||||
public void AddShaderKeyword(ShaderKeyword chunk)
|
||||
{
|
||||
if (keywords.Any(x => x.referenceName == chunk.referenceName))
|
||||
return;
|
||||
|
||||
keywords.Add(chunk);
|
||||
}
|
||||
|
||||
public void GetKeywordsDeclaration(ShaderStringBuilder builder, GenerationMode mode)
|
||||
{
|
||||
if (keywords.Count == 0)
|
||||
return;
|
||||
|
||||
// Declare keywords
|
||||
foreach (var keyword in keywords)
|
||||
{
|
||||
// Hardcode active keywords in preview to reduce compiled variants
|
||||
if (mode == GenerationMode.Preview)
|
||||
{
|
||||
string declaration = keyword.GetKeywordPreviewDeclarationString();
|
||||
if (!string.IsNullOrEmpty(declaration))
|
||||
{
|
||||
builder.AppendLine(declaration);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
keyword.AppendKeywordDeclarationStrings(builder);
|
||||
}
|
||||
}
|
||||
|
||||
// Declare another keyword per permutation for simpler if/defs in the graph code
|
||||
builder.AppendNewLine();
|
||||
KeywordUtil.GetKeywordPermutationDeclarations(builder, permutations);
|
||||
builder.AppendNewLine();
|
||||
}
|
||||
|
||||
public void CalculateKeywordPermutations()
|
||||
{
|
||||
permutations.Clear();
|
||||
|
||||
// Initialize current permutation
|
||||
List<KeyValuePair<ShaderKeyword, int>> currentPermutation = new List<KeyValuePair<ShaderKeyword, int>>();
|
||||
for (int i = 0; i < keywords.Count; i++)
|
||||
{
|
||||
currentPermutation.Add(new KeyValuePair<ShaderKeyword, int>(keywords[i], 0));
|
||||
}
|
||||
|
||||
// Recursively permute keywords
|
||||
PermuteKeywords(keywords, currentPermutation, 0);
|
||||
}
|
||||
|
||||
void PermuteKeywords(List<ShaderKeyword> keywords, List<KeyValuePair<ShaderKeyword, int>> currentPermutation, int currentIndex)
|
||||
{
|
||||
if (currentIndex == keywords.Count)
|
||||
return;
|
||||
|
||||
// Iterate each possible keyword at the current index
|
||||
int entryCount = keywords[currentIndex].keywordType == KeywordType.Enum ? keywords[currentIndex].entries.Count : 2;
|
||||
for (int i = 0; i < entryCount; i++)
|
||||
{
|
||||
// Set the index in the current permutation to the correct value
|
||||
currentPermutation[currentIndex] = new KeyValuePair<ShaderKeyword, int>(keywords[currentIndex], i);
|
||||
|
||||
// If the current index is the last keyword we are finished with this permutation
|
||||
if (currentIndex == keywords.Count - 1)
|
||||
{
|
||||
permutations.Add(currentPermutation);
|
||||
}
|
||||
// Otherwise we continue adding keywords to this permutation
|
||||
else
|
||||
{
|
||||
PermuteKeywords(keywords, currentPermutation, currentIndex + 1);
|
||||
}
|
||||
|
||||
// Duplicate current permutation
|
||||
currentPermutation = currentPermutation.Select(item => item).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ea731ae969f51e948bdc8eb82a6542e1
|
||||
timeCreated: 1469695793
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,87 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEditor.ShaderGraph.Internal
|
||||
{
|
||||
public static class KeywordDependentCollection
|
||||
{
|
||||
public enum KeywordPermutationInstanceType
|
||||
{
|
||||
Base,
|
||||
Permutation,
|
||||
}
|
||||
|
||||
public interface ISet<IInstance>
|
||||
{
|
||||
int instanceCount { get; }
|
||||
IEnumerable<IInstance> instances { get; }
|
||||
}
|
||||
|
||||
public interface IInstance
|
||||
{
|
||||
KeywordPermutationInstanceType type { get; }
|
||||
int permutationIndex { get; }
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class KeywordDependentCollection<TStorage, TAll, TAllPermutations, TForPermutation, TBase, TIInstance, TISet>
|
||||
where TAll : TISet
|
||||
where TAllPermutations : TISet
|
||||
where TForPermutation : TISet, TIInstance
|
||||
where TBase : TISet, TIInstance
|
||||
where TISet : KeywordDependentCollection.ISet<TIInstance>
|
||||
where TIInstance : KeywordDependentCollection.IInstance
|
||||
where TStorage : new()
|
||||
{
|
||||
TStorage m_Base = new TStorage();
|
||||
List<TStorage> m_PerPermutationIndex = new List<TStorage>();
|
||||
|
||||
public int permutationCount => m_PerPermutationIndex.Count;
|
||||
|
||||
public TForPermutation this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
GetOrCreateForPermutationIndex(index);
|
||||
return CreateForPermutationSmartPointer(index);
|
||||
}
|
||||
}
|
||||
|
||||
public TAll all => CreateAllSmartPointer();
|
||||
public TAllPermutations allPermutations => CreateAllPermutationsSmartPointer();
|
||||
|
||||
/// <summary>
|
||||
/// All permutation will inherit from base's active fields
|
||||
/// </summary>
|
||||
public TBase baseInstance => CreateBaseSmartPointer();
|
||||
|
||||
protected TStorage baseStorage
|
||||
{
|
||||
get => m_Base;
|
||||
set => m_Base = value;
|
||||
}
|
||||
|
||||
protected IEnumerable<TStorage> permutationStorages => m_PerPermutationIndex;
|
||||
|
||||
protected TStorage GetOrCreateForPermutationIndex(int index)
|
||||
{
|
||||
while (index >= m_PerPermutationIndex.Count)
|
||||
m_PerPermutationIndex.Add(new TStorage());
|
||||
|
||||
return m_PerPermutationIndex[index];
|
||||
}
|
||||
|
||||
protected void SetForPermutationIndex(int index, TStorage value)
|
||||
{
|
||||
while (index >= m_PerPermutationIndex.Count)
|
||||
m_PerPermutationIndex.Add(new TStorage());
|
||||
|
||||
m_PerPermutationIndex[index] = value;
|
||||
}
|
||||
|
||||
protected abstract TAll CreateAllSmartPointer();
|
||||
protected abstract TAllPermutations CreateAllPermutationsSmartPointer();
|
||||
protected abstract TForPermutation CreateForPermutationSmartPointer(int index);
|
||||
protected abstract TBase CreateBaseSmartPointer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 34772c0f4dfcde7428f8bacfb0ce0552
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,274 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor.ShaderGraph.Drawing;
|
||||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
static class BuiltinKeyword
|
||||
{
|
||||
[BuiltinKeyword]
|
||||
public static KeywordDescriptor QualityKeyword()
|
||||
{
|
||||
return new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Material Quality",
|
||||
referenceName = "MATERIAL_QUALITY",
|
||||
type = KeywordType.Enum,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
value = 0,
|
||||
entries = new KeywordEntry[]
|
||||
{
|
||||
new KeywordEntry("High", "HIGH"),
|
||||
new KeywordEntry("Medium", "MEDIUM"),
|
||||
new KeywordEntry("Low", "LOW"),
|
||||
},
|
||||
stages = KeywordShaderStage.All,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static class KeywordUtil
|
||||
{
|
||||
public static IEnumerable<KeywordDescriptor> GetBuiltinKeywordDescriptors() =>
|
||||
TypeCache.GetMethodsWithAttribute<BuiltinKeywordAttribute>()
|
||||
.Where(method => method.IsStatic && method.ReturnType == typeof(KeywordDescriptor))
|
||||
.Select(method =>
|
||||
(KeywordDescriptor)method.Invoke(null, new object[0] { }));
|
||||
|
||||
public static ConcreteSlotValueType ToConcreteSlotValueType(this KeywordType keywordType)
|
||||
{
|
||||
switch (keywordType)
|
||||
{
|
||||
case KeywordType.Boolean:
|
||||
return ConcreteSlotValueType.Boolean;
|
||||
case KeywordType.Enum:
|
||||
return ConcreteSlotValueType.Vector1;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToDeclarationSuffix(this KeywordScope scope)
|
||||
{
|
||||
switch (scope)
|
||||
{
|
||||
case KeywordScope.Local:
|
||||
return "_local";
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToDeclarationString(this KeywordDefinition keywordDefinition)
|
||||
{
|
||||
switch (keywordDefinition)
|
||||
{
|
||||
case KeywordDefinition.MultiCompile:
|
||||
return "multi_compile";
|
||||
case KeywordDefinition.ShaderFeature:
|
||||
return "shader_feature";
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateKeywordPragmaStrings(
|
||||
string keywordReferenceName,
|
||||
KeywordDefinition keywordDefinition,
|
||||
KeywordScope keywordScope,
|
||||
KeywordShaderStage keywordStages,
|
||||
string keywordVariantsString,
|
||||
Action<string> PragmaStringAction)
|
||||
{
|
||||
string definitionString = keywordDefinition.ToDeclarationString();
|
||||
string scopeString = keywordScope.ToDeclarationSuffix();
|
||||
|
||||
// check the active shader stages
|
||||
if ((keywordStages == KeywordShaderStage.All) || (keywordStages == 0)) // 0 is a default, so assume that means ALL
|
||||
{
|
||||
PragmaStringAction($"#pragma {definitionString}{scopeString} {keywordVariantsString}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// have to process each stage separately
|
||||
for (int shaderStage = (int)KeywordShaderStage.Vertex; shaderStage <= (int)keywordStages; shaderStage = shaderStage * 2)
|
||||
{
|
||||
if (((int)keywordStages & shaderStage) != 0)
|
||||
{
|
||||
var keywordStage = (KeywordShaderStage)shaderStage;
|
||||
var stageString = keywordStage.ToKeywordStagesString();
|
||||
PragmaStringAction($"#pragma {definitionString}{scopeString}{stageString} {keywordVariantsString}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void GenerateEnumKeywordPragmaStrings(
|
||||
string keywordReferenceName,
|
||||
KeywordDefinition keywordDefinition,
|
||||
KeywordScope keywordScope,
|
||||
KeywordShaderStage keywordStages,
|
||||
IEnumerable<KeywordEntry> keywordEntries,
|
||||
Action<string> pragmaStringAction)
|
||||
{
|
||||
if (keywordDefinition != KeywordDefinition.Predefined)
|
||||
{
|
||||
var entryStrings = keywordEntries.Select(x => $"{keywordReferenceName}_{x.referenceName}");
|
||||
string variantsString = string.Join(" ", entryStrings);
|
||||
GenerateKeywordPragmaStrings(keywordReferenceName, keywordDefinition, keywordScope, keywordStages, variantsString, pragmaStringAction);
|
||||
}
|
||||
}
|
||||
|
||||
public static void GenerateBooleanKeywordPragmaStrings(
|
||||
string keywordReferenceName,
|
||||
KeywordDefinition keywordDefinition,
|
||||
KeywordScope keywordScope,
|
||||
KeywordShaderStage keywordStages,
|
||||
Action<string> pragmaStringAction)
|
||||
{
|
||||
if (keywordDefinition != KeywordDefinition.Predefined)
|
||||
{
|
||||
string variantsString = $"_ {keywordReferenceName}";
|
||||
GenerateKeywordPragmaStrings(keywordReferenceName, keywordDefinition, keywordScope, keywordStages, variantsString, pragmaStringAction);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToKeywordStagesString(this KeywordShaderStage stages)
|
||||
{
|
||||
string outString = "";
|
||||
|
||||
if (stages == KeywordShaderStage.All)
|
||||
return outString;
|
||||
if (stages == KeywordShaderStage.Vertex)
|
||||
outString += "_vertex";
|
||||
if (stages == KeywordShaderStage.Fragment)
|
||||
outString += "_fragment";
|
||||
if (stages == KeywordShaderStage.Geometry)
|
||||
outString += "_geometry";
|
||||
if (stages == KeywordShaderStage.Hull)
|
||||
outString += "_hull";
|
||||
if (stages == KeywordShaderStage.Domain)
|
||||
outString += "_domain";
|
||||
if (stages == KeywordShaderStage.RayTracing)
|
||||
outString += "_raytracing";
|
||||
|
||||
return outString;
|
||||
}
|
||||
|
||||
public static string ToDefineString(this KeywordDescriptor keyword, int value)
|
||||
{
|
||||
switch (keyword.type)
|
||||
{
|
||||
case KeywordType.Boolean:
|
||||
return value == 1 ? $"#define {keyword.referenceName} 1" : string.Empty;
|
||||
case KeywordType.Enum:
|
||||
return $"#define {keyword.referenceName}_{keyword.entries[value].referenceName}";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetKeywordPermutationSetConditional(List<int> permutationSet)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("#if ");
|
||||
|
||||
for (int i = 0; i < permutationSet.Count; i++)
|
||||
{
|
||||
// Subsequent permutation predicates require ||
|
||||
if (i != 0)
|
||||
sb.Append(" || ");
|
||||
|
||||
// Append permutation
|
||||
sb.Append($"defined(KEYWORD_PERMUTATION_{permutationSet[i]})");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string GetKeywordPermutationConditional(int permutation)
|
||||
{
|
||||
return $"#if defined(KEYWORD_PERMUTATION_{permutation})";
|
||||
}
|
||||
|
||||
public static void GetKeywordPermutationDeclarations(ShaderStringBuilder sb, List<List<KeyValuePair<ShaderKeyword, int>>> permutations)
|
||||
{
|
||||
if (permutations.Count == 0)
|
||||
return;
|
||||
|
||||
for (int p = 0; p < permutations.Count; p++)
|
||||
{
|
||||
// ShaderStringBuilder.Append doesnt apply indentation
|
||||
sb.TryAppendIndentation();
|
||||
|
||||
// Append correct if
|
||||
bool isLast = false;
|
||||
if (p == 0)
|
||||
{
|
||||
sb.Append("#if ");
|
||||
}
|
||||
else if (p == permutations.Count - 1)
|
||||
{
|
||||
sb.Append("#else");
|
||||
isLast = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("#elif ");
|
||||
}
|
||||
|
||||
// Last permutation is always #else
|
||||
if (!isLast)
|
||||
{
|
||||
// Track whether && is required
|
||||
bool appendAnd = false;
|
||||
|
||||
// Iterate all keywords that are part of the permutation
|
||||
for (int i = 0; i < permutations[p].Count; i++)
|
||||
{
|
||||
// When previous keyword was inserted subsequent requires &&
|
||||
string and = appendAnd ? " && " : string.Empty;
|
||||
|
||||
switch (permutations[p][i].Key.keywordType)
|
||||
{
|
||||
case KeywordType.Enum:
|
||||
{
|
||||
sb.Append($"{and}defined({permutations[p][i].Key.referenceName}_{permutations[p][i].Key.entries[permutations[p][i].Value].referenceName})");
|
||||
appendAnd = true;
|
||||
break;
|
||||
}
|
||||
case KeywordType.Boolean:
|
||||
{
|
||||
// HLSL does not support a !value predicate
|
||||
if (permutations[p][i].Value != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sb.Append($"{and}defined({permutations[p][i].Key.referenceName})");
|
||||
appendAnd = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.AppendNewLine();
|
||||
|
||||
// Define the matching permutation keyword
|
||||
sb.IncreaseIndent();
|
||||
sb.AppendLine($"#define KEYWORD_PERMUTATION_{p}");
|
||||
sb.DecreaseIndent();
|
||||
}
|
||||
|
||||
// End statement
|
||||
sb.AppendLine("#endif");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 19fef5ded8573c34a80cf81ed0f9c56a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Graphing
|
||||
{
|
||||
class ConsoleLogHandler : ILogHandler
|
||||
{
|
||||
public void LogFormat(LogType logType, UnityEngine.Object context, string format, params object[] args)
|
||||
{
|
||||
var formatted = string.Format(format, args);
|
||||
Console.WriteLine("{0}:{1} - {2}", logType, context, formatted);
|
||||
}
|
||||
|
||||
public void LogException(Exception exception, UnityEngine.Object context)
|
||||
{
|
||||
Console.WriteLine("{0} - {1}", context, exception);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ffca76f71e6326344ad2ff5e823d02f9
|
||||
timeCreated: 1464264926
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
class PooledHashSet<T> : HashSet<T>, IDisposable
|
||||
{
|
||||
static Stack<PooledHashSet<T>> s_Pool = new Stack<PooledHashSet<T>>();
|
||||
bool m_Active;
|
||||
|
||||
PooledHashSet() { }
|
||||
|
||||
public static PooledHashSet<T> Get()
|
||||
{
|
||||
if (s_Pool.Count == 0)
|
||||
{
|
||||
return new PooledHashSet<T> { m_Active = true };
|
||||
}
|
||||
|
||||
var list = s_Pool.Pop();
|
||||
list.m_Active = true;
|
||||
#if DEBUG
|
||||
GC.ReRegisterForFinalize(list);
|
||||
#endif
|
||||
return list;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Assert.IsTrue(m_Active);
|
||||
m_Active = false;
|
||||
Clear();
|
||||
s_Pool.Push(this);
|
||||
#if DEBUG
|
||||
GC.SuppressFinalize(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Destructor causes some GC alloc so only do this sanity check in debug build
|
||||
#if DEBUG
|
||||
~PooledHashSet()
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(PooledHashSet<T>)} must be disposed manually.");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 11c00f8215374c368941cd4c06242ed7
|
||||
timeCreated: 1582812009
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
class PooledList<T> : List<T>, IDisposable
|
||||
{
|
||||
static Stack<PooledList<T>> s_Pool = new Stack<PooledList<T>>();
|
||||
bool m_Active;
|
||||
|
||||
PooledList() { }
|
||||
|
||||
public static PooledList<T> Get()
|
||||
{
|
||||
if (s_Pool.Count == 0)
|
||||
{
|
||||
return new PooledList<T> { m_Active = true };
|
||||
}
|
||||
|
||||
var list = s_Pool.Pop();
|
||||
list.m_Active = true;
|
||||
#if DEBUG
|
||||
GC.ReRegisterForFinalize(list);
|
||||
#endif
|
||||
return list;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Assert.IsTrue(m_Active);
|
||||
m_Active = false;
|
||||
Clear();
|
||||
s_Pool.Push(this);
|
||||
#if DEBUG
|
||||
GC.SuppressFinalize(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Destructor causes some GC alloc so only do this sanity check in debug build
|
||||
#if DEBUG
|
||||
~PooledList()
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(PooledList<T>)} must be disposed manually.");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9f3065ccf1f64e219d8039d355a788a1
|
||||
timeCreated: 1579171175
|
|
@ -0,0 +1,85 @@
|
|||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
internal static class PrecisionUtil
|
||||
{
|
||||
internal const string Token = "$precision";
|
||||
|
||||
internal static string ToShaderString(this ConcretePrecision precision)
|
||||
{
|
||||
switch (precision)
|
||||
{
|
||||
case ConcretePrecision.Single:
|
||||
return "float";
|
||||
case ConcretePrecision.Half:
|
||||
return "half";
|
||||
default:
|
||||
return "float";
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ToGenericString(this GraphPrecision precision)
|
||||
{
|
||||
switch (precision)
|
||||
{
|
||||
case GraphPrecision.Single:
|
||||
return "float";
|
||||
case GraphPrecision.Half:
|
||||
return "half";
|
||||
default:
|
||||
return Token;
|
||||
}
|
||||
}
|
||||
|
||||
internal static ConcretePrecision ToConcrete(this Precision precision, ConcretePrecision InheritPrecision, ConcretePrecision GraphPrecision)
|
||||
{
|
||||
switch (precision)
|
||||
{
|
||||
case Precision.Single:
|
||||
return ConcretePrecision.Single;
|
||||
case Precision.Half:
|
||||
return ConcretePrecision.Half;
|
||||
case Precision.Inherit:
|
||||
return InheritPrecision;
|
||||
default:
|
||||
return GraphPrecision;
|
||||
}
|
||||
}
|
||||
|
||||
internal static GraphPrecision ToGraphPrecision(this Precision precision, GraphPrecision inheritPrecision)
|
||||
{
|
||||
switch (precision)
|
||||
{
|
||||
case Precision.Single:
|
||||
return GraphPrecision.Single;
|
||||
case Precision.Half:
|
||||
return GraphPrecision.Half;
|
||||
case Precision.Graph:
|
||||
return GraphPrecision.Graph;
|
||||
default:
|
||||
return inheritPrecision;
|
||||
}
|
||||
}
|
||||
|
||||
internal static ConcretePrecision ToConcrete(this GraphPrecision precision, ConcretePrecision graphPrecision)
|
||||
{
|
||||
switch (precision)
|
||||
{
|
||||
case GraphPrecision.Single:
|
||||
return ConcretePrecision.Single;
|
||||
case GraphPrecision.Half:
|
||||
return ConcretePrecision.Half;
|
||||
default:
|
||||
return graphPrecision;
|
||||
}
|
||||
}
|
||||
|
||||
internal static GraphPrecision GraphFallback(this GraphPrecision precision, GraphPrecision graphFallback)
|
||||
{
|
||||
if (precision == GraphPrecision.Graph)
|
||||
return graphFallback;
|
||||
return precision;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 501418e118466ec499de0e77616e5e00
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
static class PropertyUtil
|
||||
{
|
||||
public static ConcreteSlotValueType ToConcreteShaderValueType(this PropertyType propertyType)
|
||||
{
|
||||
switch (propertyType)
|
||||
{
|
||||
case PropertyType.SamplerState:
|
||||
return ConcreteSlotValueType.SamplerState;
|
||||
case PropertyType.Matrix4:
|
||||
return ConcreteSlotValueType.Matrix4;
|
||||
case PropertyType.Matrix3:
|
||||
return ConcreteSlotValueType.Matrix3;
|
||||
case PropertyType.Matrix2:
|
||||
return ConcreteSlotValueType.Matrix2;
|
||||
case PropertyType.Texture2D:
|
||||
return ConcreteSlotValueType.Texture2D;
|
||||
case PropertyType.Texture2DArray:
|
||||
return ConcreteSlotValueType.Texture2DArray;
|
||||
case PropertyType.Texture3D:
|
||||
return ConcreteSlotValueType.Texture3D;
|
||||
case PropertyType.Cubemap:
|
||||
return ConcreteSlotValueType.Cubemap;
|
||||
case PropertyType.Gradient:
|
||||
return ConcreteSlotValueType.Gradient;
|
||||
case PropertyType.Vector4:
|
||||
return ConcreteSlotValueType.Vector4;
|
||||
case PropertyType.Vector3:
|
||||
return ConcreteSlotValueType.Vector3;
|
||||
case PropertyType.Vector2:
|
||||
return ConcreteSlotValueType.Vector2;
|
||||
case PropertyType.Float:
|
||||
return ConcreteSlotValueType.Vector1;
|
||||
case PropertyType.Boolean:
|
||||
return ConcreteSlotValueType.Boolean;
|
||||
case PropertyType.Color:
|
||||
return ConcreteSlotValueType.Vector4;
|
||||
case PropertyType.VirtualTexture:
|
||||
return ConcreteSlotValueType.VirtualTexture;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e284d5ec141b1b24a8509176d21b1d3f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,28 @@
|
|||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum ScreenSpaceType
|
||||
{
|
||||
Default,
|
||||
Raw,
|
||||
Center,
|
||||
Tiled
|
||||
};
|
||||
|
||||
static class ScreenSpaceTypeExtensions
|
||||
{
|
||||
public static string ToValueAsVariable(this ScreenSpaceType screenSpaceType)
|
||||
{
|
||||
switch (screenSpaceType)
|
||||
{
|
||||
case ScreenSpaceType.Raw:
|
||||
return string.Format("IN.{0}", ShaderGeneratorNames.ScreenPosition);
|
||||
case ScreenSpaceType.Center:
|
||||
return string.Format("$precision4(IN.{0}.xy / IN.{0}.w * 2 - 1, 0, 0)", ShaderGeneratorNames.ScreenPosition);
|
||||
case ScreenSpaceType.Tiled:
|
||||
return string.Format("frac($precision4((IN.{0}.x / IN.{0}.w * 2 - 1) * _ScreenParams.x / _ScreenParams.y, IN.{0}.y / IN.{0}.w * 2 - 1, 0, 0))", ShaderGeneratorNames.ScreenPosition);
|
||||
default:
|
||||
return string.Format("$precision4(IN.{0}.xy / IN.{0}.w, 0, 0)", ShaderGeneratorNames.ScreenPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d296e8d1103ed5c49a267d57be0f4d96
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,195 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using UnityEditor.ShaderGraph.Serialization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Graphing
|
||||
{
|
||||
static class SerializationHelper
|
||||
{
|
||||
[Serializable]
|
||||
public struct TypeSerializationInfo
|
||||
{
|
||||
[SerializeField]
|
||||
public string fullName;
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
return !string.IsNullOrEmpty(fullName);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct JSONSerializedElement
|
||||
{
|
||||
[SerializeField]
|
||||
public TypeSerializationInfo typeInfo;
|
||||
|
||||
[SerializeField]
|
||||
public string JSONnodeData;
|
||||
}
|
||||
|
||||
public static JSONSerializedElement nullElement
|
||||
{
|
||||
get
|
||||
{
|
||||
return new JSONSerializedElement();
|
||||
}
|
||||
}
|
||||
|
||||
public static TypeSerializationInfo GetTypeSerializableAsString(Type type)
|
||||
{
|
||||
return new TypeSerializationInfo
|
||||
{
|
||||
fullName = type.FullName
|
||||
};
|
||||
}
|
||||
|
||||
static Type GetTypeFromSerializedString(TypeSerializationInfo typeInfo)
|
||||
{
|
||||
if (!typeInfo.IsValid())
|
||||
return null;
|
||||
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var type = assembly.GetType(typeInfo.fullName);
|
||||
if (type != null)
|
||||
return type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static JSONSerializedElement Serialize<T>(T item)
|
||||
{
|
||||
if (item is JsonObject jsonObject)
|
||||
return new JSONSerializedElement() { JSONnodeData = jsonObject.Serialize() };
|
||||
|
||||
if (item == null)
|
||||
throw new ArgumentNullException("item", "Can not serialize null element");
|
||||
|
||||
//check if unknownnode type - if so, return saved metadata
|
||||
//unknown node type will need onbeforeserialize to set guid and edges and all the things
|
||||
var typeInfo = GetTypeSerializableAsString(item.GetType());
|
||||
var data = JsonUtility.ToJson(item, true);
|
||||
|
||||
if (string.IsNullOrEmpty(data))
|
||||
throw new ArgumentException(string.Format("Can not serialize {0}", item));
|
||||
|
||||
|
||||
return new JSONSerializedElement
|
||||
{
|
||||
typeInfo = typeInfo,
|
||||
JSONnodeData = data
|
||||
};
|
||||
}
|
||||
|
||||
static TypeSerializationInfo DoTypeRemap(TypeSerializationInfo info, Dictionary<TypeSerializationInfo, TypeSerializationInfo> remapper)
|
||||
{
|
||||
TypeSerializationInfo foundInfo;
|
||||
if (remapper.TryGetValue(info, out foundInfo))
|
||||
return foundInfo;
|
||||
return info;
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(JSONSerializedElement item, Dictionary<TypeSerializationInfo, TypeSerializationInfo> remapper, params object[] constructorArgs) where T : class
|
||||
{
|
||||
T instance;
|
||||
if (typeof(T) == typeof(JsonObject) || typeof(T).IsSubclassOf(typeof(JsonObject)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
instance = Activator.CreateInstance(typeof(T), flags, null, constructorArgs, culture) as T;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception(string.Format("Could not construct instance of: {0}", typeof(T)), e);
|
||||
}
|
||||
|
||||
MultiJson.Deserialize(instance as JsonObject, item.JSONnodeData);
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (!item.typeInfo.IsValid() || string.IsNullOrEmpty(item.JSONnodeData))
|
||||
throw new ArgumentException(string.Format("Can not deserialize {0}, it is invalid", item));
|
||||
|
||||
TypeSerializationInfo info = item.typeInfo;
|
||||
info.fullName = info.fullName.Replace("UnityEngine.MaterialGraph", "UnityEditor.ShaderGraph");
|
||||
info.fullName = info.fullName.Replace("UnityEngine.Graphing", "UnityEditor.Graphing");
|
||||
if (remapper != null)
|
||||
info = DoTypeRemap(info, remapper);
|
||||
|
||||
var type = GetTypeFromSerializedString(info);
|
||||
//if type is null but T is an abstract material node, instead we create an unknowntype node
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentException(string.Format("Can not deserialize ({0}), type is invalid", info.fullName));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
instance = Activator.CreateInstance(type, flags, null, constructorArgs, culture) as T;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception(string.Format("Could not construct instance of: {0}", type), e);
|
||||
}
|
||||
|
||||
if (instance != null)
|
||||
{
|
||||
JsonUtility.FromJsonOverwrite(item.JSONnodeData, instance);
|
||||
return instance;
|
||||
}
|
||||
Debug.Log("UhOh");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<JSONSerializedElement> Serialize<T>(IEnumerable<T> list)
|
||||
{
|
||||
var result = new List<JSONSerializedElement>();
|
||||
if (list == null)
|
||||
return result;
|
||||
|
||||
foreach (var element in list)
|
||||
{
|
||||
try
|
||||
{
|
||||
result.Add(Serialize(element));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<T> Deserialize<T>(IEnumerable<JSONSerializedElement> list, Dictionary<TypeSerializationInfo, TypeSerializationInfo> remapper, params object[] constructorArgs) where T : class
|
||||
{
|
||||
var result = new List<T>();
|
||||
if (list == null)
|
||||
return result;
|
||||
|
||||
foreach (var element in list)
|
||||
{
|
||||
try
|
||||
{
|
||||
result.Add(Deserialize<T>(element, remapper));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
Debug.LogError(element.JSONnodeData);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f6657676e9fd9cd4bbcb26b0771df3ac
|
||||
timeCreated: 1464079585
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,132 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.ShaderGraph;
|
||||
|
||||
namespace UnityEditor.ShaderGraph.Internal
|
||||
{
|
||||
sealed class ShaderGraphRequirementsPerKeyword : KeywordDependentCollection<
|
||||
ShaderGraphRequirements,
|
||||
ShaderGraphRequirementsPerKeyword.All,
|
||||
ShaderGraphRequirementsPerKeyword.AllPermutations,
|
||||
ShaderGraphRequirementsPerKeyword.ForPermutationIndex,
|
||||
ShaderGraphRequirementsPerKeyword.Base,
|
||||
ShaderGraphRequirementsPerKeyword.IRequirements,
|
||||
ShaderGraphRequirementsPerKeyword.IRequirementsSet
|
||||
>
|
||||
{
|
||||
public interface IRequirements : KeywordDependentCollection.IInstance, KeywordDependentCollection.ISet<IRequirements>
|
||||
{
|
||||
void SetRequirements(ShaderGraphRequirements value);
|
||||
|
||||
ShaderGraphRequirements requirements { get; set; }
|
||||
}
|
||||
|
||||
public interface IRequirementsSet : KeywordDependentCollection.ISet<IRequirements>
|
||||
{
|
||||
}
|
||||
|
||||
public struct ForPermutationIndex : IRequirements, IRequirementsSet
|
||||
{
|
||||
private ShaderGraphRequirementsPerKeyword m_Source;
|
||||
private int m_PermutationIndex;
|
||||
|
||||
public KeywordDependentCollection.KeywordPermutationInstanceType type => KeywordDependentCollection.KeywordPermutationInstanceType.Permutation;
|
||||
public IEnumerable<IRequirements> instances => Enumerable.Repeat<IRequirements>(this, 1);
|
||||
public int instanceCount => 1;
|
||||
public int permutationIndex => m_PermutationIndex;
|
||||
|
||||
public ShaderGraphRequirements requirements
|
||||
{
|
||||
get => m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex);
|
||||
set => m_Source.SetForPermutationIndex(m_PermutationIndex, value);
|
||||
}
|
||||
|
||||
public void SetRequirements(ShaderGraphRequirements value) => requirements = value;
|
||||
|
||||
internal ForPermutationIndex(ShaderGraphRequirementsPerKeyword source, int index)
|
||||
{
|
||||
m_Source = source;
|
||||
m_PermutationIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Base : IRequirements, IRequirementsSet
|
||||
{
|
||||
private ShaderGraphRequirementsPerKeyword m_Source;
|
||||
|
||||
public int instanceCount => 1;
|
||||
public int permutationIndex => -1;
|
||||
public KeywordDependentCollection.KeywordPermutationInstanceType type => KeywordDependentCollection.KeywordPermutationInstanceType.Base;
|
||||
public IEnumerable<IRequirements> instances => Enumerable.Repeat<IRequirements>(this, 1);
|
||||
|
||||
public ShaderGraphRequirements requirements
|
||||
{
|
||||
get => m_Source.baseStorage;
|
||||
set => m_Source.baseStorage = value;
|
||||
}
|
||||
|
||||
public void SetRequirements(ShaderGraphRequirements value) => requirements = value;
|
||||
|
||||
internal Base(ShaderGraphRequirementsPerKeyword source)
|
||||
{
|
||||
m_Source = source;
|
||||
}
|
||||
}
|
||||
|
||||
public struct All : IRequirementsSet
|
||||
{
|
||||
private ShaderGraphRequirementsPerKeyword m_Source;
|
||||
public int instanceCount => m_Source.permutationCount + 1;
|
||||
|
||||
internal All(ShaderGraphRequirementsPerKeyword source)
|
||||
{
|
||||
m_Source = source;
|
||||
}
|
||||
|
||||
public IEnumerable<IRequirements> instances
|
||||
{
|
||||
get
|
||||
{
|
||||
var self = this;
|
||||
return m_Source.permutationStorages
|
||||
.Select((v, i) => new ForPermutationIndex(self.m_Source, i) as IRequirements)
|
||||
.Union(Enumerable.Repeat((IRequirements)m_Source.baseInstance, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct AllPermutations : IRequirementsSet
|
||||
{
|
||||
private ShaderGraphRequirementsPerKeyword m_Source;
|
||||
public int instanceCount => m_Source.permutationCount;
|
||||
|
||||
internal AllPermutations(ShaderGraphRequirementsPerKeyword source)
|
||||
{
|
||||
m_Source = source;
|
||||
}
|
||||
|
||||
public IEnumerable<IRequirements> instances
|
||||
{
|
||||
get
|
||||
{
|
||||
var self = this;
|
||||
return m_Source.permutationStorages
|
||||
.Select((v, i) => new ForPermutationIndex(self.m_Source, i) as IRequirements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UnionWith(ShaderGraphRequirementsPerKeyword other)
|
||||
{
|
||||
baseStorage = baseStorage.Union(other.baseStorage);
|
||||
for (var i = 0; i < other.permutationCount; ++i)
|
||||
SetForPermutationIndex(i,
|
||||
GetOrCreateForPermutationIndex(i).Union(other.GetOrCreateForPermutationIndex(i)));
|
||||
}
|
||||
|
||||
protected override All CreateAllSmartPointer() => new All(this);
|
||||
protected override AllPermutations CreateAllPermutationsSmartPointer() => new AllPermutations(this);
|
||||
protected override ForPermutationIndex CreateForPermutationSmartPointer(int index) => new ForPermutationIndex(this, index);
|
||||
protected override Base CreateBaseSmartPointer() => new Base(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7d59a0bb237356a4f8f2284efb092c15
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,202 @@
|
|||
using System;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
static class SlotValueTypeUtil
|
||||
{
|
||||
public static SlotValueType ToSlotValueType(this ConcreteSlotValueType concreteValueType)
|
||||
{
|
||||
switch (concreteValueType)
|
||||
{
|
||||
case ConcreteSlotValueType.SamplerState:
|
||||
return SlotValueType.SamplerState;
|
||||
case ConcreteSlotValueType.Matrix4:
|
||||
return SlotValueType.Matrix4;
|
||||
case ConcreteSlotValueType.Matrix3:
|
||||
return SlotValueType.Matrix3;
|
||||
case ConcreteSlotValueType.Matrix2:
|
||||
return SlotValueType.Matrix2;
|
||||
case ConcreteSlotValueType.Texture2D:
|
||||
return SlotValueType.Texture2D;
|
||||
case ConcreteSlotValueType.Texture2DArray:
|
||||
return SlotValueType.Texture2DArray;
|
||||
case ConcreteSlotValueType.Texture3D:
|
||||
return SlotValueType.Texture3D;
|
||||
case ConcreteSlotValueType.Cubemap:
|
||||
return SlotValueType.Cubemap;
|
||||
case ConcreteSlotValueType.Gradient:
|
||||
return SlotValueType.Gradient;
|
||||
case ConcreteSlotValueType.Vector4:
|
||||
return SlotValueType.Vector4;
|
||||
case ConcreteSlotValueType.Vector3:
|
||||
return SlotValueType.Vector3;
|
||||
case ConcreteSlotValueType.Vector2:
|
||||
return SlotValueType.Vector2;
|
||||
case ConcreteSlotValueType.Vector1:
|
||||
return SlotValueType.Vector1;
|
||||
case ConcreteSlotValueType.Boolean:
|
||||
return SlotValueType.Boolean;
|
||||
case ConcreteSlotValueType.VirtualTexture:
|
||||
return SlotValueType.VirtualTexture;
|
||||
case ConcreteSlotValueType.PropertyConnectionState:
|
||||
return SlotValueType.PropertyConnectionState;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static ConcreteSlotValueType ToConcreteSlotValueType(this SlotValueType slotValueType)
|
||||
{
|
||||
switch (slotValueType)
|
||||
{
|
||||
case SlotValueType.SamplerState:
|
||||
return ConcreteSlotValueType.SamplerState;
|
||||
case SlotValueType.Matrix2:
|
||||
return ConcreteSlotValueType.Matrix2;
|
||||
case SlotValueType.Matrix3:
|
||||
return ConcreteSlotValueType.Matrix3;
|
||||
case SlotValueType.Matrix4:
|
||||
return ConcreteSlotValueType.Matrix4;
|
||||
case SlotValueType.Texture2D:
|
||||
return ConcreteSlotValueType.Texture2D;
|
||||
case SlotValueType.Texture2DArray:
|
||||
return ConcreteSlotValueType.Texture2DArray;
|
||||
case SlotValueType.Texture3D:
|
||||
return ConcreteSlotValueType.Texture3D;
|
||||
case SlotValueType.Cubemap:
|
||||
return ConcreteSlotValueType.Cubemap;
|
||||
case SlotValueType.Gradient:
|
||||
return ConcreteSlotValueType.Gradient;
|
||||
case SlotValueType.Vector4:
|
||||
return ConcreteSlotValueType.Vector4;
|
||||
case SlotValueType.Vector3:
|
||||
return ConcreteSlotValueType.Vector3;
|
||||
case SlotValueType.Vector2:
|
||||
return ConcreteSlotValueType.Vector2;
|
||||
case SlotValueType.Vector1:
|
||||
return ConcreteSlotValueType.Vector1;
|
||||
case SlotValueType.Boolean:
|
||||
return ConcreteSlotValueType.Boolean;
|
||||
case SlotValueType.VirtualTexture:
|
||||
return ConcreteSlotValueType.VirtualTexture;
|
||||
case SlotValueType.PropertyConnectionState:
|
||||
return ConcreteSlotValueType.PropertyConnectionState;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static PropertyType ToPropertyType(this ConcreteSlotValueType concreteValueType)
|
||||
{
|
||||
switch (concreteValueType)
|
||||
{
|
||||
case ConcreteSlotValueType.SamplerState:
|
||||
return PropertyType.SamplerState;
|
||||
case ConcreteSlotValueType.Matrix4:
|
||||
return PropertyType.Matrix4;
|
||||
case ConcreteSlotValueType.Matrix3:
|
||||
return PropertyType.Matrix3;
|
||||
case ConcreteSlotValueType.Matrix2:
|
||||
return PropertyType.Matrix2;
|
||||
case ConcreteSlotValueType.Texture2D:
|
||||
return PropertyType.Texture2D;
|
||||
case ConcreteSlotValueType.Texture2DArray:
|
||||
return PropertyType.Texture2DArray;
|
||||
case ConcreteSlotValueType.Texture3D:
|
||||
return PropertyType.Texture3D;
|
||||
case ConcreteSlotValueType.Cubemap:
|
||||
return PropertyType.Cubemap;
|
||||
case ConcreteSlotValueType.Gradient:
|
||||
return PropertyType.Gradient;
|
||||
case ConcreteSlotValueType.Vector4:
|
||||
return PropertyType.Vector4;
|
||||
case ConcreteSlotValueType.Vector3:
|
||||
return PropertyType.Vector3;
|
||||
case ConcreteSlotValueType.Vector2:
|
||||
return PropertyType.Vector2;
|
||||
case ConcreteSlotValueType.Vector1:
|
||||
return PropertyType.Float;
|
||||
case ConcreteSlotValueType.Boolean:
|
||||
return PropertyType.Boolean;
|
||||
case ConcreteSlotValueType.VirtualTexture:
|
||||
return PropertyType.VirtualTexture;
|
||||
case ConcreteSlotValueType.PropertyConnectionState:
|
||||
return PropertyType.PropertyConnectionState;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToShaderString(this ConcreteSlotValueType type, ConcretePrecision concretePrecision)
|
||||
{
|
||||
string precisionString = concretePrecision.ToShaderString();
|
||||
return type.ToShaderString(precisionString);
|
||||
}
|
||||
|
||||
public static string ToShaderString(this ConcreteSlotValueType type, string precisionToken = PrecisionUtil.Token)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ConcreteSlotValueType.SamplerState:
|
||||
return "UnitySamplerState";
|
||||
case ConcreteSlotValueType.Matrix4:
|
||||
return precisionToken + "4x4";
|
||||
case ConcreteSlotValueType.Matrix3:
|
||||
return precisionToken + "3x3";
|
||||
case ConcreteSlotValueType.Matrix2:
|
||||
return precisionToken + "2x2";
|
||||
case ConcreteSlotValueType.Texture2D:
|
||||
return "UnityTexture2D";
|
||||
case ConcreteSlotValueType.Texture2DArray:
|
||||
return "UnityTexture2DArray";
|
||||
case ConcreteSlotValueType.Texture3D:
|
||||
return "UnityTexture3D";
|
||||
case ConcreteSlotValueType.Cubemap:
|
||||
return "UnityTextureCube";
|
||||
case ConcreteSlotValueType.Gradient:
|
||||
return "Gradient";
|
||||
case ConcreteSlotValueType.Vector4:
|
||||
return precisionToken + "4";
|
||||
case ConcreteSlotValueType.Vector3:
|
||||
return precisionToken + "3";
|
||||
case ConcreteSlotValueType.Vector2:
|
||||
return precisionToken + "2";
|
||||
case ConcreteSlotValueType.Vector1:
|
||||
return precisionToken;
|
||||
case ConcreteSlotValueType.Boolean:
|
||||
return precisionToken;
|
||||
case ConcreteSlotValueType.PropertyConnectionState:
|
||||
return "bool";
|
||||
default:
|
||||
return "Error";
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToClassName(this ConcreteSlotValueType type)
|
||||
{
|
||||
return k_ConcreteSlotValueTypeClassNames[(int)type];
|
||||
}
|
||||
|
||||
static readonly string[] k_ConcreteSlotValueTypeClassNames =
|
||||
{
|
||||
null,
|
||||
"typeMatrix",
|
||||
"typeMatrix",
|
||||
"typeMatrix",
|
||||
"typeTexture2D",
|
||||
"typeTexture2DArray",
|
||||
"typeTexture3D",
|
||||
"typeCubemap",
|
||||
"typeGradient",
|
||||
"typeFloat4",
|
||||
"typeFloat3",
|
||||
"typeFloat2",
|
||||
"typeFloat1",
|
||||
"typeBoolean",
|
||||
"typeVirtualTexture",
|
||||
"typePropertyConnectionState"
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e28cefa3fa391ed48a67c0b476a0a95c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace UnityEditor.Graphing
|
||||
{
|
||||
static class StackPool<T>
|
||||
{
|
||||
// Object pool to avoid allocations.
|
||||
static readonly ObjectPool<Stack<T>> k_StackPool = new ObjectPool<Stack<T>>(() => new Stack<T>(), null, l => l.Clear());
|
||||
|
||||
public static Stack<T> Get()
|
||||
{
|
||||
return k_StackPool.Get();
|
||||
}
|
||||
|
||||
public static void Release(Stack<T> toRelease)
|
||||
{
|
||||
k_StackPool.Release(toRelease);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 93c41a4331c94d09a7561ea6b4983439
|
||||
timeCreated: 1505275069
|
|
@ -0,0 +1,12 @@
|
|||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
public static class TextUtil
|
||||
{
|
||||
public static string PascalToLabel(this string pascalString)
|
||||
{
|
||||
return Regex.Replace(pascalString, "(\\B[A-Z])", " $1");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c5dad4902719d054ba79ba0b3108591a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace UnityEditor.ShaderGraph.Internal
|
||||
{
|
||||
public enum UVChannel
|
||||
{
|
||||
UV0 = 0,
|
||||
UV1 = 1,
|
||||
UV2 = 2,
|
||||
UV3 = 3,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d77363d2f0df1f544b21d9e8a05f01a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue