diff --git a/TNodeCore/Attribute/InternalModel.cs b/TNodeCore/Attribute/InternalUsageAttribute.cs similarity index 65% rename from TNodeCore/Attribute/InternalModel.cs rename to TNodeCore/Attribute/InternalUsageAttribute.cs index f9b10cd..d43dc33 100644 --- a/TNodeCore/Attribute/InternalModel.cs +++ b/TNodeCore/Attribute/InternalUsageAttribute.cs @@ -2,8 +2,8 @@ /// /// Internal use only. so that Editor Cache and Runtime cache could register it globally. /// - public class InternalModel:System.Attribute{ - public InternalModel(){ + public class InternalUsageAttribute:System.Attribute{ + public InternalUsageAttribute(){ } } diff --git a/TNodeCore/Attribute/InternalModel.cs.meta b/TNodeCore/Attribute/InternalUsageAttribute.cs.meta similarity index 100% rename from TNodeCore/Attribute/InternalModel.cs.meta rename to TNodeCore/Attribute/InternalUsageAttribute.cs.meta diff --git a/TNodeCore/Attribute/PortTypeConversion.cs b/TNodeCore/Attribute/PortTypeConversion.cs new file mode 100644 index 0000000..a2e8591 --- /dev/null +++ b/TNodeCore/Attribute/PortTypeConversion.cs @@ -0,0 +1,3 @@ +namespace TNodeCore.Attribute{ + +} \ No newline at end of file diff --git a/TNodeCore/Attribute/PortTypeConversion.cs.meta b/TNodeCore/Attribute/PortTypeConversion.cs.meta new file mode 100644 index 0000000..f9f3a56 --- /dev/null +++ b/TNodeCore/Attribute/PortTypeConversion.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fb41beebff2a41efb7a3f76d58af6179 +timeCreated: 1658306360 \ No newline at end of file diff --git a/TNodeCore/Models/BlackboardDragNodeData.cs b/TNodeCore/Models/BlackboardDragNodeData.cs index 120fd77..883464a 100644 --- a/TNodeCore/Models/BlackboardDragNodeData.cs +++ b/TNodeCore/Models/BlackboardDragNodeData.cs @@ -6,7 +6,7 @@ using UnityEngine; namespace TNodeCore.Models{ [Serializable] - [InternalModel] + [InternalUsage] public class BlackboardDragNodeData:RuntimeNodeData{ public string blackDragData; diff --git a/TNodeCore/Runtime/Interfaces.meta b/TNodeCore/Runtime/Interfaces.meta new file mode 100644 index 0000000..57de07c --- /dev/null +++ b/TNodeCore/Runtime/Interfaces.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 69f4e5ae5bcf45caa656a36173eeded3 +timeCreated: 1658306474 \ No newline at end of file diff --git a/TNodeCore/Runtime/Interfaces/IPortTypeConversion.cs b/TNodeCore/Runtime/Interfaces/IPortTypeConversion.cs new file mode 100644 index 0000000..29b4277 --- /dev/null +++ b/TNodeCore/Runtime/Interfaces/IPortTypeConversion.cs @@ -0,0 +1,7 @@ +namespace TNodeCore.Runtime.Interfaces{ + + public interface IPortTypeConversion{ + public TTo Convert(TFrom tFrom); + } + +} \ No newline at end of file diff --git a/TNodeCore/Runtime/Interfaces/IPortTypeConversion.cs.meta b/TNodeCore/Runtime/Interfaces/IPortTypeConversion.cs.meta new file mode 100644 index 0000000..26781ac --- /dev/null +++ b/TNodeCore/Runtime/Interfaces/IPortTypeConversion.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4e8bdf96ae104472a12f010f37ff1190 +timeCreated: 1658306486 \ No newline at end of file diff --git a/TNodeCore/RuntimeCache/RuntimeCache.cs b/TNodeCore/RuntimeCache/RuntimeCache.cs index 932890b..139be40 100644 --- a/TNodeCore/RuntimeCache/RuntimeCache.cs +++ b/TNodeCore/RuntimeCache/RuntimeCache.cs @@ -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 : IPortConverterHelper{ + private readonly IPortTypeConversion _converter; + public PortConverterHelper(Type type){ + _converter = Activator.CreateInstance(type) as IPortTypeConversion; + } + 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> CachedPropertyAccessors = new (); - + /// + /// 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. + /// + private readonly Dictionary> CachedPortConverters = + new (); + private readonly Dictionary _graphBlackboardDictionary = new Dictionary(); @@ -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 + 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()); + } + 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 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()); CachedDelegatesForSettingValue.Add(type,new Dictionary()); - - // 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); } } + } \ No newline at end of file diff --git a/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs b/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs index fcab94f..a33661d 100644 --- a/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs +++ b/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs @@ -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; @@ -234,6 +235,7 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{ //check if the drag data is BlackboardField if (DragAndDrop.GetGenericData("DragSelection") is List{Count: > 0} data){ DragAndDrop.visualMode = DragAndDropVisualMode.Move; + //high light the } } #endregion @@ -410,9 +412,19 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{ }); } public override List GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter){ - - return ports.Where(x => startPort!=x && (x.portType == startPort.portType || x.portType.IsAssignableFrom(startPort.portType))).ToList(); - + var supportedTypes = RuntimeCache.Instance.GetSupportedTypes(startPort.portType); + + var compatiblePorts = ports.Where(x => startPort != x && + (x.portType == startPort.portType || + x.portType.IsAssignableFrom(startPort.portType) + )).ToList(); + if (supportedTypes != null){ + compatiblePorts.AddRange(ports.Where(x => supportedTypes.Contains(x.portType)).ToList()); + } + + return compatiblePorts; + + } public virtual void OnGraphViewCreate(){ diff --git a/TNodeGraphViewImpl/Editor/NodeViews/DragNodeView.cs b/TNodeGraphViewImpl/Editor/NodeViews/DragNodeView.cs index 35ca0b0..a48bb79 100644 --- a/TNodeGraphViewImpl/Editor/NodeViews/DragNodeView.cs +++ b/TNodeGraphViewImpl/Editor/NodeViews/DragNodeView.cs @@ -25,16 +25,29 @@ namespace TNode.Editor.NodeViews{ BlackboardDataWrapper blackboardWrapper = (BlackboardDataWrapper)blackboard; var serializedData = new SerializedObject(blackboardWrapper); var serializedProperty = serializedData.FindProperty("data").FindPropertyRelative(obj.blackDragData); - PropertyField field = new PropertyField(serializedProperty,""); - field.Bind(serializedData); - label.parent.parent.style.flexDirection = FlexDirection.RowReverse; - label.parent.parent.Add(field); - label.parent.parent.style.alignItems = Align.Center; - label.parent.parent.style.justifyContent = Justify.Center; - label.parent.parent.style.paddingTop = 0; - label.parent.parent.style.paddingBottom = 0; - label.RemoveFromHierarchy(); + // + // field.Bind(serializedData); + // var p = label.parent.parent.parent; + // p.Add(field); + // field.SendToBack(); + // field.SetEnabled(false); + // p.style.alignItems = Align.Center; + // p.style.justifyContent = Justify.Center; + // p.style.paddingTop = 0; + // p.style.paddingBottom = 0; + label.text = obj.blackDragData; + //Get serialized property's icon + var icon = AssetPreview.GetMiniThumbnail(serializedProperty.objectReferenceValue); + + label.parent.Add(new Image(){ + image = icon + }); + //more round style for entire element + style.borderBottomLeftRadius = style.borderBottomRightRadius = + style.borderTopLeftRadius = style.borderTopRightRadius = 25; + styleSheets.Add(Resources.Load("DragNodeStyle")); + this.name = "DragNodeView"; } } } \ No newline at end of file diff --git a/TNodeGraphViewImpl/Editor/Resources/DragNodeStyle.uss b/TNodeGraphViewImpl/Editor/Resources/DragNodeStyle.uss new file mode 100644 index 0000000..8e49b02 --- /dev/null +++ b/TNodeGraphViewImpl/Editor/Resources/DragNodeStyle.uss @@ -0,0 +1,10 @@ +#node-border{ + + /*border-radius: 16px;*/ + /*border-color: #000;*/ + /*border-width: 1px;*/ +} +Image{ + max-height: 16; + max-width: 16; +} \ No newline at end of file diff --git a/TNodeGraphViewImpl/Editor/Resources/DragNodeStyle.uss.meta b/TNodeGraphViewImpl/Editor/Resources/DragNodeStyle.uss.meta new file mode 100644 index 0000000..c0ee79f --- /dev/null +++ b/TNodeGraphViewImpl/Editor/Resources/DragNodeStyle.uss.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 91a9fc5305f445798d87f5d5b9994027 +timeCreated: 1658396456 \ No newline at end of file diff --git a/TNodeCore/Editor/Resources/GraphViewBackground.uss b/TNodeGraphViewImpl/Editor/Resources/GraphViewBackground.uss similarity index 100% rename from TNodeCore/Editor/Resources/GraphViewBackground.uss rename to TNodeGraphViewImpl/Editor/Resources/GraphViewBackground.uss diff --git a/TNodeCore/Editor/Resources/GraphViewBackground.uss.meta b/TNodeGraphViewImpl/Editor/Resources/GraphViewBackground.uss.meta similarity index 100% rename from TNodeCore/Editor/Resources/GraphViewBackground.uss.meta rename to TNodeGraphViewImpl/Editor/Resources/GraphViewBackground.uss.meta