/// <summary>
        /// Internal ctor that allows for overriding the default continue strategy.
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="continueStrategy"></param>
        internal SelectorTreeNode(IEnumerable <TreeNode <TContextType> > nodes, ICompositeContinuationStrategy continueStrategy)
            : base(nodes)
        {
            if (continueStrategy == null)
            {
                throw new ArgumentNullException(nameof(continueStrategy));
            }

            EvaluationEnumerator = new EvaluationEnumeratorMediator <TContextType>(CompositionNodes.GetEnumerator(), continueStrategy);
        }
        /// <summary>
        /// Load the shader and extract the information.
        /// </summary>
        public void PrepareNode(ConcurrentDictionary <string, string> projectShaders)
        {
            if (!MixinReference.HasLocation())
            {
                return;
            }

            var newGenerics         = new GenericDictionary();
            var newCompositionNodes = new Dictionary <string, IMaterialNode>();
            var newMembers          = new Dictionary <ParameterKey, object>();

            var             localMixinName = Path.GetFileNameWithoutExtension(MixinReference.Location);
            ShaderClassType shader;

            string source;

            if (projectShaders.TryGetValue(localMixinName, out source))
            {
                shader = MaterialNodeClassLoader.GetLoader().ParseShader(source);
            }
            else
            {
                shader = MaterialNodeClassLoader.GetLoader().GetShader(localMixinName);
            }

            if (shader == null)
            {
                return;
            }

            var acceptLinkedVariable = true;

            foreach (var generic in shader.ShaderGenerics)
            {
                if (generic.Type.Name.Text == "float4")
                {
                    AddKey <Vector4>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "float3")
                {
                    AddKey <Vector3>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "float2")
                {
                    AddKey <Vector2>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "float")
                {
                    AddKey <float>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "int")
                {
                    AddKey <int>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "Texture2D")
                {
                    AddKey <Texture2D>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "SamplerState")
                {
                    AddKey <SamplerState>(generic.Name.Text, newGenerics);
                }
                else
                {
                    AddKey <string>(generic.Name.Text, newGenerics);
                }

                if (generic.Type is LinkType)
                {
                    acceptLinkedVariable = false; // since the behavior is unpredictable, safely prevent addition of linked variable (= with Link annotation)
                }
            }

            foreach (var member in shader.Members.OfType <Variable>())
            {
                // TODO: enough detect compositions?
                if (member.Type is TypeName && (member.Type.TypeInference == null || member.Type.TypeInference.TargetType == null))
                {
                    // ComputeColor only
                    if (member.Type.Name.Text == "ComputeColor")
                    {
                        if (CompositionNodes.ContainsKey(member.Name.Text))
                        {
                            newCompositionNodes.Add(member.Name.Text, CompositionNodes[member.Name.Text]);
                        }
                        else
                        {
                            newCompositionNodes.Add(member.Name.Text, null);
                        }
                    }
                }
                else
                {
                    var    isColor  = false;
                    string linkName = null;
                    var    isStage  = member.Qualifiers.Contains(ParadoxStorageQualifier.Stage);
                    var    isStream = member.Qualifiers.Contains(ParadoxStorageQualifier.Stream);
                    foreach (var annotation in member.Attributes.OfType <SiliconStudio.Shaders.Ast.Hlsl.AttributeDeclaration>())
                    {
                        if (annotation.Name == "Color")
                        {
                            isColor = true;
                        }
                        if (acceptLinkedVariable && annotation.Name == "Link" && annotation.Parameters.Count > 0)
                        {
                            linkName = (string)annotation.Parameters[0].Value;
                        }
                    }

                    if (!isStream && (isStage || !string.IsNullOrEmpty(linkName)))
                    {
                        if (linkName == null)
                        {
                            linkName = localMixinName + "." + member.Name.Text;
                        }

                        var memberType = member.Type.ResolveType();
                        if (isColor)
                        {
                            AddMember <Color4>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.Float || memberType == ScalarType.Half)
                        {
                            AddMember <float>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.Double)
                        {
                            AddMember <double>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.Int)
                        {
                            AddMember <int>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.UInt)
                        {
                            AddMember <uint>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.Bool)
                        {
                            AddMember <bool>(linkName, newMembers);
                        }
                        else if (memberType is VectorType)
                        {
                            switch (((VectorType)memberType).Dimension)
                            {
                            case 2:
                                AddMember <Vector2>(linkName, newMembers);
                                break;

                            case 3:
                                AddMember <Vector3>(linkName, newMembers);
                                break;

                            case 4:
                                AddMember <Vector4>(linkName, newMembers);
                                break;
                            }
                        }
                        else if (member.Type.Name.Text == "Texture2D")
                        {
                            AddMember <Graphics.Texture>(linkName, newMembers);
                        }
                        else if (member.Type.Name.Text == "SamplerState")
                        {
                            AddMember <Graphics.SamplerState>(linkName, newMembers);
                        }
                    }
                }
            }

            Generics         = newGenerics;
            CompositionNodes = newCompositionNodes;
            Members          = newMembers;
        }
 /// <inheritdoc />
 public override IEnumerator <TreeNode <TContextType> > GetEnumerator()
 {
     return(CompositionNodes.GetEnumerator());
 }