Skip to content

Instantly share code, notes, and snippets.

@ErnSur
Last active June 5, 2022 16:54
Show Gist options
  • Save ErnSur/562842abc95777b8fe67e5ea0a746cb5 to your computer and use it in GitHub Desktop.
Save ErnSur/562842abc95777b8fe67e5ea0a746cb5 to your computer and use it in GitHub Desktop.
Quick, simple and a little dirty way to deserialize visual elements from XML. Created to load custom views in runtime.

XML to Visual Element

Quick, simple and a little dirty way to deserialize visual elements from XML. Created to load custom views in runtime

using UnityEngine.UIElements;
namespace QuickEye.UIToolkit
{
public class FoldoutMeta : InputFieldMeta<Foldout>
{
protected override void Initialize(Foldout e)
{
base.Initialize(e);
e.text = Label;
}
}
public class ButtonMeta : InputFieldMeta<Button>
{
protected override void Initialize(Button e)
{
base.Initialize(e);
e.text = Label;
}
}
public class ToggleMeta : InputFieldMeta<Toggle>
{
protected override void Initialize(Toggle e)
{
base.Initialize(e);
e.label = Label;
}
}
public class IntegerFieldMeta : InputFieldMeta<IntegerField>
{
protected override void Initialize(IntegerField e)
{
base.Initialize(e);
e.label = Label;
}
}
public class FloatFieldMeta : InputFieldMeta<FloatField>
{
protected override void Initialize(FloatField e)
{
base.Initialize(e);
e.label = Label;
}
}
public class SliderMeta : InputFieldMeta<Slider>
{
protected override void Initialize(Slider e)
{
base.Initialize(e);
e.lowValue = 0;
e.highValue = 1;
e.label = Label;
}
}
public class TextFieldMeta : InputFieldMeta<TextField>
{
protected override void Initialize(TextField e)
{
base.Initialize(e);
e.label = Label;
}
}
}
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml.Serialization;
using UnityEngine.UIElements;
namespace QuickEye.UIToolkit
{
public class VeMeta
{
[XmlAttribute]
public string Name;
[XmlElement("Foldout", Type = typeof(FoldoutMeta))]
[XmlElement("IntField", Type = typeof(IntegerFieldMeta))]
[XmlElement("FloatField", Type = typeof(FloatFieldMeta))]
[XmlElement("Slider", Type = typeof(SliderMeta))]
[XmlElement("TextField", Type = typeof(TextFieldMeta))]
[XmlElement("Toggle", Type = typeof(ToggleMeta))]
[XmlElement("Button", Type = typeof(ButtonMeta))]
public List<VeMeta> Children;
public VisualElement ToVisualElement()
{
var e = CreateElement();
e.name = Name;
Initialize(e);
foreach (var child in Children)
{
e.Add(child.ToVisualElement());
}
return e;
}
protected virtual VisualElement CreateElement() => new VisualElement();
protected virtual void Initialize(VisualElement e)
{
}
public string ToXml()
{
var x = new XmlSerializer(typeof(VeMeta));
using (var writer = new StringWriter(CultureInfo.InvariantCulture))
{
x.Serialize(writer, this);
return writer.ToString();
}
}
public static VeMeta FromXml(string xml)
{
var stream = new StringReader(xml);
var serializer = new XmlSerializer(typeof(VeMeta));
var root = (VeMeta)serializer.Deserialize(stream);
return root;
}
public void Add(VeMeta e) => Children.Add(e);
}
public class VeMeta<T> : VeMeta where T : VisualElement, new()
{
protected override VisualElement CreateElement() => new T();
protected override void Initialize(VisualElement e)
{
Initialize((T)e);
}
protected virtual void Initialize(T e)
{
}
}
}
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;
using UnityEngine.UIElements;
namespace QuickEye.UIToolkit
{
public class XMLSerializationTest : MonoBehaviour
{
private readonly VeMeta _root = new();
private const string FilePath = "Assets/XmlSerialization.xml";
private void CreateTree()
{
_root.Children = new List<VeMeta>()
{
new FoldoutMeta()
{
Name = "First Foldout",
Children = new List<VeMeta>
{
new ToggleMeta() { Label = "MyToggle" },
new ButtonMeta() { Label = "MyButton" }
}
},
new FoldoutMeta()
{
Name = "Second Foldout",
Children = new List<VeMeta>
{
new ToggleMeta() { Label = "MyToggle 2" },
new ButtonMeta() { Label = "MyButton 2" }
}
},
};
}
[ContextMenu(nameof(Serialize))]
private void Serialize()
{
CreateTree();
File.WriteAllText(FilePath,_root.ToXml());
AssetDatabase.ImportAsset(FilePath);
}
[ContextMenu(nameof(Deserialize))]
private void Deserialize()
{
var xml = File.ReadAllText(FilePath);
var element = VeMeta.FromXml(xml);
PrintHierarchy(element,0);
PrintHierarchy(element.ToVisualElement(),0);
}
private static void PrintHierarchy(VeMeta ve, int indent)
{
Debug.Log($"{new string(' ', indent)}{ve.GetType().Name}");
foreach (var child in ve.Children)
{
PrintHierarchy(child, indent + 3);
}
}
private static void PrintHierarchy(VisualElement ve, int indent)
{
Debug.Log($"{new string(' ', indent)}{ve.GetType().Name}");
foreach (var child in ve.Children())
{
PrintHierarchy(child, indent + 3);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment