670 lines
26 KiB
C#
670 lines
26 KiB
C#
#nullable enable
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Xml.Linq;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
internal class EditorNode
|
|
{
|
|
public Vector2 Position { get; set; }
|
|
|
|
public Vector2 Size { get; set; }
|
|
|
|
public int ID;
|
|
|
|
private const int HeaderSize = 32;
|
|
|
|
public Rectangle HeaderRectangle => new Rectangle(Position.ToPoint(), new Point((int) Size.X, HeaderSize));
|
|
public Rectangle Rectangle => new Rectangle(new Point((int) Position.X, (int) Position.Y + HeaderSize), Size.ToPoint());
|
|
public string Name { get; protected set; }
|
|
|
|
public bool CanAddConnections { get; set; }
|
|
|
|
public readonly List<EventEditorNodeConnection> Connections = new List<EventEditorNodeConnection>();
|
|
|
|
public readonly List<NodeConnectionType> RemovableTypes = new List<NodeConnectionType>();
|
|
|
|
public bool IsHighlighted;
|
|
|
|
public bool IsSelected;
|
|
|
|
protected EditorNode(string name)
|
|
{
|
|
Name = name;
|
|
Position = Vector2.Zero;
|
|
}
|
|
|
|
public virtual XElement Save()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public XElement SaveConnections()
|
|
{
|
|
XElement allConnections = new XElement("Connections", new XAttribute("i", ID));
|
|
foreach (EventEditorNodeConnection connection in Connections)
|
|
{
|
|
XElement connectionElement = new XElement("Connection");
|
|
connectionElement.Add(new XAttribute("i", connection.ID));
|
|
connectionElement.Add(new XAttribute("type", connection.Type.Label));
|
|
|
|
if (connection.EndConversation)
|
|
{
|
|
connectionElement.Add(new XAttribute("endconversation", connection.EndConversation));
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(connection.OptionText))
|
|
{
|
|
connectionElement.Add(new XAttribute("optiontext", connection.OptionText));
|
|
}
|
|
|
|
if (connection.OverrideValue is { } overrideValue && !string.IsNullOrWhiteSpace(connection.OverrideValue?.ToString()))
|
|
{
|
|
connectionElement.Add(new XAttribute("overridevalue", overrideValue.ToString() ?? string.Empty));
|
|
connectionElement.Add(new XAttribute("valuetype", overrideValue.GetType().ToString()));
|
|
}
|
|
|
|
foreach (var nodeConnection in connection.ConnectedTo)
|
|
{
|
|
XElement connectedTo = new XElement("ConnectedTo",
|
|
new XAttribute("i", nodeConnection.ID),
|
|
new XAttribute("node", nodeConnection.Parent.ID));
|
|
connectionElement.Add(connectedTo);
|
|
}
|
|
|
|
allConnections.Add(connectionElement);
|
|
}
|
|
|
|
return allConnections;
|
|
}
|
|
|
|
public void LoadConnections(XElement element)
|
|
{
|
|
foreach (var subElement in element.Elements())
|
|
{
|
|
int id = subElement.GetAttributeInt("i", -1);
|
|
string? connectionType = subElement.GetAttributeString("type", null);
|
|
bool endConversation = subElement.GetAttributeBool("endconversation", false);
|
|
|
|
if (id < 0) { continue; }
|
|
|
|
EventEditorNodeConnection? connection = Connections.Find(c => c.ID == id);
|
|
if (connection == null)
|
|
{
|
|
if (string.Equals(connectionType, NodeConnectionType.Option.Label, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
connection = new EventEditorNodeConnection(this, NodeConnectionType.Option) { ID = id, EndConversation = endConversation };
|
|
Connections.Add(connection);
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
string? optionText = subElement.GetAttributeString("optiontext", null);
|
|
string? overrideValue = subElement.GetAttributeString("overridevalue", null);
|
|
string? valueType = subElement.GetAttributeString("valuetype", null);
|
|
|
|
if (optionText != null) { connection.OptionText = optionText; }
|
|
|
|
if (overrideValue != null && valueType != null)
|
|
{
|
|
Type? type = Type.GetType(valueType);
|
|
if (type != null)
|
|
{
|
|
if (type.IsEnum)
|
|
{
|
|
Array enums = Enum.GetValues(type);
|
|
foreach (object? @enum in enums)
|
|
{
|
|
if (string.Equals(@enum?.ToString(), overrideValue, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
connection.OverrideValue = @enum;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
connection.OverrideValue = EventEditorScreen.ChangeType(overrideValue, type);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (XElement connectedTo in subElement.Elements())
|
|
{
|
|
int id2 = connectedTo.GetAttributeInt("i", -1);
|
|
int node = connectedTo.GetAttributeInt("node", -1);
|
|
if (id2 < 0 || node < 0) { continue; }
|
|
|
|
EditorNode? otherNode = EventEditorScreen.nodeList.Find(editorNode => editorNode.ID == node);
|
|
EventEditorNodeConnection? otherConnection = otherNode?.Connections.Find(c => c.ID == id2);
|
|
if (otherConnection != null)
|
|
{
|
|
connection.ConnectedTo.Add(otherConnection);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static EditorNode? Load(XElement element)
|
|
{
|
|
return element.Name.ToString().ToLowerInvariant() switch
|
|
{
|
|
"eventnode" => EventNode.LoadEventNode(element),
|
|
"valuenode" => ValueNode.LoadValueNode(element),
|
|
"customnode" => CustomNode.LoadCustomNode(element),
|
|
_ => null
|
|
};
|
|
}
|
|
|
|
public virtual XElement? ToXML()
|
|
{
|
|
XElement newElement = new XElement(Name);
|
|
foreach (var connection in Connections)
|
|
{
|
|
if (connection.Type == NodeConnectionType.Value)
|
|
{
|
|
if (connection.GetValue() is { } connValue)
|
|
{
|
|
newElement.Add(new XAttribute(connection.Attribute.ToLowerInvariant(), connValue));
|
|
}
|
|
}
|
|
}
|
|
|
|
newElement.Add(new XAttribute("_npos", XMLExtensions.Vector2ToString(Position)));
|
|
|
|
return newElement;
|
|
}
|
|
|
|
public void Connect(EditorNode otherNode, NodeConnectionType type)
|
|
{
|
|
EventEditorNodeConnection? conn = Connections.Find(connection => connection.Type == type && !connection.ConnectedTo.Any());
|
|
EventEditorNodeConnection? found = otherNode.Connections.Find(connection => connection.Type == NodeConnectionType.Activate);
|
|
if (found != null)
|
|
{
|
|
conn?.ConnectedTo.Add(found);
|
|
}
|
|
}
|
|
|
|
public static void Connect(EventEditorNodeConnection connection, EventEditorNodeConnection ownConnection)
|
|
{
|
|
connection.ConnectedTo.Add(ownConnection);
|
|
}
|
|
|
|
public static void Disconnect(EventEditorNodeConnection conn)
|
|
{
|
|
foreach (var connection in EventEditorScreen.nodeList.SelectMany(editorNode => editorNode.Connections.Where(connection => connection.ConnectedTo.Contains(conn))))
|
|
{
|
|
connection.ConnectedTo.Remove(conn);
|
|
}
|
|
}
|
|
|
|
public void ClearConnections()
|
|
{
|
|
foreach (EventEditorNodeConnection conn in Connections)
|
|
{
|
|
conn.ClearConnections();
|
|
}
|
|
}
|
|
|
|
public virtual Rectangle GetDrawRectangle()
|
|
{
|
|
return Rectangle;
|
|
}
|
|
|
|
public EventEditorNodeConnection? GetConnectionOnMouse(Vector2 mousePos)
|
|
{
|
|
return Connections.FirstOrDefault(eventNodeConnection => eventNodeConnection.DrawRectangle.Contains(mousePos));
|
|
}
|
|
|
|
public void Draw(SpriteBatch spriteBatch)
|
|
{
|
|
DrawBack(spriteBatch);
|
|
DrawFront(spriteBatch);
|
|
}
|
|
|
|
protected virtual void DrawFront(SpriteBatch spriteBatch) { }
|
|
|
|
protected virtual Color BackgroundColor => new Color(150, 150, 150);
|
|
|
|
private void DrawBack(SpriteBatch spriteBatch)
|
|
{
|
|
Color outlineColor = Color.White * 0.8f;
|
|
Color fontColor = Color.White;
|
|
Color headerColor = IsHighlighted ? new Color(100, 100, 100) : new Color(120, 120, 120);
|
|
if (IsSelected)
|
|
{
|
|
headerColor = new Color(80, 80, 80);
|
|
}
|
|
|
|
float camZoom = Screen.Selected is EventEditorScreen eventEditor ? eventEditor.Cam.Zoom : 1.0f;
|
|
|
|
Rectangle bodyRect = GetDrawRectangle();
|
|
|
|
GUI.DrawRectangle(spriteBatch, HeaderRectangle, headerColor, isFilled: true, depth: 1.0f);
|
|
GUI.DrawRectangle(spriteBatch, bodyRect, BackgroundColor, isFilled: true, depth: 1.0f);
|
|
|
|
GUI.DrawRectangle(spriteBatch, HeaderRectangle, outlineColor, isFilled: false, depth: 1.0f, thickness: (int) Math.Max(1, 1.25f / camZoom));
|
|
GUI.DrawRectangle(spriteBatch, bodyRect, outlineColor, isFilled: false, depth: 1.0f, thickness: (int) Math.Max(1, 1.25f / camZoom));
|
|
|
|
int x = 0, y = 0;
|
|
foreach (EventEditorNodeConnection connection in Connections)
|
|
{
|
|
switch (connection.Type.NodeSide)
|
|
{
|
|
case NodeConnectionType.Side.Left:
|
|
connection.Draw(spriteBatch, Rectangle, y);
|
|
y++;
|
|
break;
|
|
case NodeConnectionType.Side.Right:
|
|
connection.Draw(spriteBatch, Rectangle, x);
|
|
x++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Vector2 headerSize = GUIStyle.SubHeadingFont.MeasureString(Name);
|
|
GUIStyle.SubHeadingFont.DrawString(spriteBatch, Name, HeaderRectangle.Location.ToVector2() + (HeaderRectangle.Size.ToVector2() / 2) - (headerSize / 2), fontColor);
|
|
}
|
|
|
|
public void AddConnection(NodeConnectionType connectionType)
|
|
{
|
|
Connections.Add(new EventEditorNodeConnection(this, connectionType));
|
|
}
|
|
|
|
public virtual void AddOption()
|
|
{
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Option));
|
|
}
|
|
|
|
public void RemoveOption(EventEditorNodeConnection connection)
|
|
{
|
|
int index = Connections.IndexOf(connection);
|
|
foreach (var nodeConnection in Connections.Skip(index))
|
|
{
|
|
nodeConnection.ID--;
|
|
}
|
|
|
|
Connections.Remove(connection);
|
|
}
|
|
|
|
public EditorNode? GetNext()
|
|
{
|
|
var nextNode = Connections.Find(connection => connection.Type == NodeConnectionType.Next);
|
|
return nextNode?.ConnectedTo.FirstOrDefault()?.Parent;
|
|
}
|
|
|
|
public EditorNode? GetNext(NodeConnectionType type)
|
|
{
|
|
var nextNode = Connections.Find(connection => connection.Type == type);
|
|
return nextNode?.ConnectedTo.FirstOrDefault()?.Parent;
|
|
}
|
|
|
|
public static bool IsInstanceOf(Type type1, Type type2)
|
|
{
|
|
return type1.IsAssignableFrom(type2) || type1.IsSubclassOf(type2);
|
|
}
|
|
|
|
public EditorNode? GetParent()
|
|
{
|
|
var myNode = Connections.Find(connection => connection.Type == NodeConnectionType.Activate);
|
|
if (myNode == null) { return null; }
|
|
|
|
foreach (EditorNode editorNode in EventEditorScreen.nodeList)
|
|
{
|
|
List<EventEditorNodeConnection> childConnection = editorNode.Connections.Where(connection => connection.Type == NodeConnectionType.Next ||
|
|
connection.Type == NodeConnectionType.Option ||
|
|
connection.Type == NodeConnectionType.Failure ||
|
|
connection.Type == NodeConnectionType.Success ||
|
|
connection.Type == NodeConnectionType.Add).ToList();
|
|
if (childConnection.Any(connection => connection != null && connection.ConnectedTo.Contains(myNode)))
|
|
{
|
|
return editorNode;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
internal class EventNode : EditorNode
|
|
{
|
|
private readonly Type type;
|
|
|
|
public EventNode(Type type, string name) : base(name)
|
|
{
|
|
this.type = type;
|
|
Size = new Vector2(256, 256);
|
|
PropertyInfo[] properties = type.GetProperties().Where(info => info.CustomAttributes.Any(data => data.AttributeType == typeof(Serialize))).ToArray();
|
|
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Activate));
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Next));
|
|
|
|
foreach (PropertyInfo property in properties)
|
|
{
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Value, property.Name, property.PropertyType, property));
|
|
}
|
|
|
|
if (IsInstanceOf(type, typeof(BinaryOptionAction)))
|
|
{
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Success));
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Failure));
|
|
}
|
|
|
|
if (IsInstanceOf(type, typeof(ConversationAction)))
|
|
{
|
|
CanAddConnections = true;
|
|
RemovableTypes.Add(NodeConnectionType.Option);
|
|
}
|
|
|
|
if (IsInstanceOf(type, typeof(StatusEffectAction)) || IsInstanceOf(type, typeof(MissionAction)))
|
|
{
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Add));
|
|
}
|
|
}
|
|
|
|
public override XElement Save()
|
|
{
|
|
XElement newElement = new XElement(nameof(EventNode),
|
|
new XAttribute("i", ID),
|
|
new XAttribute("type", type.ToString()),
|
|
new XAttribute("name", Name),
|
|
new XAttribute("xpos", Position.X),
|
|
new XAttribute("ypos", Position.Y));
|
|
|
|
return newElement;
|
|
}
|
|
|
|
public static EditorNode? LoadEventNode(XElement element)
|
|
{
|
|
if (!string.Equals(element.Name.ToString(), nameof(EventNode), StringComparison.InvariantCultureIgnoreCase)) { return null; }
|
|
|
|
Type? t = Type.GetType(element.GetAttributeString("type", string.Empty));
|
|
if (t == null) { return null; }
|
|
|
|
EventNode newNode = new EventNode(t, element.GetAttributeString("name", string.Empty)) { ID = element.GetAttributeInt("i", -1) };
|
|
float posX = element.GetAttributeFloat("xpos", 0f);
|
|
float posY = element.GetAttributeFloat("ypos", 0f);
|
|
newNode.Position = new Vector2(posX, posY);
|
|
return newNode;
|
|
}
|
|
|
|
public override Rectangle GetDrawRectangle()
|
|
{
|
|
return ScaleRectFromConnections(Connections, Rectangle);
|
|
}
|
|
|
|
public static Rectangle ScaleRectFromConnections(List<EventEditorNodeConnection> connections, Rectangle baseRect)
|
|
{
|
|
// determine how big this box should get based on how many input/output nodes the sides have
|
|
int y = connections.Count(connection => connection.Type.NodeSide == NodeConnectionType.Side.Left),
|
|
x = connections.Count(connection => connection.Type.NodeSide == NodeConnectionType.Side.Right);
|
|
int maxHeight = Math.Max(x, y);
|
|
|
|
Rectangle bodyRect = baseRect;
|
|
bodyRect.Height = bodyRect.Height / 8 * maxHeight;
|
|
return bodyRect;
|
|
}
|
|
|
|
public Tuple<EditorNode?, string?, bool>[] GetOptions()
|
|
{
|
|
IEnumerable<EventEditorNodeConnection> myNode = Connections.Where(connection => connection.Type == NodeConnectionType.Option).ToArray();
|
|
List<Tuple<EditorNode?, string?, bool>> list = new List<Tuple<EditorNode?, string?, bool>>();
|
|
if (myNode != null)
|
|
{
|
|
foreach (EventEditorNodeConnection connection in myNode)
|
|
{
|
|
if (connection.ConnectedTo.Any())
|
|
{
|
|
foreach (EventEditorNodeConnection nodeConnection in connection.ConnectedTo)
|
|
{
|
|
list.Add(Tuple.Create((EditorNode?) nodeConnection.Parent, connection.OptionText, connection.EndConversation));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
list.Add(Tuple.Create<EditorNode?, string?, bool>(null, connection.OptionText, connection.EndConversation));
|
|
}
|
|
}
|
|
}
|
|
|
|
return list.ToArray();
|
|
}
|
|
}
|
|
|
|
internal class ValueNode : EditorNode
|
|
{
|
|
private object? nodeValue;
|
|
|
|
public object? Value
|
|
{
|
|
get => nodeValue;
|
|
set
|
|
{
|
|
nodeValue = value;
|
|
if (value is string str)
|
|
{
|
|
WrappedText = TextManager.Get(str) is { Loaded:true } translated ? translated.Value : str;
|
|
}
|
|
else
|
|
{
|
|
WrappedText = value?.ToString() ?? string.Empty;
|
|
}
|
|
valueTextSize = GUIStyle.SubHeadingFont.MeasureString(WrappedText);
|
|
}
|
|
}
|
|
|
|
private Vector2 valueTextSize = Vector2.Zero;
|
|
|
|
public Type Type { get; }
|
|
|
|
public ValueNode(Type type, string name) : base(name)
|
|
{
|
|
Type = type;
|
|
Value = type.IsValueType ? Activator.CreateInstance(type) : null;
|
|
Size = new Vector2(256, 32);
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Out, "Output", Type));
|
|
}
|
|
|
|
public override XElement Save()
|
|
{
|
|
XElement newElement = new XElement(nameof(ValueNode));
|
|
newElement.Add(new XAttribute("i", ID));
|
|
if (Value != null)
|
|
{
|
|
newElement.Add(new XAttribute("value", Value));
|
|
}
|
|
|
|
newElement.Add(new XAttribute("type", Type.ToString()));
|
|
newElement.Add(new XAttribute("name", Name));
|
|
newElement.Add(new XAttribute("xpos", Position.X));
|
|
newElement.Add(new XAttribute("ypos", Position.Y));
|
|
return newElement;
|
|
}
|
|
|
|
public override XElement? ToXML() { return null; }
|
|
|
|
public static EditorNode? LoadValueNode(XElement element)
|
|
{
|
|
if (!string.Equals(element.Name.ToString(), nameof(ValueNode), StringComparison.InvariantCultureIgnoreCase)) { return null; }
|
|
|
|
string? value = element.GetAttributeString("value", null);
|
|
Type? type = Type.GetType(element.GetAttributeString("type", string.Empty));
|
|
if (type != null)
|
|
{
|
|
ValueNode newNode = new ValueNode(type, element.GetAttributeString("name", string.Empty)) { ID = element.GetAttributeInt("i", -1) };
|
|
float posX = element.GetAttributeFloat("xpos", 0f);
|
|
float posY = element.GetAttributeFloat("ypos", 0f);
|
|
newNode.Position = new Vector2(posX, posY);
|
|
|
|
if (value != null)
|
|
{
|
|
if (type.IsEnum)
|
|
{
|
|
Array enums = Enum.GetValues(type);
|
|
foreach (object? @enum in enums)
|
|
{
|
|
if (string.Equals(@enum?.ToString(), value, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
newNode.Value = @enum;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
newNode.Value = EventEditorScreen.ChangeType(value, type);
|
|
}
|
|
}
|
|
|
|
return newNode;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected override Color BackgroundColor => new Color(50, 50, 50);
|
|
|
|
private string? wrappedText;
|
|
|
|
private string? WrappedText
|
|
{
|
|
get => wrappedText;
|
|
set
|
|
{
|
|
string valueText = value ?? "null";
|
|
int width = Rectangle.Width;
|
|
if (width == 0)
|
|
{
|
|
wrappedText = valueText;
|
|
return;
|
|
}
|
|
|
|
if (width > 16)
|
|
{
|
|
width -= 16;
|
|
}
|
|
|
|
if (GUIStyle.SubHeadingFont.Value != null)
|
|
{
|
|
valueText = ToolBox.WrapText(valueText, width, GUIStyle.SubHeadingFont.Value);
|
|
}
|
|
wrappedText = valueText;
|
|
}
|
|
}
|
|
|
|
public override Rectangle GetDrawRectangle()
|
|
{
|
|
Rectangle drawRectangle = Rectangle;
|
|
Vector2 size = GUIStyle.SubHeadingFont.MeasureString(WrappedText ?? "");
|
|
drawRectangle.Height = (int) Math.Max(size.Y + 16, drawRectangle.Height);
|
|
return drawRectangle;
|
|
}
|
|
|
|
protected override void DrawFront(SpriteBatch spriteBatch)
|
|
{
|
|
base.DrawFront(spriteBatch);
|
|
Vector2 pos = GetDrawRectangle().Location.ToVector2() + (GetDrawRectangle().Size.ToVector2() / 2) - (valueTextSize / 2);
|
|
Rectangle drawRect = Rectangle;
|
|
drawRect.Inflate(-1, -1);
|
|
GUI.DrawString(spriteBatch, pos, WrappedText, EventEditorNodeConnection.GetPropertyColor(Type), font: GUIStyle.SubHeadingFont);
|
|
}
|
|
}
|
|
|
|
class SpecialNode : EditorNode
|
|
{
|
|
public SpecialNode(string name) : base(name)
|
|
{
|
|
Size = new Vector2(256, 256);
|
|
}
|
|
|
|
public override Rectangle GetDrawRectangle()
|
|
{
|
|
return EventNode.ScaleRectFromConnections(Connections, Rectangle);
|
|
}
|
|
}
|
|
|
|
class CustomNode : SpecialNode
|
|
{
|
|
public CustomNode(string name) : base(name)
|
|
{
|
|
CanAddConnections = true;
|
|
RemovableTypes.Add(NodeConnectionType.Value);
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Activate));
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Next));
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Add));
|
|
}
|
|
|
|
public CustomNode() : this("Custom")
|
|
{
|
|
Prompt(s =>
|
|
{
|
|
Name = s;
|
|
return true;
|
|
});
|
|
}
|
|
|
|
public override void AddOption()
|
|
{
|
|
Prompt(s =>
|
|
{
|
|
Connections.Add(new EventEditorNodeConnection(this, NodeConnectionType.Value, s, typeof(string)));
|
|
return true;
|
|
});
|
|
}
|
|
|
|
public override XElement Save()
|
|
{
|
|
XElement newElement = new XElement(nameof(CustomNode));
|
|
newElement.Add(new XAttribute("i", ID));
|
|
newElement.Add(new XAttribute("name", Name));
|
|
newElement.Add(new XAttribute("xpos", Position.X));
|
|
newElement.Add(new XAttribute("ypos", Position.Y));
|
|
foreach (EventEditorNodeConnection connection in Connections.FindAll(connection => connection.Type == NodeConnectionType.Value))
|
|
{
|
|
newElement.Add(new XElement("Value", new XAttribute("name", connection.Attribute)));
|
|
}
|
|
return newElement;
|
|
}
|
|
|
|
public static EditorNode? LoadCustomNode(XElement element)
|
|
{
|
|
if (!string.Equals(element.Name.ToString(), nameof(CustomNode), StringComparison.OrdinalIgnoreCase)) { return null; }
|
|
|
|
CustomNode newNode = new CustomNode(element.GetAttributeString("name", string.Empty)) { ID = element.GetAttributeInt("i", -1) };
|
|
float posX = element.GetAttributeFloat("xpos", 0f);
|
|
float posY = element.GetAttributeFloat("ypos", 0f);
|
|
newNode.Position = new Vector2(posX, posY);
|
|
foreach (XElement valueElement in element.Elements())
|
|
{
|
|
newNode.Connections.Add(new EventEditorNodeConnection(newNode, NodeConnectionType.Value, valueElement.GetAttributeString("name", string.Empty), typeof(string)));
|
|
}
|
|
return newNode;
|
|
}
|
|
|
|
private static void Prompt(Func<string, bool> OnAccepted)
|
|
{
|
|
var msgBox = new GUIMessageBox(TextManager.Get("Name"), "", new[] { TextManager.Get("Ok"), TextManager.Get("Cancel") }, new Vector2(0.2f, 0.175f), minSize: new Point(300, 175));
|
|
var layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), msgBox.Content.RectTransform), isHorizontal: true);
|
|
GUITextBox nameInput = new GUITextBox(new RectTransform(Vector2.One, layout.RectTransform));
|
|
|
|
msgBox.Buttons[1].OnClicked = delegate
|
|
{
|
|
msgBox.Close();
|
|
return true;
|
|
};
|
|
|
|
msgBox.Buttons[0].OnClicked = delegate
|
|
{
|
|
OnAccepted.Invoke(nameInput.Text);
|
|
msgBox.Close();
|
|
return true;
|
|
};
|
|
}
|
|
}
|
|
} |