feat:so now different type could connected if a Converter is given

main
taoria 3 years ago
parent b95b47dfd8
commit 4858dfdbd6
  1. 4
      TNodeCore/Attribute/InternalUsageAttribute.cs
  2. 0
      TNodeCore/Attribute/InternalUsageAttribute.cs.meta
  3. 3
      TNodeCore/Attribute/PortTypeConversion.cs
  4. 3
      TNodeCore/Attribute/PortTypeConversion.cs.meta
  5. 2
      TNodeCore/Models/BlackboardDragNodeData.cs
  6. 3
      TNodeCore/Runtime/Interfaces.meta
  7. 7
      TNodeCore/Runtime/Interfaces/IPortTypeConversion.cs
  8. 3
      TNodeCore/Runtime/Interfaces/IPortTypeConversion.cs.meta
  9. 95
      TNodeCore/RuntimeCache/RuntimeCache.cs
  10. 6
      TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs

@ -2,8 +2,8 @@
/// <summary>
/// Internal use only. so that Editor Cache and Runtime cache could register it globally.
/// </summary>
public class InternalModel:System.Attribute{
public InternalModel(){
public class InternalUsageAttribute:System.Attribute{
public InternalUsageAttribute(){
}
}

@ -0,0 +1,3 @@
namespace TNodeCore.Attribute{
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fb41beebff2a41efb7a3f76d58af6179
timeCreated: 1658306360

@ -6,7 +6,7 @@ using UnityEngine;
namespace TNodeCore.Models{
[Serializable]
[InternalModel]
[InternalUsage]
public class BlackboardDragNodeData:RuntimeNodeData{
public string blackDragData;

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 69f4e5ae5bcf45caa656a36173eeded3
timeCreated: 1658306474

@ -0,0 +1,7 @@
namespace TNodeCore.Runtime.Interfaces{
public interface IPortTypeConversion<in TFrom, out TTo>{
public TTo Convert(TFrom tFrom);
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e8bdf96ae104472a12f010f37ff1190
timeCreated: 1658306486

@ -5,6 +5,7 @@ using System.Reflection;
using PlasticPipe.PlasticProtocol.Messages;
using TNodeCore.Attribute;
using TNodeCore.Models;
using TNodeCore.Runtime.Interfaces;
using UnityEngine;
namespace TNodeCore.RuntimeCache{
@ -32,6 +33,22 @@ namespace TNodeCore.RuntimeCache{
Set((T1)model,(T2)value);
}
}
internal class PortConverterHelper<T1,T2> : IPortConverterHelper{
private readonly IPortTypeConversion<T1, T2> _converter;
public PortConverterHelper(Type type){
_converter = Activator.CreateInstance(type) as IPortTypeConversion<T1, T2>;
}
public object Convert(object value){
return _converter.Convert((T1)value);
}
}
internal interface IPortConverterHelper{
public object Convert(object value);
}
public class PropertyNotFoundException : Exception{
public PropertyNotFoundException(string path):base("Property not found :"+path){
@ -55,7 +72,12 @@ namespace TNodeCore.RuntimeCache{
new ();
public readonly Dictionary<Type,Dictionary<string,IModelPropertyAccessor>> CachedPropertyAccessors =
new ();
/// <summary>
/// TODO: Converters now work globally, but it should be possible to specify a converter for a specific graph.but it will be too nested.so in current implementation, we will use a global converter.
/// </summary>
private readonly Dictionary<Type,Dictionary<Type,IPortConverterHelper>> CachedPortConverters =
new ();
private readonly Dictionary<Type, Type> _graphBlackboardDictionary = new Dictionary<Type, Type>();
@ -75,8 +97,8 @@ namespace TNodeCore.RuntimeCache{
AddTypeToCache(type,attribute as GraphUsageAttribute);
}
if (attribute is InternalModel){
AddTypeToCache(type,attribute as InternalModel);
if (attribute is InternalUsageAttribute usageAttribute){
AddTypeToCache(type,usageAttribute);
}
}
}
@ -93,9 +115,53 @@ namespace TNodeCore.RuntimeCache{
//if it is, add it to the cache
CacheRuntimeNodeData(type);
}
//Check if the type is implementing IPortTypeConversion<T1,T2>
if(typeof(IPortTypeConversion<,>).IsAssignableFrom(type)){
//if it is, add it to the cache
CacheRuntimePortTypeConversion(type);
}
}
private void CacheRuntimePortTypeConversion(Type type){
if (type.IsGenericType == false){
return;
}
var genericType = type.GetGenericTypeDefinition();
if (genericType != typeof(IPortTypeConversion<,>)){
return;
}
var type1 = type.GetGenericArguments()[0];
var type2 = type.GetGenericArguments()[1];
var specificType = typeof(PortConverterHelper<,>).MakeGenericType(type1, type2);
var instance = Activator.CreateInstance(specificType, type) as IPortConverterHelper;
if (instance == null){
return;
}
if (!CachedPortConverters.ContainsKey(type1)){
CachedPortConverters.Add(type1,new Dictionary<Type,IPortConverterHelper>());
}
CachedPortConverters[type1].Add(type2,instance);
}
public object GetConvertedValue(Type from,Type to,object value){
if(!CachedPortConverters.ContainsKey(from)){
throw new ConversionFailedException("No converter found for type "+from);
return value;
}
if(!CachedPortConverters[from].ContainsKey(to)){
return value;
}
return CachedPortConverters[from][to].Convert(value);
}
public List<Type> GetSupportedTypes(Type type){
if(!CachedPortConverters.ContainsKey(type)){
return null;
}
return CachedPortConverters[type].Keys.ToList();
}
private void AddBlackboardDataTypeToCache(Type type,GraphUsageAttribute attribute){
var graphData = attribute.GraphDataType;
_graphBlackboardDictionary.Add(graphData,type);
@ -121,18 +187,6 @@ namespace TNodeCore.RuntimeCache{
if(!CachedDelegatesForGettingValue.ContainsKey(type)){
CachedDelegatesForGettingValue.Add(type, new Dictionary<string, GetValueDelegate>());
CachedDelegatesForSettingValue.Add(type,new Dictionary<string, SetValueDelegate>());
// var properties = type.GetProperties();
// foreach(var property in properties){
// //if the property only has a setter ,skip
//
// var getValueDelegate = GetValueDelegateForProperty(property);
// CachedDelegatesForGettingValue[type].Add(property.Name,getValueDelegate);
//
// var setValueDelegate = SetValueDelegateForProperty(property);
// CachedDelegatesForSettingValue[type].Add(property.Name,setValueDelegate);
// }
//register the fields
var fields = type.GetFields();
foreach(var field in fields){
var getValueDelegate = GetValueDelegateForField(field);
@ -184,9 +238,17 @@ namespace TNodeCore.RuntimeCache{
return field.SetValue;
}
}
public class ConversionFailedException : Exception{
public ConversionFailedException(string noConverterFoundForType):base(noConverterFoundForType){
}
}
public static class RuntimeExtension{
//todo latter on i will try some way caching reflection more efficiently
@ -208,4 +270,5 @@ namespace TNodeCore.RuntimeCache{
method.Invoke(data,value);
}
}
}

@ -10,6 +10,7 @@ using TNodeCore.Editor.NodeGraphView;
using TNodeCore.Editor.Tools.NodeCreator;
using TNodeCore.Models;
using TNodeCore.Runtime;
using TNodeCore.RuntimeCache;
using TNodeGraphViewImpl.Editor.Cache;
using TNodeGraphViewImpl.Editor.GraphBlackboard;
using TNodeGraphViewImpl.Editor.NodeViews;
@ -411,7 +412,10 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{
}
public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter){
return ports.Where(x => startPort!=x && (x.portType == startPort.portType || x.portType.IsAssignableFrom(startPort.portType))).ToList();
return ports.Where(x => startPort!=x &&
(x.portType == startPort.portType ||
x.portType.IsAssignableFrom(startPort.portType) ||
RuntimeCache.Instance.GetSupportedTypes(startPort.portType).Contains(x.portType))).ToList();
}

Loading…
Cancel
Save