/// <summary>Returns list of all layer groups in correct z-order (Takes into account the fact that some of them are merged).</summary> /// <returns>List of all layer groups in correct z-order.</returns> public List <LayerGroup> GetLayerGroups() { var visited = new HashSet <GraphNode>(); var layerGroups = new List <LayerGroup>(); var mapping = new LayersIndexMapper(); var generator = new LayersIndexMapper.IndexGenerator(); // Topological sorting. foreach (var node in nodes) { WalkGraph(node, visited, layerGroups, mapping, generator); } layerGroups = mapping.RemapLayerGroups(layerGroups); return(layerGroups); }
/// <summary> /// Simple depth-first search for topological sorting. /// </summary> void WalkGraph(GraphNode node, HashSet <GraphNode> visited, List <LayerGroup> layerGroups, LayersIndexMapper mapping, LayersIndexMapper.IndexGenerator generator) { if (visited.Contains(node)) { return; } visited.Add(node); // If this node is merged with another node then we mark it as visited too. if (node.MergedWithNode is not null) { visited.Add(node.MergedWithNode !); } foreach (var parent in node.Parents) { WalkGraph(parent, visited, layerGroups, mapping, generator); } if (node.MergedWithNode is not null) { foreach (var parent in ((GraphNode)node.MergedWithNode !).Parents) { WalkGraph(parent, visited, layerGroups, mapping, generator); } } if (node.MergedGroup is not null) { // Remap indexes for matte layers. if (node.Group.MatteLayer is not null) { int matteIndex = generator.GenerateIndex(); mapping.SetMapping(node.Group.MatteLayer !.Index, matteIndex); mapping.SetMapping(node.MergedWithNode !.Group.MatteLayer !.Index, matteIndex); } // Remap indexes for main layers. int index = generator.GenerateIndex(); mapping.SetMapping(node.Group.MainLayer.Index, index); mapping.SetMapping(node.MergedWithNode !.Group.MainLayer.Index, index); // Add merged layer group of current node to the result. layerGroups.Add(node.MergedGroup !); } else { // Remap indexes for matte layers. if (node.Group.MatteLayer is not null) { mapping.SetMapping(node.Group.MatteLayer !.Index, generator.GenerateIndex()); } // Remap indexes for main layers. mapping.SetMapping(node.Group.MainLayer.Index, generator.GenerateIndex()); // Add layer group of current node to the result. layerGroups.Add(node.Group); } }