using System; using System.Collections.Generic; using System.Linq; using UnityEditor.ShaderGraph; using UnityEditor.ShaderGraph.Internal; namespace UnityEditor.ShaderGraph.Internal { internal interface IActiveFields : KeywordDependentCollection.IInstance, KeywordDependentCollection.ISet { IEnumerable fields { get; } bool Add(FieldDescriptor field); bool Contains(FieldDescriptor field); bool Contains(string value); } internal interface IActiveFieldsSet : KeywordDependentCollection.ISet { void AddAll(FieldDescriptor field); } internal class FieldNamePairStorage { private HashSet m_fieldDescriptors; private HashSet m_fieldNames; public IEnumerable fields => m_fieldDescriptors; public FieldNamePairStorage() { m_fieldDescriptors = new HashSet(); m_fieldNames = new HashSet(StringComparer.Ordinal); } public IEnumerable Union(FieldNamePairStorage other) { var output = new HashSet(m_fieldDescriptors); output.UnionWith(other.m_fieldDescriptors); return output; } public bool Contains(FieldDescriptor fieldDescriptor) { return m_fieldDescriptors.Contains(fieldDescriptor); } public bool Contains(string fieldName) { return m_fieldNames.Contains(fieldName); } public bool Add(FieldDescriptor fieldDescriptor) { bool added = m_fieldDescriptors.Add(fieldDescriptor); if (added) { m_fieldNames.Add(fieldDescriptor.ToFieldString()); } return added; } } internal sealed class ActiveFields : KeywordDependentCollection< FieldNamePairStorage, ActiveFields.All, ActiveFields.AllPermutations, ActiveFields.ForPermutationIndex, ActiveFields.Base, IActiveFields, IActiveFieldsSet > { public struct ForPermutationIndex : IActiveFields, IActiveFieldsSet { private ActiveFields m_Source; private int m_PermutationIndex; public KeywordDependentCollection.KeywordPermutationInstanceType type => KeywordDependentCollection.KeywordPermutationInstanceType.Permutation; public IEnumerable instances => Enumerable.Repeat(this, 1); public IEnumerable fields => m_Source.baseStorage.Union(m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex)); public int instanceCount => 1; public int permutationIndex => m_PermutationIndex; internal ForPermutationIndex(ActiveFields source, int index) { m_Source = source; m_PermutationIndex = index; } public bool Add(FieldDescriptor field) => m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex).Add(field); public bool Contains(FieldDescriptor field) => m_Source.baseStorage.Contains(field) || m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex).Contains(field); public bool Contains(string value) => m_Source.baseStorage.Contains(value) || m_Source.GetOrCreateForPermutationIndex(m_PermutationIndex).Contains(value); public void AddAll(FieldDescriptor field) => Add(field); } public struct Base : IActiveFields, IActiveFieldsSet { private ActiveFields m_Source; public IEnumerable fields => m_Source.baseStorage.fields; public int instanceCount => 1; public int permutationIndex => -1; public KeywordDependentCollection.KeywordPermutationInstanceType type => KeywordDependentCollection.KeywordPermutationInstanceType.Base; public IEnumerable instances => Enumerable.Repeat(this, 1); internal Base(ActiveFields source) { m_Source = source; } public bool Add(FieldDescriptor field) => m_Source.baseStorage.Add(field); public bool Contains(FieldDescriptor field) => m_Source.baseStorage.Contains(field); public bool Contains(string value) => m_Source.baseStorage.Contains(value); public void AddAll(FieldDescriptor field) => Add(field); } public struct All : IActiveFieldsSet { private ActiveFields m_Source; public int instanceCount => m_Source.permutationCount + 1; internal All(ActiveFields source) { m_Source = source; } public void AddAll(FieldDescriptor field) { m_Source.baseInstance.Add(field); for (var i = 0; i < m_Source.permutationCount; ++i) m_Source.GetOrCreateForPermutationIndex(i).Add(field); } public IEnumerable instances { get { var self = this; return m_Source.permutationStorages .Select((v, i) => new ForPermutationIndex(self.m_Source, i) as IActiveFields) .Union(Enumerable.Repeat((IActiveFields)m_Source.baseInstance, 1)); } } } public struct AllPermutations : IActiveFieldsSet { private ActiveFields m_Source; public int instanceCount => m_Source.permutationCount; internal AllPermutations(ActiveFields source) { m_Source = source; } public void AddAll(FieldDescriptor field) { for (var i = 0; i < m_Source.permutationCount; ++i) m_Source.GetOrCreateForPermutationIndex(i).Add(field); } public IEnumerable instances { get { var self = this; return m_Source.permutationStorages .Select((v, i) => new ForPermutationIndex(self.m_Source, i) as IActiveFields); } } } public struct NoPermutation : IActiveFields, IActiveFieldsSet { private ActiveFields m_Source; public IEnumerable fields => m_Source.baseStorage.fields; public int instanceCount => 1; public int permutationIndex => -1; public KeywordDependentCollection.KeywordPermutationInstanceType type => KeywordDependentCollection.KeywordPermutationInstanceType.Base; internal NoPermutation(ActiveFields source) { m_Source = source; } public bool Add(FieldDescriptor field) => m_Source.baseInstance.Add(field); public bool Contains(FieldDescriptor field) => m_Source.baseStorage.Contains(field); public bool Contains(string value) => m_Source.baseStorage.Contains(value); public void AddAll(FieldDescriptor field) => Add(field); public IEnumerable instances => Enumerable.Repeat(this, 1); } 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); } }