TeamColorManager.cs (3321B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // The Command & Conquer Map Editor and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // The Command & Conquer Map Editor and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 using System.Collections.Generic; 16 using System.Linq; 17 using System.Xml; 18 19 namespace MobiusEditor.Utility 20 { 21 public class TeamColorManager 22 { 23 private readonly Dictionary<string, TeamColor> teamColors = new Dictionary<string, TeamColor>(); 24 25 private readonly MegafileManager megafileManager; 26 27 public TeamColor this[string key] => !string.IsNullOrEmpty(key) ? teamColors[key] : null; 28 29 public TeamColorManager(MegafileManager megafileManager) 30 { 31 this.megafileManager = megafileManager; 32 } 33 34 public void Reset() 35 { 36 teamColors.Clear(); 37 } 38 39 public void Load(string xmlPath) 40 { 41 XmlDocument xmlDoc = new XmlDocument(); 42 xmlDoc.Load(megafileManager.Open(xmlPath)); 43 44 foreach (XmlNode teamColorNode in xmlDoc.SelectNodes("/*/TeamColorTypeClass")) 45 { 46 var teamColor = new TeamColor(this, megafileManager); 47 teamColor.Load(teamColorNode.OuterXml); 48 49 teamColors[teamColorNode.Attributes["Name"].Value] = teamColor; 50 } 51 52 foreach (var teamColor in TopologicalSortTeamColors()) 53 { 54 teamColor.Flatten(); 55 } 56 } 57 58 private IEnumerable<TeamColor> TopologicalSortTeamColors() 59 { 60 var nodes = teamColors.Values.ToList(); 61 HashSet<(TeamColor, TeamColor)> edges = new HashSet<(TeamColor, TeamColor)>(); 62 foreach (var node in nodes) 63 { 64 if (!string.IsNullOrEmpty(node.Variant)) 65 { 66 edges.Add((this[node.Variant], node)); 67 } 68 } 69 70 var sorted = new List<TeamColor>(); 71 var openSet = new HashSet<TeamColor>(nodes.Where(n => edges.All(e => !e.Item2.Equals(n)))); 72 while (openSet.Count > 0) 73 { 74 var node = openSet.First(); 75 openSet.Remove(node); 76 sorted.Add(node); 77 78 foreach (var edge in edges.Where(e => e.Item1.Equals(node)).ToArray()) 79 { 80 var node2 = edge.Item2; 81 edges.Remove(edge); 82 83 if (edges.All(edge2 => !edge2.Item2.Equals(node2))) 84 { 85 openSet.Add(node2); 86 } 87 } 88 } 89 90 return (edges.Count == 0) ? sorted : null; 91 } 92 } 93 }