private IEnumerable <ShaderViewModel> BuildShaderTree() { var files = Paths.Where(p => !string.IsNullOrWhiteSpace(p) && Directory.Exists(p)) .SelectMany(path => Directory.GetFiles(path, "*.sdsl", SearchOption.AllDirectories)); shaders.Clear(); var duplicates = new Dictionary <string, ShaderViewModel>(); foreach (var file in files) { var name = Path.GetFileNameWithoutExtension(file); if (!shaders.ContainsKey(name)) { shaders[name] = new ShaderViewModel { Path = file, Name = name } } ; else { duplicates[name] = new ShaderViewModel { Path = file, Name = name } }; } foreach (var shader in shaders.Values) { if (EffectUtils.TryParseEffect(shader.Name, shaders, out var parsedShader)) { var baseShaderNames = parsedShader.BaseShaders.Select(s => s.ShaderClass.Name.Text).ToList(); shader.ParsedShader = parsedShader; // get all declrarations in this shader foreach (var m in parsedShader.ShaderClass.Members.OfType <IDeclaration>() ?? Enumerable.Empty <IDeclaration>()) { var mn = m.Name.Text; if (string.IsNullOrWhiteSpace(mn)) { continue; } if (!members.TryGetValue(mn, out var memberCandidates)) { memberCandidates = new Dictionary <ShaderViewModel, MemberList>(); } if (!memberCandidates.TryGetValue(shader, out var mems)) { mems = new MemberList(); } mems.Add(new MemberViewModel(mn, m)); memberCandidates[shader] = mems; members[mn] = memberCandidates; } if (baseShaderNames.Count > 0) { var baseShaders = baseShaderNames .Select(s => shaders.TryGetValue(s, out var b) ? b : null) .Where(s => s != null); foreach (var baseShader in baseShaders) { shader.BaseShaders.Add(baseShader); baseShader.DerivedShaders.Add(shader); if (_directParentsOnly) { if (parsedShader.ShaderClass.BaseClasses.FirstOrDefault(bc => bc.Name.Text == baseShader.Name) != null) { baseShader.TreeViewChildren.Add(shader); } } else { baseShader.TreeViewChildren.Add(shader); } } } else { yield return(shader); } } } Debug.WriteLine($"Found {shaders.Count} shaders"); } }