private void ExportChildNodes(EditorNode startNode, XElement parent) { XElement?newElement = startNode.ToXML(); if (newElement == null) { return; } parent.Add(newElement); EditorNode?success = startNode.GetNext(NodeConnectionType.Success); EditorNode?failure = startNode.GetNext(NodeConnectionType.Failure); EditorNode?add = startNode.GetNext(NodeConnectionType.Add); Tuple <EditorNode?, string?, bool>[] options = startNode is EventNode eNode?eNode.GetOptions() : new Tuple <EditorNode?, string?, bool> [0]; if (success != null) { XElement successElement = new XElement("Success"); ExportChildNodes(success, successElement); newElement.Add(successElement); } if (failure != null) { XElement failureElement = new XElement("Failure"); ExportChildNodes(failure, failureElement); newElement.Add(failureElement); } if (add is CustomNode custom) { ExportChildNodes(custom, newElement); } foreach (var(node, text, end) in options) { XElement optionElement = new XElement("Option"); optionElement.Add(new XAttribute("text", text)); if (end) { optionElement.Add(new XAttribute("endconversation", true)); } if (node != null) { ExportChildNodes((EventNode)node, optionElement); } newElement.Add(optionElement); } EditorNode?next = startNode.GetNext(); if (next != null) { ExportChildNodes(next, parent); } }
private void CreateContextMenu(EditorNode node, NodeConnection?connection = null) { if (GUIContextMenu.CurrentContextMenu != null) { return; } GUIContextMenu.CreateContextMenu( new ContextMenuOption("EventEditor.Edit", isEnabled: node is ValueNode || connection?.Type == NodeConnectionType.Value || connection?.Type == NodeConnectionType.Option, onSelected: delegate { CreateEditMenu(node as ValueNode, connection); }), new ContextMenuOption("EventEditor.MarkEnding", isEnabled: connection != null && connection.Type == NodeConnectionType.Option, onSelected: delegate { if (connection == null) { return; } connection.EndConversation = !connection.EndConversation; }), new ContextMenuOption("EventEditor.RemoveConnection", isEnabled: connection != null, onSelected: delegate { if (connection == null) { return; } connection.ClearConnections(); connection.OverrideValue = null; connection.OptionText = connection.OptionText; }), new ContextMenuOption("EventEditor.AddOption", isEnabled: node.CanAddConnections, onSelected: node.AddOption), new ContextMenuOption("EventEditor.RemoveOption", isEnabled: connection != null && node.RemovableTypes.Contains(connection.Type), onSelected: delegate { connection?.Parent.RemoveOption(connection); }), new ContextMenuOption("EventEditor.Delete", isEnabled: true, onSelected: delegate { nodeList.Remove(node); node.ClearConnections(); })); }
private void Load(XElement saveElement) { nodeList.Clear(); projectName = saveElement.GetAttributeString("name", TextManager.Get("EventEditor.Unnamed")); foreach (XElement element in saveElement.Elements()) { switch (element.Name.ToString().ToLowerInvariant()) { case "nodes": { foreach (XElement subElement in element.Elements()) { EditorNode?node = EditorNode.Load(subElement); if (node != null) { nodeList.Add(node); } } break; } case "allconnections": { foreach (XElement subElement in element.Elements()) { int id = subElement.GetAttributeInt("i", -1); EditorNode?node = nodeList.Find(editorNode => editorNode.ID == id); node?.LoadConnections(subElement); } break; } } } }
private void CreateContextMenu(EditorNode node, NodeConnection?connection = null) { contextMenu = new GUIListBox(new RectTransform(new Vector2(0.1f, 0.1f), GUI.Canvas) { ScreenSpaceOffset = PlayerInput.MousePosition.ToPoint() }, style: "GUIToolTip") { Padding = new Vector4(5) }; new GUITextBlock(new RectTransform(Point.Zero, contextMenu.Content.RectTransform), TextManager.Get("EventEditor.Edit"), font: GUI.SmallFont) { UserData = "edit", Enabled = node is ValueNode || connection?.Type == NodeConnectionType.Value || connection?.Type == NodeConnectionType.Option }; new GUITextBlock(new RectTransform(Point.Zero, contextMenu.Content.RectTransform), TextManager.Get("EventEditor.MarkEnding"), font: GUI.SmallFont) { UserData = "markend", Enabled = connection != null && connection.Type == NodeConnectionType.Option }; new GUITextBlock(new RectTransform(Point.Zero, contextMenu.Content.RectTransform), TextManager.Get("EventEditor.RemoveConnection"), font: GUI.SmallFont) { UserData = "remcon", Enabled = connection != null }; new GUITextBlock(new RectTransform(Point.Zero, contextMenu.Content.RectTransform), TextManager.Get("EventEditor.AddOption"), font: GUI.SmallFont) { UserData = "addoption", Enabled = node.CanAddConnections }; new GUITextBlock(new RectTransform(Point.Zero, contextMenu.Content.RectTransform), TextManager.Get("EventEditor.RemoveOption"), font: GUI.SmallFont) { UserData = "removeoption", Enabled = connection != null && node.RemovableTypes.Contains(connection.Type) }; new GUITextBlock(new RectTransform(Point.Zero, contextMenu.Content.RectTransform), TextManager.Get("EventEditor.Delete"), font: GUI.SmallFont) { UserData = "delete", Enabled = true }; foreach (var guiComponent in contextMenu.Content.Children) { if (guiComponent is GUITextBlock child) { if (!child.Enabled) { child.TextColor *= 0.5f; } } } foreach (GUIComponent c in contextMenu.Content.Children) { if (c is GUITextBlock block) { block.RectTransform.NonScaledSize = new Point((int)(block.TextSize.X + block.Padding.X * 2), (int)(18 * GUI.Scale)); } } int biggestSize = contextMenu.Content.Children.Max(c => c.Rect.Width + (int)contextMenu.Padding.X * 2); contextMenu.Content.Children.ForEach(c => c.RectTransform.MinSize = new Point(biggestSize, c.Rect.Height)); contextMenu.RectTransform.NonScaledSize = new Point(biggestSize, (int)(contextMenu.Content.Children.Sum(c => c.Rect.Height) + (contextMenu.Padding.X * 2))); contextMenu.OnSelected = (component, obj) => { if (!component.Enabled) { return(false); } switch (obj as string) { case "edit": CreateEditMenu(node as ValueNode, connection); break; case "markend" when connection != null: connection.EndConversation = !connection.EndConversation; break; case "remcon" when connection != null: connection.ClearConnections(); connection.OverrideValue = null; connection.OptionText = connection.OptionText; break; case "addoption": node.AddOption(); break; case "removeoption": connection?.Parent.RemoveOption(connection); break; case "delete": nodeList.Remove(node); node.ClearConnections(); break; } contextMenu = null; return(true); }; }
private void CreateNodes(XElement element, ref bool hadNodes, EditorNode?parent = null, int ident = 0) { EditorNode?lastNode = null; foreach (XElement subElement in element.Elements()) { bool skip = true; switch (subElement.Name.ToString().ToLowerInvariant()) { case "failure": case "success": case "option": CreateNodes(subElement, ref hadNodes, parent, ident); break; default: skip = false; break; } if (!skip) { Vector2 defaultNodePos = new Vector2(-16000, -16000); EditorNode newNode; Type? t = Type.GetType($"Barotrauma.{subElement.Name}"); if (t != null && EditorNode.IsInstanceOf(t, typeof(EventAction))) { newNode = new EventNode(t, subElement.Name.ToString()) { Position = new Vector2(ident, 0), ID = CreateID() }; } else { newNode = new CustomNode(subElement.Name.ToString()) { Position = new Vector2(ident, 0), ID = CreateID() }; foreach (XAttribute attribute in subElement.Attributes()) { newNode.Connections.Add(new NodeConnection(newNode, NodeConnectionType.Value, attribute.Name.ToString(), typeof(string))); } } Vector2 npos = subElement.GetAttributeVector2("_npos", defaultNodePos); if (npos != defaultNodePos) { newNode.Position = npos; } else { hadNodes = false; } XElement?parentElement = subElement.Parent; foreach (XElement xElement in subElement.Elements()) { if (xElement.Name.ToString().ToLowerInvariant() == "option") { NodeConnection optionConnection = new NodeConnection(newNode, NodeConnectionType.Option) { OptionText = xElement.GetAttributeString("text", string.Empty), EndConversation = xElement.GetAttributeBool("endconversation", false) }; newNode.Connections.Add(optionConnection); } } foreach (NodeConnection connection in newNode.Connections) { if (connection.Type == NodeConnectionType.Value) { foreach (XAttribute attribute in subElement.Attributes()) { if (string.Equals(connection.Attribute, attribute.Name.ToString(), StringComparison.InvariantCultureIgnoreCase) && connection.ValueType != null) { if (connection.ValueType.IsEnum) { Array values = Enum.GetValues(connection.ValueType); foreach (object? @enum in values) { if (string.Equals(@enum?.ToString(), attribute.Value, StringComparison.InvariantCultureIgnoreCase)) { connection.OverrideValue = @enum; } } } else { connection.OverrideValue = Convert.ChangeType(attribute.Value, connection.ValueType); } } } } } if (npos == defaultNodePos) { hadNodes = false; bool Predicate(EditorNode node) => Rectangle.Union(node.GetDrawRectangle(), node.HeaderRectangle).Intersects(Rectangle.Union(newNode.GetDrawRectangle(), newNode.HeaderRectangle)); while (nodeList.Any(Predicate)) { EditorNode?otherNode = nodeList.Find(Predicate); if (otherNode != null) { newNode.Position += new Vector2(128, otherNode.GetDrawRectangle().Height + otherNode.HeaderRectangle.Height + new Random().Next(128, 256)); } } } if (parentElement?.FirstElement() == subElement) { switch (parentElement?.Name.ToString().ToLowerInvariant()) { case "failure": parent?.Connect(newNode, NodeConnectionType.Failure); break; case "success": parent?.Connect(newNode, NodeConnectionType.Success); break; case "option": if (parent != null) { NodeConnection?activateConnection = newNode.Connections.Find(connection => connection.Type == NodeConnectionType.Activate); NodeConnection?optionConnection = parent.Connections.FirstOrDefault(connection => connection.Type == NodeConnectionType.Option && string.Equals(connection.OptionText, parentElement.GetAttributeString("text", string.Empty), StringComparison.Ordinal)); if (activateConnection != null) { optionConnection?.ConnectedTo.Add(activateConnection); } } break; default: parent?.Connect(newNode, NodeConnectionType.Add); break; } } else { lastNode?.Connect(newNode, NodeConnectionType.Next); } lastNode = newNode; nodeList.Add(newNode); ident += 600; CreateNodes(subElement, ref hadNodes, newNode, ident); } else { } } }