/// <summary> /// Select should be called from within other GuiManagers /// and wants this manager to get avtive and go to given item. /// </summary> /// <param name="item">The KmlItem to select</param> /// <returns>Whether item was found or not</returns> public bool Select(KmlItem item) { KmlNode masterNode = item is KmlNode ? (KmlNode)item : item.Parent; foreach (GuiKerbalsNode node in KerbalsList.Items) { if (node.DataKerbal == masterNode) { // Force a refreh, by causing SelectionChanged to invoke KerbalsList.SelectedItem = null; KerbalsList.SelectedItem = node; KerbalsList.ScrollIntoView(node); Focus(); if (item is KmlAttrib) { foreach (GuiTreeAttrib attrib in KerbalsDetails.Items) { if (attrib.DataAttrib == item) { attrib.IsSelected = true; KerbalsDetails.Focus(); } } } return(true); } } return(false); }
private void Tree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { // Store currently selected attribute, in case we just unselect + select the current item to refresh if (Tree.SelectedItem == null) { // We're unselcting, this is the old data we want to restore in future call of this event GuiTreeAttrib attrib = (TreeDetails.SelectedItem as GuiTreeAttrib); if (attrib == null) { _oldSelectedAttrib = null; _alternativeSelectedAttrib = null; } else { _oldSelectedAttrib = attrib.DataAttrib; int i = TreeDetails.SelectedIndex; if (i < TreeDetails.Items.Count - 1) { _alternativeSelectedAttrib = (TreeDetails.Items[i + 1] as GuiTreeAttrib).DataAttrib; } else if (i > 0) { _alternativeSelectedAttrib = (TreeDetails.Items[i - 1] as GuiTreeAttrib).DataAttrib; } else { _alternativeSelectedAttrib = null; } } } TreeDetails.Items.Clear(); if (Tree.SelectedItem != null) { GuiTreeNode Node = (GuiTreeNode)Tree.SelectedItem; TreeDetails.ContextMenu = Node.ContextMenu; foreach (KmlAttrib attrib in Node.DataNode.Attribs) { TreeDetails.Items.Add(new GuiTreeAttrib(attrib)); } _oldSelectedNode = Node.DataNode; // Restore attrib selection if (Node.DataNode == _oldSelectedNode && _oldSelectedAttrib != null) { if (!Select(_oldSelectedAttrib)) { Select(_alternativeSelectedAttrib); } if (TreeDetails.SelectedItem != null) { (TreeDetails.SelectedItem as ListViewItem).Focus(); } } } else { TreeDetails.ContextMenu = null; } }
/// <summary> /// Writes serialized KmlItem into writer /// </summary> /// <param name="writer">Writer used to write serialized item.</param> /// <param name="item">Item for serialization.</param> /// <param name="indent">Default indent.</param> public static void WriteItem(TextWriter writer, KmlItem item, int indent) { bool ghost = item is KmlGhostNode; if (!ghost) { writer.WriteLine(item.ToLine(indent)); } if (item is KmlNode) { int newIndent = indent; KmlNode node = (KmlNode)item; if (!ghost) { writer.WriteLine(new KmlBegin().ToLine(indent)); newIndent = indent + 1; } foreach (KmlItem child in node.AllItems) { WriteItem(writer, child, newIndent); } if (!ghost) { writer.WriteLine(new KmlEnd().ToLine(indent)); } } }
private void AddAttrib(KmlNode toItem, KmlAttrib beforeItem) { KmlNode node = toItem; string input; string preset = ""; bool loop = true; while (loop && DlgInput.Show("Enter the name for the new attribute:", "NEW attribute", Icons.Add, preset, out input)) { string attrib = input; if (attrib.Length > 0 && attrib.IndexOf('=') < 0) { attrib = attrib + "="; } KmlItem item = KmlItem.CreateItem(attrib); if (item is KmlAttrib && beforeItem != null) { node.InsertBefore(beforeItem, (KmlAttrib)item); loop = false; // View will be refreshed in AttribChanged event } else if (item is KmlAttrib) { node.Add((KmlAttrib)item); loop = false; // View will be refreshed in AttribChanged event } else { DlgMessage.Show("Attribute name is not allowed to be empty or contain following characters: {}", "NEW attribute", Icons.Warning); preset = input; // Input will pop up again while loop == true } } }
/// <summary> /// Creates a GuiTreeNode containing the given dataNode. /// </summary> /// <param name="dataNode">The KmlNode to contain</param> /// <param name="withImage">Do you want an Image in your tree node?</param> /// <param name="withText">Do you want text in your tree node?</param> /// <param name="withMenu">Do you want a context menu for your tree node?</param> /// <param name="withAddMenu">Do you want a context menu for adding nodes?</param> /// <param name="withDeleteMenu">Do you want a context menu for deletion of this tree node?</param> /// <param name="withChildren">Do you want tree children to expand under this node?</param> public GuiTreeNode(KmlNode dataNode, bool withImage, bool withText, bool withMenu, bool withAddMenu, bool withDeleteMenu, bool withChildren) { DataNode = dataNode; TemplateWithImage = withImage; TemplateWithText = withText; TemplateWithMenu = withMenu; TemplateWithAddMenu = withAddMenu; TemplateWithDeleteMenu = withDeleteMenu; AssignTemplate(withImage, withText); if (withChildren) { PrepareChildren(); } // Get notified when KmlNode ToString() changes DataNode.ToStringChanged += DataNode_ToStringChanged; // Get notified when attributes / children are added / deleted DataNode.AttribChanged += DataNode_AttribChanged; DataNode.ChildrenChanged += DataNode_ChildrenChanged; // Build a context menu with tools if (withMenu) { BuildContextMenu(withAddMenu, withDeleteMenu); } }
private void ReLoadChildren() { if (NeedsLoadingChildren()) { LoadChildren(); } else { // Check all KmlNodes for (int i = 0; i < DataNode.Children.Count; i++) { KmlNode child = DataNode.Children[i]; if (Items.Count > i && (Items[i] as GuiTreeNode).DataNode != child) { Items.Insert(i, new GuiTreeNode(child)); } else { Add(child); } } // Check if there are Items left to delete for (int i = Items.Count - 1; i > DataNode.Children.Count - 1; i--) { Items.RemoveAt(i); } } }
private void AddChildNode(KmlNode toItem, KmlNode beforeItem) { KmlNode node = toItem; string input; string preset = ""; bool loop = true; while (loop && DlgInput.Show("Enter the tag for the new node:", "NEW node", Icons.Add, preset, out input)) { KmlItem item = KmlItem.CreateItem(input); if (item is KmlNode && beforeItem != null) { node.InsertBefore(beforeItem, (KmlNode)item); loop = false; // View will be refreshed in ChildrenChanged event } else if (item is KmlNode) { node.Add((KmlNode)item); loop = false; // View will be refreshed in ChildrenChanged event } else { DlgMessage.Show("Tag is not allowed to be empty or contain following characters: ={}", "NEW node", Icons.Warning); preset = input; // Input will pop up again while loop == true } } }
private static void WriteFile(StreamWriter file, KmlItem item, int indent) { bool ghost = item is KmlGhostNode; if (!ghost) { file.WriteLine(item.ToLine(indent)); } if (item is KmlNode) { int newIndent = indent; KmlNode node = (KmlNode)item; if (!ghost) { file.WriteLine(new KmlBegin().ToLine(indent)); newIndent = indent + 1; } foreach (KmlItem child in node.AllItems) { WriteFile(file, child, newIndent); } if (!ghost) { file.WriteLine(new KmlEnd().ToLine(indent)); } } }
private static void RepairClearDocking(KmlPartDock dock1, KmlPartDock dock2) { try { KmlNode module = dock1.GetChildNode("MODULE", "ModuleDockingNode"); module.GetAttrib("state").Value = "Ready"; //module.GetAttrib("dockUId").Value = ""; KmlNode events = module.GetChildNode("EVENTS"); events.GetChildNode("Undock").GetAttrib("active").Value = "False"; events.GetChildNode("UndockSameVessel").GetAttrib("active").Value = "False"; if (dock2 != null) { module = dock2.GetChildNode("MODULE", "ModuleDockingNode"); module.GetAttrib("state").Value = "Ready"; //module.GetAttrib("dockUId").Value = ""; events = module.GetChildNode("EVENTS"); events.GetChildNode("Undock").GetAttrib("active").Value = "False"; events.GetChildNode("UndockSameVessel").GetAttrib("active").Value = "False"; } System.Windows.MessageBox.Show("Successfully reset docking to ready. Please save and reload to see the rebuilt part structure."); // TODO KmlPartDock:RepairClearDocking(): Refresh structure without save / reload } catch (NullReferenceException) { System.Windows.MessageBox.Show("Couldn't reset docking node, there are sub-nodes missing.\n" + "You should copy a MODULE node from a functional state 'Ready' part.\n"); } }
private bool SelectSearch(Stack <KmlNode> stack, KmlItem item) { KmlNode node = stack.Peek(); foreach (KmlItem sub in node.AllItems) { if (sub == item) { return(true); } else if (sub is KmlNode) { stack.Push(sub as KmlNode); if (SelectSearch(stack, item)) { return(true); } else { stack.Pop(); } } } return(false); }
private List <T> GetFlatList <T>(KmlNode parent) where T : KmlItem { List <KmlItem> source; if (parent == null) { source = KmlRoots; } else { source = parent.AllItems; } List <T> target = new List <T>(); foreach (KmlItem item in source) { if (item is T) { target.Add((T)item); } if (item is KmlNode) { target.AddRange(GetFlatList <T>((KmlNode)item)); } } return(target); }
/// <summary> /// Creates a KmlResource as a copy of a given KmlNode. /// </summary> /// <param name="node">The KmlNode to copy</param> public KmlResource(KmlNode node) : base(node.Line, node.Parent) { Amount = new KmlAttrib("amount ="); MaxAmount = new KmlAttrib("maxAmount ="); AddRange(node.AllItems); }
/// <summary> /// This method is called by KmlPart.BuildAttachmentStructure() after a complete vessel is read and all parts exist, /// so we can build KmlPart references from the index or UId information got from reading this part anlone. /// </summary> /// <param name="dock">The part identified as KmlPartDock</param> /// <param name="other">The other docked KmlPart (could be KmlPartDock also)</param> public static void BuildDockStructure(KmlPartDock dock, KmlPart other) { if (dock.DockUid == other.Uid) { dock.DockedPart = other; } else { Syntax.Warning(dock, "Dock part is attached to (UId " + dock.DockUid + ") but supposed to be attached to: " + other.ToString() + " (UId " + other.Uid + ")"); dock.NeedsRepair = true; } if (dock.DockType == DockTypes.Dock && dock.DockState.ToLower() == "docked (docker)") { KmlNode module = dock.GetChildNode("MODULE", "ModuleDockingNode"); if (module == null) { Syntax.Warning(dock, "Dock sub-node MODULE with name = 'ModuleDockingNode' is missing. Please copy one from functional dock part or older save file"); dock.NeedsRepair = true; } else if (module.GetChildNode("DOCKEDVESSEL") == null) { Syntax.Warning(dock, "Dock sub-sub-node DOCKEDVESSEL is missing"); dock.NeedsRepair = true; } } else if (dock.DockType == DockTypes.Grapple && dock.DockState.ToLower() == "grappled") { KmlNode module = dock.GetChildNode("MODULE", "ModuleGrappleNode"); if (module == null) { Syntax.Warning(dock, "Grapple sub-node MODULE with name = 'ModuleGrappleNode' is missing. Please copy one from functional dock part or older save file"); dock.NeedsRepair = true; } else { if (module.GetChildNode("DOCKEDVESSEL") == null) { Syntax.Warning(dock, "Grapple sub-sub-node DOCKEDVESSEL is missing"); dock.NeedsRepair = true; } if (module.GetChildNode("DOCKEDVESSEL_other") == null) { Syntax.Warning(dock, "Grapple sub-sub-node DOCKEDVESSEL_other is missing"); dock.NeedsRepair = true; } } } else if (dock.DockType == DockTypes.KasCPort) { KmlNode module = dock.GetChildNode("MODULE", "KASModuleStrut"); if (module == null) { Syntax.Warning(dock, "KAS CPort sub-node MODULE with name = 'KASModuleStrut' is missing. Please copy one from functional CPort part or older save file"); dock.NeedsRepair = true; } } }
private static void RepairDockerDockee(KmlPartDock docker, KmlPartDock dockee) { if (docker.ParentPart == dockee || dockee.ParentPart == docker) { bool dockerOk = false; bool dockeeOk = false; try { KmlNode module = docker.GetChildNode("MODULE", "ModuleDockingNode"); module.GetAttrib("state").Value = "Docked (docker)"; module.GetAttrib("dockUId").Value = dockee.Uid; KmlNode events = module.GetChildNode("EVENTS"); events.GetChildNode("Undock").GetAttrib("active").Value = "True"; events.GetChildNode("UndockSameVessel").GetAttrib("active").Value = "False"; if (module.GetChildNode("DOCKEDVESSEL") == null) { System.Windows.MessageBox.Show("Couldn't find sub-node DOCKEDVESSEL, you should try to copy it from older save files."); } else { dockerOk = true; } } catch (NullReferenceException) { System.Windows.MessageBox.Show("Couldn't fix docker node, there are sub-nodes missing.\n" + "You should copy a MODULE node from a functional 'Docked (docker)' part.\n" + "Docker should be: " + docker); } try { KmlNode module = dockee.GetChildNode("MODULE", "ModuleDockingNode"); module.GetAttrib("state").Value = "Docked (dockee)"; module.GetAttrib("dockUId").Value = docker.Uid; KmlNode events = module.GetChildNode("EVENTS"); events.GetChildNode("Undock").GetAttrib("active").Value = "False"; events.GetChildNode("UndockSameVessel").GetAttrib("active").Value = "False"; dockeeOk = true; } catch (NullReferenceException) { System.Windows.MessageBox.Show("Couldn't fix dockee node, there are sub-nodes missing.\n" + "You should copy a MODULE node from a functional 'Docked (dockee)' part.\n" + "Dockee should be: " + dockee); } if (dockerOk && dockeeOk) { System.Windows.MessageBox.Show("Successfully repaired docker-dockee. Please save and reload to see the rebuilt part structure."); // TODO KmlPartDock:RepairDockerDockee(): Refresh structure without save / reload } } else { RepairSameVesselChoose(docker, dockee); } }
private static List <KmlItem> ParseFile(System.IO.StreamReader file, KmlNode parent) { List <KmlItem> list = new List <KmlItem>(); string line; while ((line = file.ReadLine()) != null) { KmlItem newItem = ParseLine(line); if (newItem is KmlBegin) { KmlItem lastItem; int l = list.Count - 1; if (l < 0) { lastItem = new KmlItem(""); } else { lastItem = list[l]; list.RemoveAt(l); } KmlNode newNode = new KmlNode(lastItem, parent); if (newNode.Tag.ToLower() == "vessel") { newNode = new KmlVessel(newNode); } else if (newNode.Tag.ToLower() == "kerbal") { newNode = new KmlKerbal(newNode); } else if (newNode.Tag.ToLower() == "part") { newNode = new KmlPart(newNode); } else if (newNode.Tag.ToLower() == "resource") { newNode = new KmlResource(newNode); } list.Add(newNode); newNode.AddRange(ParseFile(file, newNode)); } else if (newItem is KmlEnd) { Identify(list); return(list); } else { list.Add(newItem); } } Identify(list); return(list); }
/// <summary> /// Creates a KmlItem with a line read from data file. /// </summary> /// <param name="line">String with only one line from data file</param> public KmlItem(string line) { this.Line = line; // Parent will be set within parent's Add method Parent = null; // Default is to allow any item deletion. // Sepcial ones, used for class properties will be protected. CanBeDeleted = true; }
/// <summary> /// Serach all child nodes of sourceNode for a certain tag. /// Does not search recursive. /// </summary> /// <param name="sourceNode">The node to search in its chgild nodes</param> /// <param name="tag">The tag of the KmlNode to search for</param> /// <returns>The found KmlNode or null if no such is found</returns> public static KmlNode GetChildNodeFrom(KmlNode sourceNode, string tag) { if (sourceNode != null) { return(sourceNode.GetChildNode(tag)); } else { return(null); } }
/// <summary> /// Some key was pressed. /// </summary> public void CommandExec(string Command) { if (TreeDetails.IsKeyboardFocusWithin && TreeDetails.SelectedItem is GuiTreeAttrib) { if (Command == "Enter") { // Enter the TextBox for value editing TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next); (TreeDetails.SelectedItem as ListViewItem).MoveFocus(request); } else if (Command == "Escape" || Command == "Left") { // Get back to TreeView Tree.Focus(); (Tree.SelectedItem as TreeViewItem).Focus(); } else { (TreeDetails.SelectedItem as GuiTreeAttrib).CommandExec(Command); } } else if (TreeDetails.IsKeyboardFocusWithin) { // Empty details if (Command == "Left") { // Get back to TreeView Tree.Focus(); (Tree.SelectedItem as TreeViewItem).Focus(); } } else if (Tree.IsKeyboardFocusWithin && Tree.SelectedItem is GuiTreeNode) { if (Command == "Enter" && TreeDetails.HasItems) { // Switch to attributes TreeDetails.Focus(); KmlItem item = GetSelectedItem(); if (item is KmlNode) { KmlNode node = (KmlNode)item; if (node.Attribs.Count > 0) { Select(node.Attribs[0]); (TreeDetails.SelectedItem as ListViewItem).Focus(); } } } else { (Tree.SelectedItem as GuiTreeNode).CommandExec(Command); } } }
/// <summary> /// Creates a KmlNode with a line read from data file as a child of given parent node. /// </summary> /// <param name="line">String with only one line from data file</param> /// <param name="parent">The parent KmlNode or null to create a root node</param> public KmlNode(string line, KmlNode parent) : base(line) { Tag = line.Trim(); Name = ""; AllItems = new List <KmlItem>(); Parent = parent; Children = new List <KmlNode>(); Attribs = new List <KmlAttrib>(); Unknown = new List <KmlItem>(); }
/// <summary> /// Changes the parent. Needed when a node is changed to a derived class /// and all existing children need to have a new parent. /// </summary> /// <param name="item">The KmlItem where parent needs to be changed</param> /// <param name="parent">The new parent KmlNode</param> protected static void RemapParent(KmlItem item, KmlNode parent) { if (item.Parent != parent) { // This often happens when we iterate through the lists, // so we can not delete items from that list here. // TODO KmlItem.RemapParent(): Delete item from old parent // item.Delete(); // from previous parent item.UnbindOldParent(); item.Parent = parent; item.IdentifyParent(); } }
/// <summary> /// Serach all nodes in sourceItems for the first tag in tag. /// Then search recursive in the found node's children for next tag in tags. /// </summary> /// <param name="sourceItems">The list of KmlItems to search in</param> /// <param name="tags">An array of tags of the KmlNodes to search for</param> /// <returns>The found KmlNode or null if no such is found</returns> public static KmlNode GetNodeFromDeep(List <KmlItem> sourceItems, string[] tags) { if (tags.Length > 0) { KmlNode node = GetNodeFrom(sourceItems, tags[0]); for (int i = 1; i < tags.Length && node != null; i++) { node = GetChildNodeFrom(node, tags[i]); } return(node); } return(null); }
private KmlNode GetNextSibling(KmlNode node) { int index = Children.IndexOf(node); if (index >= 0 && index < Children.Count - 1) { return(Children[index + 1]); } else { return(null); } }
private void NodeInsertBefore_Click(object sender, RoutedEventArgs e) { KmlNode node = ((sender as MenuItem).DataContext as KmlNode); if (node.Parent != null) { AddChildNode(node.Parent, node); } else { DlgMessage.Show("Can not insert, node has no parent", "NEW node", Icons.Warning); } }
/// <summary> /// Creates a GuiKebalsManager to link and manage the given two ListViews. /// </summary> /// <param name="master">The master GuiTabsManager</param> /// <param name="kerbalsList">The ListView to manage the kerbal list</param> /// <param name="kerbalsDetails">The ListView to manage the kerbal details</param> /// <param name="kerbalsCount">The Label to display the visible items count</param> public GuiKebalsManager(GuiTabsManager master, ListView kerbalsList, ListView kerbalsDetails, Label kerbalsCount) { Filter = new GuiKerbalsFilter(); Master = master; Kerbals = new List <KmlKerbal>(); KerbalsList = kerbalsList; KerbalsDetails = kerbalsDetails; KerbalsCount = kerbalsCount; Roster = null; KerbalsList.SelectionChanged += KerbalsList_SelectionChanged; }
/// <summary> /// After all items are loaded, each items Finalize is called. /// The roots list will contain all loaded items in KML tree structure. /// Each item can then check for other items to get further properties. /// </summary> /// <param name="roots">The loaded root items list</param> protected override void Finalize(List <KmlItem> roots) { base.Finalize(roots); if (Origin == KerbalOrigin.Roster) { string[] tags = { "game", "flightstate" }; KmlNode flightStateNode = GetNodeFromDeep(roots, tags); if (flightStateNode != null) { foreach (KmlNode vesselNode in flightStateNode.Children) { if (vesselNode is KmlVessel) { KmlVessel vessel = (KmlVessel)vesselNode; foreach (KmlPart part in vessel.Parts) { foreach (KmlAttrib attrib in part.Attribs) { if (attrib.Name.ToLower() == "crew" && attrib.Value.ToLower() == Name.ToLower()) { if (AssignedCrewAttrib == null) { AssignedVessel = vessel; AssignedPart = part; AssignedCrewAttrib = attrib; attrib.CanBeDeleted = false; } else { Syntax.Warning(attrib, "Kerbal is listed in multiple vessel part's crew. Kerbal: " + Name + "Assigned vessel: " + AssignedVessel.Name + ", Assigned part: " + AssignedPart + ", Unused Vessel: " + vessel.Name + ", Unused part: " + part); } if (State.ToLower() != "assigned") { Syntax.Warning(this, "Kerbal is listed in a vessels crew list, but state is not 'Assigned'. Vessel: " + vessel.Name + ", Part: " + part); } } } } } } } if (AssignedCrewAttrib == null && State.ToLower() == "assigned" && Type.ToLower() != "unowned") { Syntax.Warning(this, "Kerbal state is 'Assigned' but not listed in any vessels crew list"); } } }
private static void RepairSameVesselDockee(KmlPartDock same, KmlPartDock dockee) { if (same.ParentPart == dockee || dockee.ParentPart == same) { RepairDependingWhosParent(same, dockee); } else { bool sameOk = false; bool dockeeOk = false; try { KmlNode module = same.GetChildNode("MODULE", "ModuleDockingNode"); module.GetAttrib("state").Value = "Docked (same vessel)"; module.GetAttrib("dockUId").Value = dockee.Uid; KmlNode events = module.GetChildNode("EVENTS"); events.GetChildNode("Undock").GetAttrib("active").Value = "False"; events.GetChildNode("UndockSameVessel").GetAttrib("active").Value = "True"; sameOk = true; } catch (NullReferenceException) { System.Windows.MessageBox.Show("Couldn't fix same vessel docking node, there are sub-nodes missing.\n" + "You should copy a MODULE node from a functional 'Docked (same vessel)' part.\n" + "Same vessel dock should be: " + same); } try { KmlNode module = dockee.GetChildNode("MODULE", "ModuleDockingNode"); module.GetAttrib("state").Value = "Docked (dockee)"; module.GetAttrib("dockUId").Value = same.Uid; KmlNode events = module.GetChildNode("EVENTS"); events.GetChildNode("Undock").GetAttrib("active").Value = "False"; events.GetChildNode("UndockSameVessel").GetAttrib("active").Value = "False"; dockeeOk = true; } catch (NullReferenceException) { System.Windows.MessageBox.Show("Couldn't fix dockee node, there are sub-nodes missing.\n" + "You should copy a MODULE node from a functional 'Docked (dockee)' part.\n" + "Dockee should be: " + dockee); } if (sameOk && dockeeOk) { System.Windows.MessageBox.Show("Successfully repaired same vessel docking. Please save and reload to see the rebuilt part structure."); // TODO KmlPartDock:RepairDockerDockee(): Refresh structure without save / reload } } }
/// <summary> /// Search all child nodes of this node for a certain tag and name, /// create one if not found. Does not search recursive. /// </summary> /// <param name="tag">The tag of the KmlNode to search for</param> /// <param name="name">The name of the KmlNode to search for</param> /// <returns>The found or created KmlNode</returns> public KmlNode GetOrCreateChildNode(string tag, string name) { KmlNode node = GetChildNode(tag, name); if (node == null) { node = KmlItem.CreateItem(tag) as KmlNode; if (name != null && name.Length > 0) { // Add name attribute node.Add(KmlItem.CreateItem("name=" + name)); } Add(node); } return(node); }
private static void Identify(List <KmlItem> list, bool recursive = false) { for (int i = 0; i < list.Count; i++) { KmlItem item = list[i]; if (recursive && item is KmlNode) { KmlNode node = (KmlNode)item; Identify(node.AllItems, recursive); } KmlItem replaceItem = item.Identify(); if (replaceItem != null) { list[i] = replaceItem; } } }
/// <summary> /// Creates a KmlVessel as a copy of a given KmlNode. /// </summary> /// <param name="node">The KmlNode to copy</param> public KmlVessel(KmlNode node) : base(node.Line) { // First parent is null, will be set later when added to parent, // then IdentifyParent() will set Origin. Origin = VesselOrigin.Other; Type = ""; Situation = ""; Parts = new List <KmlPart>(); Flags = new List <string>(); AssignedCrew = new List <KmlKerbal>(); ResourceTypes = new SortedSet <string>(); RootPart = null; AddRange(node.AllItems); }
/// <summary> /// After all items are loaded, each items Finalize is called. /// The roots list will contain all loaded items in KML tree structure. /// Each item can then check for other items to get further properties. /// </summary> /// <param name="roots">The loaded root items list</param> protected override void Finalize(List <KmlItem> roots) { base.Finalize(roots); if (Origin == VesselOrigin.Flightstate) { AssignedCrew.Clear(); string[] tags = { "game", "roster" }; KmlNode rosterNode = GetNodeFromDeep(roots, tags); if (rosterNode != null) { foreach (KmlPart part in Parts) { foreach (KmlAttrib attrib in part.Attribs) { if (attrib.Name.ToLower() == "crew" && attrib.Value.Length > 0) { int oldCrewCount = AssignedCrew.Count; foreach (KmlNode kerbalNode in rosterNode.Children) { if (kerbalNode is KmlKerbal) { KmlKerbal kerbal = (KmlKerbal)kerbalNode; if (attrib.Value.ToLower() == kerbal.Name.ToLower()) { // Duplicate entries are checked on the kerbal side, // here only duplicates within one vessel could be checked, // there all vessels are checked AssignedCrew.Add(kerbal); } } } if (AssignedCrew.Count < oldCrewCount + 1) { Syntax.Warning(attrib, "Crew could not be assigned, this kerbal does not exist: " + attrib.Value); } else if (AssignedCrew.Count > oldCrewCount + 1) { Syntax.Warning(attrib, "Crew member not unique, there are multiple kerbals with name: " + attrib.Value); } } } } } } }