fix: fix serialization bugs

main
taoria 3 years ago
parent 69346b388b
commit 5c851d5cca
  1. 2
      TNode/Attribute/Ports/InputAttribute.cs
  2. 4
      TNode/Attribute/Ports/OutputAttribute.cs
  3. 13
      TNode/Attribute/Ports/PortAttribute.cs
  4. 3
      TNode/JsonSerialize.meta
  5. 36
      TNode/JsonSerialize/JsonSerializeTool.cs
  6. 3
      TNode/JsonSerialize/JsonSerializeTool.cs.meta
  7. 42
      TNode/JsonSerialize/NodeDataConverter.cs
  8. 3
      TNode/JsonSerialize/NodeDataConverter.cs.meta
  9. 24
      TNode/JsonSerialize/UnityObjectConverter.cs
  10. 3
      TNode/JsonSerialize/UnityObjectConverter.cs.meta
  11. 28
      TNode/JsonSerialize/Vector3Converter.cs
  12. 3
      TNode/JsonSerialize/Vector3Converter.cs.meta
  13. 15
      TNode/Models/BlackboardDragNodeData.cs
  14. 48
      TNode/Models/GraphData.cs
  15. 5
      TNode/RuntimeCache/RuntimeCache.cs
  16. 5
      TNodeGraphViewImpl/Editor/GraphBlackboard/DefaultGraphBlackboardView.cs
  17. 2
      TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs
  18. 9
      TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs
  19. 6
      TNodeGraphViewImpl/Editor/NodeViews/DragNodeView.cs
  20. 16
      TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs
  21. 3
      TNodeGraphViewImpl/Editor/Resources.meta
  22. 5
      TNodeGraphViewImpl/Editor/Resources/GraphViewPropertyField.uss
  23. 3
      TNodeGraphViewImpl/Editor/Resources/GraphViewPropertyField.uss.meta

@ -5,7 +5,7 @@ namespace TNode.Attribute.Ports{
[MeansImplicitUse]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class InputAttribute : PortAttribute{
public InputAttribute(string name="", PortNameHandling nameHandling = PortNameHandling.Auto) : base(name, nameHandling){
public InputAttribute(string name="", PortNameHandling nameHandling = PortNameHandling.Auto,TypeHandling typeHandling=TypeHandling.Declared) : base(name, nameHandling,typeHandling){
}
}
}

@ -1,6 +1,8 @@
namespace TNode.Attribute.Ports{
public class OutputAttribute:PortAttribute{
public OutputAttribute(string name="", PortNameHandling nameHandling = PortNameHandling.Auto) : base(name, nameHandling){
public OutputAttribute(string name="", PortNameHandling nameHandling = PortNameHandling.Auto,TypeHandling typeHandling = TypeHandling.Declared) : base(name, nameHandling,typeHandling){
}
}
}

@ -9,17 +9,26 @@ namespace TNode.Attribute.Ports{
Manual,
Format,
MemberType
}
public enum TypeHandling{
Declared,
Implemented,
Specified
}
[MeansImplicitUse]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class PortAttribute:System.Attribute{
public readonly string Name;
public readonly PortNameHandling NameHandling;
public PortAttribute(string name,PortNameHandling nameHandling=PortNameHandling.Auto){
public Type HandledType;
public TypeHandling TypeHandling{ get; set; }
public PortAttribute(string name,PortNameHandling nameHandling=PortNameHandling.Auto,TypeHandling typeHandling=TypeHandling.Declared){
this.Name = name;
this.NameHandling = nameHandling;
this.TypeHandling = typeHandling;
}
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: ec6119d082a947f58ed6402290b65596
timeCreated: 1656817965

@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace TNode.JsonSerialize{
public static class JsonSerializeTool{
class WritablePropertiesOnlyResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
return props.Where(p => p.Writable).ToList();
}
}
public static JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings(){
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
DateFormatString = "yyyy-MM-dd HH:mm:ss",
Converters = new List<JsonConverter> { new Vector3Converter(),new UnityObjectConverter() },
TypeNameHandling = TypeNameHandling.Auto,
ContractResolver = new WritablePropertiesOnlyResolver(),
Formatting = Formatting.Indented
};
public static JsonSerializerSettings InternalJsonSerializerSettings = new JsonSerializerSettings(){
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented
};
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 14067671fe28434e9ae2e67a34074c52
timeCreated: 1656819161

@ -1,42 +0,0 @@
using System;
using Newtonsoft.Json;
using TNode.Models;
using UnityEngine;
namespace TNode.JsonSerialize{
public class NodeDataConverter:JsonConverter<NodeData>{
public override void WriteJson(JsonWriter writer, NodeData value, JsonSerializer serializer){
//Write node data with type information
writer.WriteStartObject();
writer.WritePropertyName("type");
Debug.Log(value.GetType().ToString());
writer.WriteValue(value.GetType().Name);
writer.WritePropertyName("data");
serializer.Serialize(writer, value, value.GetType());
writer.WriteEndObject();
}
public override NodeData ReadJson(JsonReader reader, Type objectType, NodeData existingValue, bool hasExistingValue,
JsonSerializer serializer){
//Load type info
reader.Read();
if (reader.Value != null){
var type = reader.Value.ToString();
if (type.Trim().Length==0){
Debug.LogError(type);
throw new JsonSerializationException("Type name is empty");
}
reader.Read();
//Load data
var data = serializer.Deserialize(reader, Type.GetType(type));
return (NodeData) data;
}
return null;
}
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 6f960539f2744729b35ff3011677d8ba
timeCreated: 1656857829

@ -1,24 +0,0 @@
using System;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace TNode.JsonSerialize{
public class UnityObjectConverter:JsonConverter<Object>{
public override void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer){
//Holding the object reference in a string
var go = value;
var guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(go));
writer.WriteValue(value.GetInstanceID().ToString());
}
public override Object ReadJson(JsonReader reader, Type objectType, Object existingValue, bool hasExistingValue,
JsonSerializer serializer){
//Reading the object reference from the string
var guid = reader.Value.ToString();
var go = AssetDatabase.LoadAssetAtPath<Object>(AssetDatabase.GUIDToAssetPath(guid));
return go;
}
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 1c430c5760df439690d22ab18daa9d72
timeCreated: 1657700744

@ -1,28 +0,0 @@
using System;
using System.Numerics;
using Newtonsoft.Json;
namespace TNode.JsonSerialize{
public class Vector3Converter:JsonConverter<Vector3>{
public override void WriteJson(JsonWriter writer, Vector3 value, JsonSerializer serializer){
writer.WriteStartArray();
writer.WriteValue(value.X);
writer.WriteValue(value.Y);
writer.WriteValue(value.Z);
writer.WriteEndArray();
}
public override Vector3 ReadJson(JsonReader reader, Type objectType, Vector3 existingValue, bool hasExistingValue, JsonSerializer serializer){
if (reader.TokenType == JsonToken.Null){
return default(Vector3);
}
else{
var array = serializer.Deserialize<float[]>(reader);
if (array != null) return new Vector3(array[0], array[1], array[2]);
}
return default(Vector3);
}
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: fecb77054ad348239341a58c50549879
timeCreated: 1656817975

@ -4,15 +4,18 @@ using Newtonsoft.Json;
using TNode.Attribute;
using TNode.Attribute.Ports;
using TNode.RuntimeCache;
using UnityEngine;
using UnityEngine.Serialization;
namespace TNode.Models{
public class BlackboardDragNodeData<T>:NodeData{
private string _blackDragData;
[JsonIgnore]
private BlackboardData _blackboardData;
[Serializable]
public class BlackboardDragNodeData:NodeData{
public string blackDragData;
[SerializeReference]
public BlackboardData blackboardData;
[Output("",PortNameHandling.MemberType)]
public T Value => _blackboardData.GetValue<T>(_blackDragData);
[Output("",PortNameHandling.MemberType,TypeHandling.Implemented)]
public object Value => blackboardData.GetValue(blackDragData);
public BlackboardDragNodeData(){

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using TNode.JsonSerialize;
using UnityEngine;
using UnityEngine.Serialization;
namespace TNode.Models{
@ -10,18 +9,12 @@ namespace TNode.Models{
public class GraphData:ScriptableObject,ISerializationCallbackReceiver{
public Dictionary<string,NodeData> NodeDictionary = new Dictionary<string,NodeData>();
[SerializeReference]
public List<NodeData> nodeList = new List<NodeData>();
[SerializeField]
protected List<NodeLink> nodeLinks;
[TextArea(1,10)]
[SerializeField]
//[HideInInspector]
private string jsonNodeData;
[TextArea(1,10)]
[SerializeField]
private string jsonBlackboard;
[SerializeReference]
public BlackboardData blackboardData;
public List<NodeLink> NodeLinks{
@ -34,32 +27,19 @@ namespace TNode.Models{
public void OnBeforeSerialize(){
if (nodeLinks != null){
jsonNodeData = JsonConvert.SerializeObject(NodeDictionary,JsonSerializeTool.JsonSerializerSettings);
}
if (jsonBlackboard != null){
jsonBlackboard = JsonConvert.SerializeObject(blackboardData,typeof(object),JsonSerializeTool.JsonSerializerSettings);
nodeList.Clear();
foreach(var node in NodeDictionary.Values){
nodeList.Add(node);
}
}
public void OnAfterDeserialize(){
//Deserialize node dictionary
var deserializedData = JsonConvert.DeserializeObject<Dictionary<string,NodeData>>(jsonNodeData,JsonSerializeTool.JsonSerializerSettings);
NodeDictionary = deserializedData;
//Deserialize blackboard data
// var deserializedBlackboard =
// JsonConvert.DeserializeObject(jsonBlackboard,JsonSerializeTool.JsonSerializerSettings);
// blackboardData = deserializedBlackboard as BlackboardData;
// Debug.Log(deserializedBlackboard);
}
public void OnEnable(){
var deserializedBlackboard =
JsonConvert.DeserializeObject(jsonBlackboard,JsonSerializeTool.JsonSerializerSettings);
blackboardData = deserializedBlackboard as BlackboardData;
Debug.Log(deserializedBlackboard);
NodeDictionary.Clear();
foreach(var node in nodeList){
NodeDictionary.Add(node.id,node);
}
}
}
}

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using EasyRandomGenerator.Blackboard;
using JetBrains.Annotations;
using TNode.Models;
using Unity.VisualScripting;
@ -21,6 +22,10 @@ namespace TNode.RuntimeCache{
new ();
private static readonly string[] ExcludedAssemblies = new string[]{"Microsoft", "UnityEngine","UnityEditor","mscorlib","System"};
public RuntimeCache(){
RegisterRuntimeBlackboard(typeof(EasyBlackboardData));
}
public void RegisterRuntimeBlackboard(Type type){
if(!CachedDelegatesForGettingValue.ContainsKey(type)){
CachedDelegatesForGettingValue.Add(type, new Dictionary<string, GetValueDelegate>());

@ -14,6 +14,11 @@ using UnityEngine.UIElements;
namespace TNodeGraphViewImpl.Editor.GraphBlackboard{
[ViewComponent]
public class DefaultGraphBlackboardView:GraphBlackboardView<BlackboardData>{
public DefaultGraphBlackboardView():base(){
//the label and the field gap smaller
styleSheets.Add( Resources.Load<StyleSheet>("GraphViewPropertyField"));
}
protected override void UpdateBlackboard(BlackboardData data){
var serializedObject = new SerializedObject((BlackboardDataWrapper)data);
foreach (var field in data.GetType()

@ -38,7 +38,7 @@ namespace TNode.Editor.Inspector{
private void RefreshPropertyDrawer(){
//Check if the data's type is a generic type of BlackboardDragNodeData<>
if (_data.GetType().IsSubclassOf(typeof(BlackboardDragNodeData<>))){
if (_data.GetType().IsSubclassOf(typeof(BlackboardDragNodeData))){
return;
}
var serializedObject = new SerializedObject((NodeDataWrapper)_data);

@ -105,11 +105,10 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{
foreach (var selectable in blackboardFields){
if(selectable is { } field) {
//Make a constructor of BlackboardDragNodeData<field.PropertyType > by reflection
var specifiedType =
typeof(BlackboardDragNodeData<>).MakeGenericType(field.BlackboardProperty.PropertyType);
//Create a new instance of specified type
var dragNodeData = NodeCreator.InstantiateNodeData(specifiedType);
this.AddTNode(dragNodeData,new Rect(evt.mousePosition,new Vector2(200,200)));
var dragNodeData = NodeCreator.InstantiateNodeData<BlackboardDragNodeData>();
dragNodeData.blackboardData = _data.blackboardData;
dragNodeData.blackDragData = field.BlackboardProperty.PropertyName;
AddTNode(dragNodeData,new Rect(evt.mousePosition,new Vector2(200,200)));
}
}

@ -4,11 +4,9 @@ using TNodeGraphViewImpl.Editor.NodeViews;
namespace TNode.Editor.NodeViews{
[ViewComponent]
public class DragBaseNodeView<T>:BaseNodeView<BlackboardDragNodeData<T>>{
public class DragBaseNodeView:BaseNodeView<BlackboardDragNodeData>{
public DragBaseNodeView() : base(){
//Make capsule like style
this.titleContainer.visible = false;
this.titleContainer.visible = false;
this.titleContainer.RemoveFromHierarchy();
}
}

@ -76,6 +76,18 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{
throw new ArgumentOutOfRangeException();
}
}
protected virtual Type BuildPortType(PortAttribute portAttribute,PropertyInfo propertyInfo){
switch (portAttribute.TypeHandling){
case TypeHandling.Declared :
return propertyInfo.PropertyType;
case TypeHandling.Implemented:
return propertyInfo.GetValue(_data)?.GetType();
case TypeHandling.Specified:
return portAttribute.HandledType??typeof(object);
default:
throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// of course you can override this method to build your own port builder
/// </summary>
@ -84,7 +96,7 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{
foreach (var propertyInfo in propertyInfos){
if (propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true).FirstOrDefault() is OutputAttribute attribute){
Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,Port.Capacity.Multi,propertyInfo.PropertyType);
Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,Port.Capacity.Multi,BuildPortType(attribute,propertyInfo));
this.outputContainer.Add(port);
var portName = BuildPortName(attribute,propertyInfo);
port.portName = portName;
@ -93,7 +105,7 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{
}
foreach (var propertyInfo in propertyInfos){
if(propertyInfo.GetCustomAttributes(typeof(InputAttribute),true).FirstOrDefault() is InputAttribute attribute){
Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,Port.Capacity.Single,propertyInfo.PropertyType);
Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,Port.Capacity.Single,BuildPortType(attribute,propertyInfo));
this.inputContainer.Add(port);
var portName = BuildPortName(attribute,propertyInfo);
port.portName = portName;

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7d628735dd6d477c88ed608b684c50b4
timeCreated: 1657702172

@ -0,0 +1,5 @@
.unity-property-field__label {
width: 75px;
min-width: 100px;
max-width: 150px;
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2b84790a3a0445f894b9c496ad1e716b
timeCreated: 1657702197
Loading…
Cancel
Save