/// <summary> /// Creates a GuiVesselsPartGraphNode containing the given KmlPart at the given PartGrid koordinates. /// Also needs a master GuiTabsManager to switch view on double click on this node. /// </summary> /// <param name="part">The KmlPart this node will represent</param> /// <param name="koordX">The X koord in parents PartGrid</param> /// <param name="koordY">The Y koord in parents PartGrid</param> /// <param name="master">The master GuiTabsManager</param> public GuiVesselsPartGraphNode(KmlPart part, int koordX, int koordY, GuiTabsManager master) { KoordX = koordX; KoordY = koordY; Master = master; Lines = new List <Line>(); if (part != null) { Orientation = System.Windows.Controls.Orientation.Horizontal; Icon = new GuiTreeNode(part, true, false, true, false); Icon.ToolTip = part.ToString(); Icon.Margin = new System.Windows.Thickness(-16, 0, 0, 0); // GuiTreeNode gets selected and drawn highlighted after using its context menu // we don't want this in the part graph Icon.Selected += Icon_Selected; Children.Add(Icon); Text = new Label(); Text.DataContext = part; Text.Content = "[" + (part.Parent as KmlVessel).Parts.IndexOf(part) + "]"; Text.ToolTip = part.ToString(); // TODO GuiVesselsPartGraphNode.GuiVesselsPartGraphNode(): Label.ContextMenu does not really work Text.ContextMenu = Icon.ContextMenu; Text.Margin = new System.Windows.Thickness(-6, -6, 0, 0); Children.Add(Text); MouseEnter += Node_MouseEnter; MouseLeave += Node_MouseLeave; Icon.MouseDoubleClick += Node_MouseDoubleClick; // TODO GuiVesselsPartGraphNode.GuiVesselsPartGraphNode(): Label.MouseDoubleClick does not really work Text.MouseDoubleClick += Node_MouseDoubleClick; } }
/// <summary> /// Identify whether a KmlPart is a docking port part, /// so it should be replaced by an intance of KmlPartDock. /// </summary> /// <param name="part">The KmlPart to check</param> /// <returns>True if KmlPart should be replaced by KmlPartDock</returns> public static bool PartIsDock(KmlPart part) { foreach (KmlNode node in part.Children) { if (node.Tag.ToLower() != "module") { continue; } if (node.Name.ToLower() == "moduledockingnode") { return(true); } else if (node.Name.ToLower() == "moduledockingnodenamed") { return(true); } else if (node.Name.ToLower() == "modulegrapplenode") { return(true); } else if (node.Name.ToLower() == "kasmodulestrut") { return(true); } } return(false); }
private static void RepairGrappleAttachment(KmlPart part, int attachmentIndex) { int lastIndex = -1; // Repair part 'attN = grapple, <attachmentIndex>' for (int i = 0; i < part.Attribs.Count; i++) { KmlAttrib attrib = part.Attribs[i]; if (attrib.Name.ToLower() == "attn") { lastIndex = i; if (attrib.Value.ToLower().StartsWith("grapple,") || attrib.Value.EndsWith(", " + attachmentIndex)) { attrib.Value = "grapple, " + attachmentIndex; return; } } else if (attrib.Name.ToLower() == "srfn") { lastIndex = i; } } // If we got here we didn't find it KmlAttrib newAttrib = new KmlAttrib("attN = grapple, " + attachmentIndex); part.Attribs.Insert(lastIndex + 1, newAttrib); part.AllItems.Insert(lastIndex + 1, newAttrib); }
/// <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 int CountBottom(KmlPart part, KmlPart cameFrom) { int c = 1; if (part.AttachedPartsSurface.Count > 2) { c = 2; foreach (KmlPart p in part.AttachedPartsSurface) { if (p != cameFrom) { c = Math.Max(c, CountBottom(p, part) + 1); } } } if (part.AttachedPartsFront.Count > 0) { c = Math.Max(c, 2); foreach (KmlPart p in part.AttachedPartsFront) { if (p != cameFrom) { c = Math.Max(c, CountBottom(p, part) + 1); } } } foreach (KmlPart p in part.AttachedPartsBack) { if (p != cameFrom) { c = Math.Max(c, CountBottom(p, part) - 1); } } foreach (KmlPart p in part.AttachedPartsLeft) { if (p != cameFrom) { c = Math.Max(c, CountBottom(p, part)); } } foreach (KmlPart p in part.AttachedPartsRight) { if (p != cameFrom) { c = Math.Max(c, CountBottom(p, part)); } } if (part is KmlPartDock) { KmlPart p = ((KmlPartDock)part).DockedPart; if (p != null && p != cameFrom) { c = Math.Max(c, CountBottom(p, part)); } } return(c); }
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); }
private void SetRootPart(string value) { if (int.TryParse(value, out rootPartIndex)) { if (Parts.Count > rootPartIndex) { RootPart = Parts[rootPartIndex]; } } }
private void DrawPartAndConnected(KmlPart part, IntPair koords, IntPair parentKoords, Brush lineBrush) { GuiVesselsPartGraphNode partNode = DrawPart(part, koords); Line l = DrawConnection(parentKoords, koords, lineBrush); partNode.Lines.Add(l); GuiVesselsPartGraphNode parentNode = PartGrid[parentKoords.X - PartGridMinX][parentKoords.Y - PartGridMinY]; parentNode.Lines.Add(l); DrawConnectedParts(partNode, koords); }
/// <summary> /// Clear all child nodes and attributes from this node. /// </summary> public override void Clear() { Type = ""; Situation = ""; Parts.Clear(); Flags.Clear(); ResourceTypes.Clear(); RootPart = null; rootPartIndex = 0; base.Clear(); }
private void Node_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) { KmlPart part = null; if (sender is GuiTreeNode) { part = ((GuiTreeNode)sender).DataNode as KmlPart; } else if (sender is Label) { part = ((Label)sender).DataContext as KmlPart; } if (part != null) { GuiTabsManager.GetCurrent().Select(part); } }
/// <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> /// 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, node.Parent) { if (node.Parent != null && node.Parent.Tag.ToLower() == "flightstate") { Origin = VesselOrigin.Flightstate; } else { Origin = VesselOrigin.Other; } Type = ""; Situation = ""; Parts = new List <KmlPart>(); ResourceTypes = new SortedSet <string>(); RootPart = null; AddRange(node.AllItems); }
/// <summary> /// After an item is completely loaded the Intentify() method is called. /// This is the right moment to build the connection structure of the parts. /// There is no class derived from KmlVessel so it doesn't need to be replaced. /// </summary> /// <returns>There is no class derived from KmlVessel so always null is returned</returns> protected override KmlItem Identify() { // No need to replace this by another class, but after vessel is completed // it's the right time to build parts structure List <KmlPart> roots = KmlPart.BuildAttachmentStructure(Parts); if (roots.Count > 1) { Syntax.Warning(this, "Vessel has more than one root part identified from part structure: " + string.Join <KmlPart>(", ", roots.ToArray())); } if (RootPart == null && roots.Count > 0) { Syntax.Warning(this, "Vessel's root part attribute does not point to a valid part. Set root to: " + string.Join <KmlPart>(", ", roots.ToArray())); } else if (RootPart != null && !roots.Contains(RootPart)) { Syntax.Warning(this, "Vessel's root part attribute is not equal to root identified from part structure: " + RootPart.ToString() + " <-> " + string.Join <KmlPart>(", ", roots.ToArray())); } return(base.Identify()); }
private GuiVesselsPartGraphNode DrawPart(KmlPart part, int x, int y) { GuiVesselsPartGraphNode node = new GuiVesselsPartGraphNode(part, x, y, Master); if (!InsertGrid(x, y, node)) { throw new Exception("Couldn't place GuiVesselsPartGraphNode on grid pos " + x + ", " + y + " (already occupied)"); //IntPair p = CalcKoords(new IntPair(x, y), x + 1, y); //InsertGrid(p.X, p.Y, node); } Point position = CalcPosition(x, y); Canvas.SetLeft(node, position.X); Canvas.SetTop(node, position.Y); // Have nodes on higher ZIndex than the lines Canvas.SetZIndex(node, 1); VesselsDetails.Children.Add(node); part.Visited = true; return(node); }
private static KmlNode ParseNode(KmlItem item) { KmlNode newNode = new KmlNode(item); 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); } return(newNode); }
private void AssignTemplate(bool withImage, bool withText) { // Fit an Image and a TextBlock into a Stackpanel, // have the Stackpanel as node Header StackPanel pan = new StackPanel(); pan.Orientation = Orientation.Horizontal; if (withImage) { if (DataNode is KmlResource) { KmlResource res = (KmlResource)DataNode; pan.Children.Add(GenerateProgressBar(res.AmountRatio)); } else if (DataNode is KmlPart) { KmlPart part = (KmlPart)DataNode; pan.Children.Add(GenerateImage(DataNode)); if (part.WorstResourceRatio >= 0.0) { ProgressBar prog = GenerateProgressBar(part.WorstResourceRatio); prog.Height = 4; prog.Margin = new Thickness(-19, 6, 3, 0); pan.Children.Add(prog); } } else { pan.Children.Add(GenerateImage(DataNode)); } } if (withText) { pan.Children.Add(new TextBlock(new Run(DataNode.ToString()))); } Header = pan; }
private void DrawConnectionAndSeachPart(KmlPart part, IntPair parentKoords, Brush lineBrush) { // Already drawn sub part with one way arrow. // Need to draw the reverse arrow only // But where is the node? Point parentPos = CalcPosition(parentKoords); GuiVesselsPartGraphNode parentNode = PartGrid[parentKoords.X - PartGridMinX][parentKoords.Y - PartGridMinY]; foreach (UIElement element in VesselsDetails.Children) { if (element is GuiVesselsPartGraphNode) { GuiVesselsPartGraphNode node = (GuiVesselsPartGraphNode)element; if (node.DataPart == part) { Line l = DrawConnection(parentPos.X, parentPos.Y, Canvas.GetLeft(node), Canvas.GetTop(node), lineBrush); node.Lines.Add(l); parentNode.Lines.Add(l); break; } } } }
private static void RepairGrappleAttachment(KmlPart part, int attachmentIndex) { KmlAttrib lastItem = null; // Repair part 'attN = grapple, <attachmentIndex>' for (int i = 0; i < part.Attribs.Count; i++) { KmlAttrib attrib = part.Attribs[i]; if (attrib.Name.ToLower() == "attn") { lastItem = attrib; if (attrib.Value.ToLower().StartsWith("grapple,") || attrib.Value.EndsWith(", " + attachmentIndex)) { attrib.Value = "grapple, " + attachmentIndex; return; } } else if (attrib.Name.ToLower() == "srfn") { lastItem = attrib; } } // If we got here we didn't find it KmlAttrib newAttrib = new KmlAttrib("attN = grapple, " + attachmentIndex); // InsertAfter will add to the end if lastItem is null part.InsertAfter(lastItem, newAttrib); //if (lastItem != null) //{ // part.Attribs.Insert(part.Attribs.IndexOf(lastItem) + 1, newAttrib); // part.AllItems.Insert(part.AllItems.IndexOf(lastItem) + 1, newAttrib); //} //else //{ // part.Add(newAttrib); //} }
/// <summary> /// Parts of a vessel are first read one after the other, so the first part can only store indices of later parts it is connected to. /// After a complete vessel is read also all parts are read and the indices can be translated in references to now existing KmlParts. /// This is done by this method. Also reverse information (what parts are connected to this one) is then stored in a part. /// </summary> /// <param name="parts">The list of KmlParts, a KmlVessel will have one</param> /// <returns>A list of root parts (not pointing to another parent part). Could be more than one, if some connections are broken.</returns> public static List <KmlPart> BuildAttachmentStructure(List <KmlPart> parts) { List <KmlPart> roots = new List <KmlPart>(); for (int i = 0; i < parts.Count; i++) { // Check parent connection KmlPart part = parts[i]; if (part.ParentPartIndex == i) { // Parent part is itself, so ParentPart property stays null roots.Add(part); } else if (part.ParentPartIndex < 0 || part.ParentPartIndex >= parts.Count) { Syntax.Warning(part, "Part's parent part index [" + part.ParentPartIndex + "] does not point to a valid part."); roots.Add(part); } else { part.ParentPart = parts[part.ParentPartIndex]; if (!part.AttachedToNodeIndices.Contains(part.ParentPartIndex) && part.AttachedToSurfaceIndex != part.ParentPartIndex) { // Part could be docked to parent if ((part is KmlPartDock) && (part.ParentPart is KmlPartDock)) { KmlPartDock docker = (KmlPartDock)part; KmlPartDock dockee = (KmlPartDock)part.ParentPart; // In case of "Docked (same vessel)" there has to be another docker-dockee connection and that would have connection via parent part if (docker.DockState.ToLower() == "docked (docker)") { if (dockee.DockState.ToLower() != "docked (dockee)") { Syntax.Warning(dockee, "Dock part is parent of other docker part. Docking state should be 'Docked (dockee)' but is '" + dockee.DockState + "', other dock: " + docker); docker.NeedsRepair = true; dockee.NeedsRepair = true; } else { KmlPartDock.BuildDockStructure(dockee, docker); KmlPartDock.BuildDockStructure(docker, dockee); } } else if (docker.DockState.ToLower() == "docked (dockee)") { if (dockee.DockState.ToLower() != "docked (docker)") { Syntax.Warning(dockee, "Dock part is parent of other dockee part. Docking state should be 'Docked (docker)' but is '" + dockee.DockState + "', other dock: " + docker); docker.NeedsRepair = true; dockee.NeedsRepair = true; } else { KmlPartDock.BuildDockStructure(dockee, docker); KmlPartDock.BuildDockStructure(docker, dockee); } } else { if (dockee.DockState.ToLower() == "docked (dockee)") { Syntax.Warning(docker, "Dock part is docked to parent dockee part. Docking state should be 'Docked (docker)' but is '" + docker.DockState + "', parent dock: " + dockee); } else if (dockee.DockState.ToLower() == "docked (docker)") { Syntax.Warning(docker, "Dock part is docked to parent docker part. Docking state should be 'Docked (dockee)' but is '" + docker.DockState + "', parent dock: " + dockee); } else { Syntax.Warning(docker, "Dock part is docked to parent dock part. Docking state should be 'Docked (docker)' or 'Docked (dockee)' but is '" + docker.DockState + "', parent dock: " + dockee); Syntax.Warning(dockee, "Dock part is parent of other dock part. Docking state should be 'Docked (dockee)' or 'Docked (docker)' but is '" + dockee.DockState + "', other dock: " + docker); } docker.NeedsRepair = true; dockee.NeedsRepair = true; } } // Part could be grappled by parent else if ((part.ParentPart is KmlPartDock) && (part.ParentPart as KmlPartDock).DockType == KmlPartDock.DockTypes.Grapple) { KmlPartDock grapple = (KmlPartDock)part.ParentPart; if (grapple.DockUid != part.Uid) { Syntax.Warning(part, "Part not attached or grappled by parent grappling part: " + grapple); Syntax.Warning(grapple, "Grappling part is parent of other part, but is not grappled to it: " + part); grapple.NeedsRepair = true; } else if (grapple.DockState.ToLower() != "grappled") { Syntax.Warning(part, "Part grappled by parent part. Docking state should be 'Grappled' but is '" + grapple.DockState + "', parent grapple: " + grapple); Syntax.Warning(grapple, "Grappling part is parent of grappled part. Docking state should be 'Grappled' but is '" + grapple.DockState + "', grappled part: " + part); grapple.NeedsRepair = true; } else { // It's docked but grappling needs a node attachment KmlPartDock.BuildDockStructure(grapple, part); Syntax.Warning(part, "Part is docked but not attached to parent grappling part: " + grapple); Syntax.Warning(grapple, "Grappling part is parent and docked but not attached to grappled part: " + part); grapple.NeedsRepair = true; } } // TODO KmlPart.BuildAttachmentStructure(): How do KAS links work? // Usually you can only attach a new part by a node to the surface of parent // and not attach a part by surface to parents node. But if you have vessels docked // this situation may happen and this leads to this additional check else if (part.ParentPart.AttachedToSurfaceIndex != i) { Syntax.Warning(part, "Part not attached to parent part: " + part.ParentPart); } } } // Check attachments foreach (int p in part.AttachedToNodeIndices) { if (p >= 0 && p < parts.Count) { KmlPart other = parts[p]; // Sort attached part in the corresponding list, identified by position not by node name double diffX = part.Position.X - other.Position.X; double diffY = part.Position.Y - other.Position.Y; double diffZ = part.Position.Z - other.Position.Z; if (Math.Abs(diffX) > Math.Abs(diffY) && Math.Abs(diffX) > Math.Abs(diffZ)) { if (diffX > 0) { other.AttachedPartsRight.Add(part); part.AttachedToPartsLeft.Add(other); } else { other.AttachedPartsLeft.Add(part); part.AttachedToPartsRight.Add(other); } } else if (Math.Abs(diffZ) > Math.Abs(diffX) && Math.Abs(diffZ) > Math.Abs(diffY)) { if (diffZ > 0) { other.AttachedPartsFront.Add(part); part.AttachedToPartsBack.Add(other); } else { other.AttachedPartsBack.Add(part); part.AttachedToPartsFront.Add(other); } } else { if (diffY > 0) { other.AttachedPartsTop.Add(part); part.AttachedToPartsBottom.Add(other); } else { other.AttachedPartsBottom.Add(part); part.AttachedToPartsTop.Add(other); } } if (!other.AttachedToNodeIndices.Contains(parts.IndexOf(part))) { if ((other is KmlPartDock) && (other as KmlPartDock).DockType == KmlPartDock.DockTypes.Grapple) { KmlPartDock grapple = (KmlPartDock)other; if (grapple.DockUid != part.Uid) { Syntax.Warning(part, "Part node attachment not responded from other grappling part: " + grapple); grapple.NeedsRepair = true; } else if (grapple.DockState.ToLower() != "grappled") { Syntax.Warning(part, "Part grappled by other grappling part. Docking state should be 'Grappled' but is '" + grapple.DockState + ", other grapple: " + grapple); grapple.NeedsRepair = true; } else { KmlPartDock.BuildDockStructure(grapple, part); } } else if ((part is KmlPartDock) && (part as KmlPartDock).DockType == KmlPartDock.DockTypes.Grapple) { KmlPartDock grapple = (KmlPartDock)part; if (grapple.DockUid != other.Uid) { Syntax.Warning(grapple, "Grappling part node attachment not responded from other grappled part: " + other); grapple.NeedsRepair = true; } else if (grapple.DockState.ToLower() != "grappled") { Syntax.Warning(grapple, "Grappling part grappled attached part. Docking state should be 'Grappled' but is '" + grapple.DockState + ", attached part: " + other); grapple.NeedsRepair = true; } else { KmlPartDock.BuildDockStructure(grapple, other); } } else { Syntax.Warning(part, "Part node attachment not responded from other part: " + other.ToString()); } } } else { Syntax.Warning(part, "Part supposed to be node attached to part index [" + p + "], which does not point to a valid part"); } } if (part.AttachedToSurfaceIndex >= 0 && part.AttachedToSurfaceIndex < parts.Count) { parts[part.AttachedToSurfaceIndex].AttachedPartsSurface.Add(part); } else if (part.AttachedToSurfaceIndex != -1) { Syntax.Warning(part, "Part supposed to be surface attached to part index [" + part.AttachedToSurfaceIndex + "], which does not point to a valid part"); } // Check docking (with parent involved is already checked above, here needs to e checked a 'Docked (same vessel)' // Need to check one side only, other part will be touched here in another iteration of the loop if (part is KmlPartDock) { KmlPartDock dock = (KmlPartDock)part; KmlPart other = null; foreach (KmlPart p in parts) { if (p.Uid == dock.DockUid) { other = p; break; } } if (other == null) { // This happens a lot, parts show UId 0 or some other UId they have been attached to before if (dock.DockState.ToLower() == "docked (docker)" || dock.DockState.ToLower() == "docked (dockee)" || dock.DockState.ToLower() == "docked (same vessel)" || dock.DockState.ToLower() == "grappled") { Syntax.Warning(dock, "Dock part supposed to be attached to (UId " + dock.DockUid + "), which does not point to a valid part"); dock.NeedsRepair = true; } // If it still says 'Disengage' something went wron on undocking. We can repair if undocked part is now another vessel // so other will be null because not found in this vessel // Also could be 'Disarmed', 'Disabled' etc., so it's not checked to be 'Ready'. else if (dock.DockState.ToLower() == "disengage") { Syntax.Warning(dock, "Dock part state should be 'Ready' but is '" + dock.DockState + "'"); dock.NeedsRepair = true; } } // Docking with parent already checked else if (other != dock.ParentPart && other.ParentPartIndex != i) { if (dock.DockState.ToLower() == "docked (docker)" || dock.DockState.ToLower() == "docked (dockee)" || dock.DockState.ToLower() == "docked (same vessel)" || dock.DockState.ToLower() == "grappled") { KmlPartDock.BuildDockStructure(dock, other); if (other is KmlPartDock) { KmlPartDock otherDock = (KmlPartDock)other; if (otherDock.DockUid != dock.Uid) { Syntax.Warning(dock, "Dock part docked to other dock part, but docking not responded from other side. Other dock: " + otherDock); dock.NeedsRepair = true; otherDock.NeedsRepair = true; } else if (otherDock.DockState.ToLower() == "docked (dockee)") { if (dock.DockState.ToLower() != "docked (same vessel)") { Syntax.Warning(dock, "Dock part is docked to dockee part. Docking state should be 'Docked (same vessel)' but is '" + dock.DockState + "', dockee part: " + otherDock); dock.NeedsRepair = true; otherDock.NeedsRepair = true; } } else if (otherDock.DockState.ToLower() == "docked (same vessel)") { if (dock.DockState.ToLower() != "docked (dockee)") { Syntax.Warning(dock, "Dock part is docked to same vessel docking part. Docking state should be 'Docked (dockee)' but is '" + dock.DockState + "', same vessel docking part: " + otherDock); dock.NeedsRepair = true; otherDock.NeedsRepair = true; } } else { Syntax.Warning(dock, "Dock part is docked to other dock part. Docking state should be 'Docked (same vessel)' or 'Docked (dockee)' but is '" + dock.DockState + "', other dock: " + otherDock); dock.NeedsRepair = true; otherDock.NeedsRepair = true; } } else if (dock.DockType != KmlPartDock.DockTypes.Grapple) { Syntax.Warning(dock, "Dock part is no grappling device, so it should be only docked to other dock parts, but is docked to: " + other); dock.NeedsRepair = true; } } } } } return(roots); }
private void BuildContextMenu(bool withAddMenu, bool withDeleteMenu) { ContextMenu menu = new ContextMenu(); MenuItem title = new MenuItem(); Image img = GenerateImage(DataNode); img.Margin = new Thickness(0); title.Icon = img; title.Header = DataNode.ToString(); title.IsEnabled = false; title.Background = new SolidColorBrush(Colors.Black); title.BorderThickness = new Thickness(1); title.BorderBrush = new SolidColorBrush(Colors.Gray); menu.Items.Add(title); menu.Items.Add(new Separator()); // So far it's the default Menu, wich should not be shown if no items follow int defaultMenuCount = menu.Items.Count; // Give menu item a more descriptive name string nodeName = "node"; if (DataNode is KmlResource) { nodeName = "resource"; MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "_Refill this resource"; m.Click += ResourceRefill_Click; menu.Items.Add(m); } else if (DataNode is KmlPart) { nodeName = "part"; KmlPart node = (KmlPart)DataNode; if (node.HasResources) { MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "_Refill all resources in this part"; m.Click += PartRefill_Click; menu.Items.Add(m); foreach (string resType in node.ResourceTypes) { m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "_Refill '" + resType + "' resource in this part"; m.Tag = resType; m.Click += PartRefill_Click; menu.Items.Add(m); } } if (node is KmlPartDock) { KmlPartDock dock = (KmlPartDock)node; if (dock.NeedsRepair) { if (menu.Items.Count > defaultMenuCount) { menu.Items.Add(new Separator()); } MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.PartDock); m.Header = "Re_pair docking connection of this and connected part"; m.Click += DockRepair_Click; menu.Items.Add(m); } } } else if (DataNode is KmlVessel) { nodeName = "vessel"; KmlVessel node = (KmlVessel)DataNode; MenuItem m = new MenuItem(); m.DataContext = DataNode; img = GenerateImage(DataNode); img.Margin = new Thickness(0); m.Icon = img; m.Header = "S_witch view"; m.Click += SwitchView_Click; menu.Items.Add(m); menu.Items.Add(new Separator()); m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.VesselSpaceObject); m.Header = "Send to _low kerbin orbit"; m.Click += VesselToLKO_Click; menu.Items.Add(m); if (node.HasResources) { menu.Items.Add(new Separator()); m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "_Refill all resources in all parts of this vessel"; m.Click += VesselRefill_Click; menu.Items.Add(m); foreach (string resType in node.ResourceTypes) { m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "_Refill all '" + resType + "' resources in all parts of this vessel"; m.Tag = resType; m.Click += VesselRefill_Click; menu.Items.Add(m); } } if (node.Flags.Count > 0) { menu.Items.Add(new Separator()); m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.VesselFlag); m.Header = "Change _flag in all parts of this vessel..."; m.Click += VesselFlagExchange_Click; menu.Items.Add(m); } } else if (DataNode is KmlKerbal) { nodeName = "kerbal"; KmlKerbal node = (KmlKerbal)DataNode; MenuItem m = new MenuItem(); m.DataContext = DataNode; img = GenerateImage(DataNode); img.Margin = new Thickness(0); m.Icon = img; m.Header = "S_witch view"; m.Click += SwitchView_Click; menu.Items.Add(m); if (node.AssignedVessel != null || node.AssignedPart != null) { if (menu.Items.Count > defaultMenuCount) { menu.Items.Add(new Separator()); } if (node.AssignedVessel != null) { m = new MenuItem(); m.DataContext = DataNode; img = GenerateImage(node.AssignedVessel); img.Margin = new Thickness(0); m.Icon = img; m.Header = "Select assigned _vessel: " + node.AssignedVessel.Name; m.Click += KerbalSelectAssignedVessel_Click; menu.Items.Add(m); } if (node.AssignedPart != null) { m = new MenuItem(); m.DataContext = DataNode; img = GenerateImage(node.AssignedPart); img.Margin = new Thickness(0); m.Icon = img; m.Header = "Select assigned _part: " + node.AssignedPart.Name; m.Click += KerbalSelectAssignedPart_Click; menu.Items.Add(m); } } if (node.AssignedVessel != null || node.AssignedPart != null || node.State.ToLower() == "missing") { if (menu.Items.Count > defaultMenuCount) { menu.Items.Add(new Separator()); } m = new MenuItem(); m.DataContext = DataNode; img = Icons.CreateImage(Icons.VesselSpaceObject); m.Icon = img; m.Header = "Send _home to astronaut complex"; m.Click += KerbalSendHome_Click; menu.Items.Add(m); } } // Adding / deleting if (withAddMenu) { if (menu.Items.Count > defaultMenuCount) { menu.Items.Add(new Separator()); } MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Add); m.Header = "Add _attribute..."; m.Click += NodeAddAttrib_Click; menu.Items.Add(m); m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Add); m.Header = "Add _child node..."; m.Click += NodeAddChild_Click; menu.Items.Add(m); m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Add); m.Header = "_Insert node..."; m.Click += NodeInsertBefore_Click; m.IsEnabled = DataNode.Parent != null; menu.Items.Add(m); } if (withDeleteMenu) { if (menu.Items.Count > defaultMenuCount) { menu.Items.Add(new Separator()); } MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Delete); m.Header = "_Delete this " + nodeName + "..."; m.Click += NodeDelete_Click; m.IsEnabled = DataNode.CanBeDeleted; menu.Items.Add(m); } // Need to have a seperate menu for each item, even if it is empty. // If ContextMenu is null, the parent's contextmenu will be used (WTF). // Item[0] is the menu title, Item[1] a Seperator, both always created. ContextMenu = menu; if (menu.Items.Count <= defaultMenuCount) { ContextMenu.Visibility = System.Windows.Visibility.Hidden; } else { // Apply look and feel foreach (object o in menu.Items) { if (o is MenuItem) { MenuItem m = (MenuItem)o; if (!m.IsEnabled && m.Icon != null) { (m.Icon as Image).Opacity = 0.3; } } } } }
/// <summary> /// Adds a child KmlItem to this nodes lists of children, depending of its /// derived class KmlNode, KmlPart, KmlAttrib or further derived from these. /// When an KmlAttrib "Name", "Type" or "Root" are found, their value /// will be used for the corresponding property of this node. /// </summary> /// <param name="beforeItem">The KmlItem where the new item should be inserted before</param> /// <param name="newItem">The KmlItem to add</param> protected override void Add(KmlItem beforeItem, KmlItem newItem) { if (newItem is KmlAttrib) { KmlAttrib attrib = (KmlAttrib)newItem; if (attrib.Name.ToLower() == "type" && Type.Length == 0) { Type = attrib.Value; // Get notified when Type changes attrib.AttribValueChanged += Type_Changed; attrib.CanBeDeleted = false; } else if (attrib.Name.ToLower() == "sit" && Situation.Length == 0) { Situation = attrib.Value; // Get notified when Type changes attrib.AttribValueChanged += Situation_Changed; attrib.CanBeDeleted = false; } else if (attrib.Name.ToLower() == "root" && RootPart == null) { SetRootPart(attrib.Value); // Get notified when Type changes attrib.AttribValueChanged += Root_Changed; attrib.CanBeDeleted = false; } } else if (newItem is KmlPart) { KmlPart part = (KmlPart)newItem; if (beforeItem != null) { KmlPart beforePart = null; int allIndex = AllItems.IndexOf(beforeItem); for (int i = allIndex; i < AllItems.Count; i++) { if (AllItems[i] is KmlPart && Parts.Contains((KmlPart)AllItems[i])) { beforePart = (KmlPart)AllItems[i]; break; } } if (beforePart != null) { beforePart.InsertionPreparation(); Parts.Insert(Parts.IndexOf(beforePart), part); beforePart.InsertionFinalization(); } else { Parts.Add(part); } } else { Parts.Add(part); } if (Parts.Count == rootPartIndex + 1) { RootPart = Parts[rootPartIndex]; } if (part.Flag != "" && !Flags.Any(x => x.ToLower() == part.Flag.ToLower())) { Flags.Add(part.Flag); } if (part.HasResources) { foreach (string resType in part.ResourceTypes) { ResourceTypes.Add(resType); } } KmlAttrib flag = part.GetAttrib("flag"); if (flag != null) { flag.AttribValueChanged += Flag_Changed; } } base.Add(beforeItem, newItem); }
private GuiVesselsPartGraphNode DrawPart(KmlPart part, IntPair koords) { return(DrawPart(part, koords.X, koords.Y)); }
private void BuildContextMenu() { ContextMenu menu = new ContextMenu(); MenuItem title = new MenuItem(); title.Icon = GenerateImage(DataNode); title.Header = DataNode.ToString(); title.IsEnabled = false; title.Background = new SolidColorBrush(Colors.Black); title.BorderThickness = new Thickness(1); title.BorderBrush = new SolidColorBrush(Colors.Gray); menu.Items.Add(title); menu.Items.Add(new Separator()); if (DataNode is KmlResource) { MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "Refill this resource"; m.Click += ResourceRefill_Click; menu.Items.Add(m); } else if (DataNode is KmlPart) { KmlPart node = (KmlPart)DataNode; if (node.HasResources) { MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "Refill all resources in this part"; m.Click += PartRefill_Click; menu.Items.Add(m); foreach (string resType in node.ResourceTypes) { m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "Refill '" + resType + "' resource in this part"; m.Tag = resType; m.Click += PartRefill_Click; menu.Items.Add(m); } } if (node is KmlPartDock) { KmlPartDock dock = (KmlPartDock)node; if (dock.NeedsRepair) { if (menu.Items.Count > 2) { menu.Items.Add(new Separator()); } MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.PartDock); m.Header = "Repair docking connection of this and connected part"; m.Click += DockRepair_Click; menu.Items.Add(m); } } } else if (DataNode is KmlVessel) { KmlVessel node = (KmlVessel)DataNode; if (node.HasResources) { MenuItem m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "Refill all resources in all parts of this vessel"; m.Click += VesselRefill_Click; menu.Items.Add(m); foreach (string resType in node.ResourceTypes) { m = new MenuItem(); m.DataContext = DataNode; m.Icon = Icons.CreateImage(Icons.Resource); m.Header = "Refill all '" + resType + "' resources in all parts of this vessel"; m.Tag = resType; m.Click += VesselRefill_Click; menu.Items.Add(m); } } } // Need to have a seperate menu for each item, even if it is empty. // If ContextMenu is null, the parent's contextmenu will be used (WTF). // Item[0] is the menu title, Item[1] a Seperator, both always created. ContextMenu = menu; if (menu.Items.Count < 3) { ContextMenu.Visibility = System.Windows.Visibility.Hidden; } }
/// <summary> /// Repair the docking connection of this port. /// </summary> public void Repair() { // Two docks if (DockType == DockTypes.Dock) { if (DockedPart == null) { if (Parent is KmlVessel) { KmlVessel vessel = (KmlVessel)Parent; int myIndex = vessel.Parts.IndexOf(this); for (int i = 0; i < vessel.Parts.Count; i++) { KmlPart part = vessel.Parts[i]; if (part is KmlPartDock) { KmlPartDock otherDock = (KmlPartDock)part; if (otherDock.DockedPart == this) { // This will choose the right docker / dockee or switch to same vessel if none is parent RepairDockerChoose(this, otherDock); return; } else if (otherDock.ParentPart == this || ParentPart == otherDock) { if (AttachedToSurfaceIndex == i || AttachedToNodeIndices.Contains(i) || otherDock.AttachedToSurfaceIndex == myIndex || otherDock.AttachedToNodeIndices.Contains(myIndex)) { // It's attached and not docked continue; } else { RepairDockerChoose(this, otherDock); return; } } } } // To avoid getting to here there are returns spread above // Syntax.Warning(this, "Didn't find another part in all parts of the vessel to fix this dock with"); RepairClearDocking(this); } else { Syntax.Warning(this, "Could not search for connected parts, parent vessel is not valid"); } } else if (!(DockedPart is KmlPartDock)) { Syntax.Warning(this, "Don't know how to repair this docking connection, this one is no dock: " + DockedPart); } else { KmlPartDock otherDock = (KmlPartDock)DockedPart; if (otherDock.DockedPart == this || otherDock.ParentPart == this || ParentPart == otherDock) { // They are already linked but there's something to fix unless context menu to this wouldn't be enabled // This will choose the right docker / dockee or switch to same vessel if none is parent RepairDockerChoose(this, otherDock); } else { // Semi-functional same vessel docking would be fixed above, this is no docking RepairClearDocking(this); } } } // One dock and another part else if (DockType == DockTypes.Grapple) { if (DockedPart == null) { if (Parent is KmlVessel) { KmlVessel vessel = (KmlVessel)Parent; int myIndex = vessel.Parts.IndexOf(this); for (int i = 0; i < vessel.Parts.Count; i++) { KmlPart part = vessel.Parts[i]; if (part.ParentPart == this || this.ParentPart == part) { if (AttachedToSurfaceIndex == i || AttachedToNodeIndices.Contains(i) || part.AttachedToSurfaceIndex == myIndex || part.AttachedToNodeIndices.Contains(myIndex)) { // It's attached and not grappled continue; } else { RepairGrappling(this, part); return; } } } // To avoid getting to here there are returns spread above // Syntax.Warning(this, "Didn't find another part in all parts of the vessel to fix this grappling device with"); RepairClearDocking(this); } else { Syntax.Warning(this, "Could not search for connected parts, parent vessel is not valid"); } } else { if (DockedPart.ParentPart == this || ParentPart == DockedPart) { RepairGrappling(this, DockedPart); } else { RepairClearDocking(this); } } } }
private void DrawConnectedParts(GuiVesselsPartGraphNode parent, IntPair parentKoords) { KmlPart parentPart = parent.DataPart; IntPair newKoords; // Top atteched parts foreach (KmlPart sub in parentPart.AttachedPartsTop) { if (!sub.Visited) { newKoords = CalcKoords(parentKoords, parentKoords.X, parentKoords.Y - CountBottom(sub, parentPart) - CountTop(parentPart, parentPart) + 1); for (int y = parentKoords.Y - 1; y > newKoords.Y; y--) { // Fill space with dummy nodes InsertGrid(parentKoords.X, y, new GuiVesselsPartGraphNode(parentKoords.X, y)); } DrawPartAndConnected(sub, newKoords, parentKoords, ConnectVerticalBrush); } else { DrawConnectionAndSeachPart(sub, parentKoords, ConnectVerticalBrush); } } // Bottom atteched parts foreach (KmlPart sub in parentPart.AttachedPartsBottom) { if (!sub.Visited) { newKoords = CalcKoords(parentKoords, parentKoords.X, parentKoords.Y + CountTop(sub, parentPart) + CountBottom(parentPart, parentPart) - 1); for (int y = parentKoords.Y + 1; y < newKoords.Y; y++) { // Fill space with dummy nodes InsertGrid(parentKoords.X, y, new GuiVesselsPartGraphNode(parentKoords.X, y)); } DrawPartAndConnected(sub, newKoords, parentKoords, ConnectVerticalBrush); } else { DrawConnectionAndSeachPart(sub, parentKoords, ConnectVerticalBrush); } } // Left atteched parts foreach (KmlPart sub in parentPart.AttachedPartsLeft) { if (!sub.Visited) { newKoords = CalcKoords(parentKoords, parentKoords.X - 2, parentKoords.Y); DrawPartAndConnected(sub, newKoords, parentKoords, ConnectSidesBrush); } else { DrawConnectionAndSeachPart(sub, parentKoords, ConnectSidesBrush); } } // Right atteched parts foreach (KmlPart sub in parentPart.AttachedPartsRight) { if (!sub.Visited) { newKoords = CalcKoords(parentKoords, parentKoords.X + 2, parentKoords.Y); DrawPartAndConnected(sub, newKoords, parentKoords, ConnectSidesBrush); } else { DrawConnectionAndSeachPart(sub, parentKoords, ConnectSidesBrush); } } // Back atteched parts foreach (KmlPart sub in parentPart.AttachedPartsBack) { if (!sub.Visited) { newKoords = CalcKoords(parentKoords, parentKoords.X - 2, parentKoords.Y - 1); DrawPartAndConnected(sub, newKoords, parentKoords, ConnectSidesBrush); } else { DrawConnectionAndSeachPart(sub, parentKoords, ConnectSidesBrush); } } // Front atteched parts foreach (KmlPart sub in parentPart.AttachedPartsFront) { if (!sub.Visited) { newKoords = CalcKoords(parentKoords, parentKoords.X + 2, parentKoords.Y + 1); DrawPartAndConnected(sub, newKoords, parentKoords, ConnectSidesBrush); } else { DrawConnectionAndSeachPart(sub, parentKoords, ConnectSidesBrush); } } // Surface atteched parts int i = 0; foreach (KmlPart sub in parentPart.AttachedPartsSurface) { if (!sub.Visited) { // Arrange alternating left and right do { if (i % 4 == 0) { newKoords = new IntPair(parentKoords.X - (i / 4 + 1), parentKoords.Y - 1); } else if (i % 4 == 1) { newKoords = new IntPair(parentKoords.X + (i / 4 + 1), parentKoords.Y - 1); } else if (i % 4 == 2) { newKoords = new IntPair(parentKoords.X - (i / 4 + 1), parentKoords.Y + 1); } else { newKoords = new IntPair(parentKoords.X + (i / 4 + 1), parentKoords.Y + 1); } i++; }while (!InsertGrid(newKoords.X, newKoords.Y, null)); DrawPartAndConnected(sub, newKoords, parentKoords, ConnectSurfaceBrush); } else { DrawConnectionAndSeachPart(sub, parentKoords, ConnectSurfaceBrush); i++; } } // Docked parts if (parentPart is KmlPartDock) { KmlPartDock dock = (KmlPartDock)parentPart; KmlPart sub = dock.DockedPart; if (sub != null) { if (!sub.Visited) { newKoords = CalcKoords(parentKoords, parentKoords.X + (sub.Position.X > parentPart.Position.X ? 1 : -1), parentKoords.Y + (sub.Position.Y > parentPart.Position.Y ? 1 : -1)); DrawPartAndConnected(sub, newKoords, parentKoords, ConnectDockBrush); } else { DrawConnectionAndSeachPart(sub, parentKoords, ConnectDockBrush); } } } }
private static void RepairGrappling(KmlPartDock grapple, KmlPart part) { int grappleIndex = -1; int partIndex = -1; if (grapple.Parent is KmlVessel) { bool dockedVesselOk = true; KmlVessel vessel = (KmlVessel)grapple.Parent; grappleIndex = vessel.Parts.IndexOf(grapple); partIndex = vessel.Parts.IndexOf(part); try { KmlNode module = grapple.GetOrCreateChildNode("MODULE", "ModuleGrappleNode"); module.GetOrCreateAttrib("isEnabled", "True"); //module.GetOrCreateAttrib("stagingEnabled").Value = "False"; // True?!? module.GetOrCreateAttrib("state").Value = "Grappled"; module.GetOrCreateAttrib("dockUId").Value = part.Uid; KmlNode events = module.GetOrCreateChildNode("EVENTS"); events.GetOrCreateChildNode("Release").GetOrCreateAttrib("active").Value = "True"; events.GetOrCreateChildNode("ReleaseSameVessel").GetOrCreateAttrib("active").Value = "False"; events.GetOrCreateChildNode("Decouple").GetOrCreateAttrib("active").Value = "False"; module.GetOrCreateChildNode("ACTIONS"); KmlNode dockedVessel = module.GetOrCreateChildNode("DOCKEDVESSEL"); KmlNode dockedVesselOther = module.GetOrCreateChildNode("DOCKEDVESSEL_Other"); string vesselName; string vesselRootUId; string defaultName; if (grapple.Parent is KmlVessel) { vesselName = (grapple.Parent as KmlVessel).Name; vesselRootUId = (grapple.Parent as KmlVessel).RootPart.Uid; defaultName = vesselName + " Grappled - repaired by KML"; } else { vesselName = "Unknown Vessel - repaired by KML"; if (part.ParentPart == grapple) { vesselRootUId = grapple.Uid; } else { vesselRootUId = part.Uid; } defaultName = "Unknown Grappled - repaired by KML"; } string thisName; string otherName; string thisUid; string otherUid; if (part.ParentPart == grapple) { thisName = vesselName; thisUid = vesselRootUId; otherName = defaultName; otherUid = part.Uid; } else { thisName = defaultName; thisUid = grapple.Uid; otherName = vesselName; otherUid = vesselRootUId; } if (dockedVessel.GetAttrib("vesselName") == null) { KmlAttrib attrib = dockedVessel.GetOrCreateAttrib("vesselName", thisName); attrib.AttribValueChanged += grapple.DockedVesselName_Changed; grapple.DockedVesselName_Changed(attrib, new System.Windows.RoutedEventArgs()); } if (dockedVessel.GetAttrib("vesselType") == null) { KmlAttrib attrib = dockedVessel.GetOrCreateAttrib("vesselType", "6"); attrib.AttribValueChanged += grapple.DockedVesselType_Changed; grapple.DockedVesselType_Changed(attrib, new System.Windows.RoutedEventArgs()); } dockedVessel.GetOrCreateAttrib("rootUId", thisUid); if (dockedVesselOther.GetAttrib("vesselName") == null) { KmlAttrib attrib = dockedVesselOther.GetOrCreateAttrib("vesselName", otherName); attrib.AttribValueChanged += grapple.DockedVesselOtherName_Changed; grapple.DockedVesselOtherName_Changed(attrib, new System.Windows.RoutedEventArgs()); } if (dockedVesselOther.GetAttrib("vesselType") == null) { KmlAttrib attrib = dockedVesselOther.GetOrCreateAttrib("vesselType", "6"); attrib.AttribValueChanged += grapple.DockedVesselOtherType_Changed; grapple.DockedVesselOtherType_Changed(attrib, new System.Windows.RoutedEventArgs()); } dockedVesselOther.GetOrCreateAttrib("rootUId", otherUid); module = grapple.GetOrCreateChildNode("MODULE", "ModuleAnimateGeneric"); module.GetOrCreateAttrib("animSwitch").Value = "False"; module.GetOrCreateAttrib("animTime").Value = "1"; events = module.GetOrCreateChildNode("EVENTS"); KmlNode toggle = events.GetOrCreateChildNode("Toggle"); toggle.GetOrCreateAttrib("active").Value = "False"; toggle.GetOrCreateAttrib("guiName").Value = "Disarm"; if (part.ParentPart == grapple) { RepairGrappleAttachment(part, grappleIndex); } else if (grapple.ParentPart == part) { RepairGrappleAttachment(grapple, partIndex); } else { // TODO KmlPartDock:RepairGrappling(): Is there a 'Grappled (same vessel)'? } if (dockedVesselOk) { Syntax.Info(grapple, "Successfully repaired grappling"); BuildAttachmentStructure(vessel.Parts); } } catch (NullReferenceException) { Syntax.Warning(grapple, "Couldn't fix grappling node, there are sub-nodes missing.\n" + "You should copy a MODULE node from a functional state 'Grappled' part\n" + "grappled part should be: " + part); } } else { Syntax.Warning(grapple, "Could not search for connected parts, parent vessel is not valid"); } }
/// <summary> /// Creates a KmlPartDock as a copy of a given KmlPart. /// </summary> /// <param name="part">The KmlPart to copy</param> public KmlPartDock(KmlPart part) : base(part) { DockType = DockTypes.Dock; DockName = ""; DockState = ""; DockedVesselName = ""; DockedVesselType = ""; DockedVesselOtherName = ""; DockedVesselOtherType = ""; DockUid = ""; DockedPart = null; NeedsRepair = false; foreach (KmlNode node in Children) { if (node.Tag.ToLower() == "module" && (node.Name.ToLower() == "moduledockingnode" || node.Name.ToLower() == "modulegrapplenode" || node.Name.ToLower() == "kasmodulestrut")) { if (node.Name.ToLower() == "modulegrapplenode") { DockType = DockTypes.Grapple; } else if (node.Name.ToLower() == "kasmodulestrut") { DockType = DockTypes.KasCPort; } foreach (KmlAttrib attrib in node.Attribs) { if (attrib.Name.ToLower() == "state") { DockState = attrib.Value; attrib.AttribValueChanged += DockState_Changed; attrib.CanBeDeleted = false; } else if (attrib.Name.ToLower() == "dockuid") { DockUid = attrib.Value; attrib.AttribValueChanged += DockUid_Changed; attrib.CanBeDeleted = false; } else if (DockType == DockTypes.KasCPort && attrib.Name.ToLower() == "dockedpartid") { DockUid = attrib.Value; attrib.AttribValueChanged += DockUid_Changed; attrib.CanBeDeleted = false; } } foreach (KmlNode subnode in node.Children) { if (subnode.Tag.ToLower() == "dockedvessel") { foreach (KmlAttrib attrib in subnode.Attribs) { if (attrib.Name.ToLower() == "vesselname") { DockedVesselName = attrib.Value; attrib.AttribValueChanged += DockedVesselName_Changed; attrib.CanBeDeleted = false; } else if (attrib.Name.ToLower() == "vesseltype") { DockedVesselType = TranslateDockedVesselType(attrib.Value); attrib.AttribValueChanged += DockedVesselType_Changed; attrib.CanBeDeleted = false; } } } // Grapple-links with grapplingdevice on master side // (the one that's name survived) need to read "dockedvessel_other" to get slave side name else if (subnode.Tag.ToLower() == "dockedvessel_other") { foreach (KmlAttrib attrib in subnode.Attribs) { if (attrib.Name.ToLower() == "vesselname") { DockedVesselOtherName = attrib.Value; attrib.AttribValueChanged += DockedVesselOtherName_Changed; attrib.CanBeDeleted = false; } else if (attrib.Name.ToLower() == "vesseltype") { DockedVesselOtherType = TranslateDockedVesselType(attrib.Value); attrib.AttribValueChanged += DockedVesselOtherType_Changed; attrib.CanBeDeleted = false; } } } } } else if (node.Tag.ToLower() == "module" && node.Name.ToLower() == "moduledockingnodenamed") { foreach (KmlAttrib attrib in node.Attribs) { if (attrib.Name.ToLower() == "portname") { DockName = attrib.Value; attrib.AttribValueChanged += DockName_Changed; attrib.CanBeDeleted = false; } } } } }
/// <summary> /// Adds a child KmlItem to this nodes lists of children, depending of its /// derived class KmlNode, KmlPart, KmlAttrib or further derived from these. /// When an KmlAttrib "Name", "Type" or "Root" are found, their value /// will be used for the corresponding property of this node. /// </summary> /// <param name="item">The KmlItem to add</param> public override void Add(KmlItem item) { KmlItem newItem = item; if (item is KmlAttrib) { KmlAttrib attrib = (KmlAttrib)item; if (attrib.Name.ToLower() == "type") { Type = attrib.Value; // Get notified when Type changes attrib.AttribValueChanged += Type_Changed; attrib.CanBeDeleted = false; } else if (attrib.Name.ToLower() == "sit") { Situation = attrib.Value; // Get notified when Type changes attrib.AttribValueChanged += Situation_Changed; attrib.CanBeDeleted = false; } else if (attrib.Name.ToLower() == "root") { SetRootPart(attrib.Value); // Get notified when Type changes attrib.AttribValueChanged += Root_Changed; attrib.CanBeDeleted = false; } } else if (item is KmlPart) { KmlPart part = (KmlPart)item; Parts.Add(part); if (Parts.Count == rootPartIndex + 1) { RootPart = Parts[rootPartIndex]; } if (part.HasResources) { foreach (string resType in part.ResourceTypes) { ResourceTypes.Add(resType); } } } /*else if (Item is KmlNode) * { * KmlNode node = (KmlNode)Item; * if (node.Tag.ToLower() == "part") * { * newItem = new KmlPart(node); * Parts.Add((KmlPart)newItem); * if (Parts.Count == rootPartNr + 1) * { * RootPart = Parts[rootPartNr]; * } * } * }*/ base.Add(newItem); }
private static void RepairGrappling(KmlPartDock grapple, KmlPart part) { int grappleIndex = -1; int partIndex = -1; if (grapple.Parent == null || !(grapple.Parent is KmlVessel)) { System.Windows.MessageBox.Show("Could not search for connected parts, parent vessel is not valid"); } else { bool dockedVesselOk = true; KmlVessel vessel = (KmlVessel)grapple.Parent; grappleIndex = vessel.Parts.IndexOf(grapple); partIndex = vessel.Parts.IndexOf(part); try { KmlNode module = grapple.GetChildNode("MODULE", "ModuleGrappleNode"); module.GetAttrib("state").Value = "Grappled"; module.GetAttrib("dockUId").Value = part.Uid; KmlNode events = module.GetChildNode("EVENTS"); events.GetChildNode("Release").GetAttrib("active").Value = "True"; events.GetChildNode("ReleaseSameVessel").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 file."); dockedVesselOk = false; } if (module.GetChildNode("DOCKEDVESSEL_other") == null) { System.Windows.MessageBox.Show("Couldn't find sub-node DOCKEDVESSEL_other, you should try to copy it from older save file."); dockedVesselOk = false; } module = grapple.GetChildNode("MODULE", "ModuleAnimateGeneric"); module.GetAttrib("animSwitch").Value = "False"; module.GetAttrib("animTime").Value = "1"; events = module.GetChildNode("EVENTS"); KmlNode toggle = events.GetChildNode("Toggle"); toggle.GetAttrib("active").Value = "False"; toggle.GetAttrib("guiName").Value = "Disarm"; if (part.ParentPart == grapple) { RepairGrappleAttachment(part, grappleIndex); } else if (grapple.ParentPart == part) { RepairGrappleAttachment(grapple, partIndex); } else { // TODO KmlPartDock:RepairGrappling(): Is there a 'Grappled (same vessel)'? } if (dockedVesselOk) { // Maybe RepairGrappleAttachment() will cause a message to save and reload System.Windows.MessageBox.Show("Successfully repaired grappling. Please save and reload to see the rebuilt part structure."); // TODO KmlPartDock:RepairGrappling(): Refresh structure without save / reload } } catch (NullReferenceException) { System.Windows.MessageBox.Show("Couldn't fix grappling node, there are sub-nodes missing.\n" + "You should copy a MODULE node from a functional state 'Grappled' part.\n" + "grappled part should be: " + part); } } }