Skip to content

Commit 1adffe6

Browse files
committed
Deprecated field factory and replace all nodes + drawer fields by PropertyFields
1 parent 8f0dd94 commit 1adffe6

File tree

10 files changed

+105
-36
lines changed

10 files changed

+105
-36
lines changed

Assets/com.alelievr.NodeGraphProcessor/Editor/NodeInspectorObject.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ public class NodeInspectorObjectEditor : Editor
1818
protected VisualElement selectedNodeList;
1919
protected VisualElement placeholder;
2020

21-
Dictionary<BaseNode, VisualElement> nodeInspectorCache = new Dictionary<BaseNode, VisualElement>();
22-
2321
protected virtual void OnEnable()
2422
{
2523
inspector = target as NodeInspectorObject;
@@ -88,6 +86,8 @@ public virtual void UpdateSelectedNodes(HashSet<BaseNodeView> views)
8886
nodeSelectionUpdated?.Invoke();
8987
}
9088

89+
public virtual void RefreshNodes() => nodeSelectionUpdated?.Invoke();
90+
9191
public virtual void NodeViewRemoved(BaseNodeView view)
9292
{
9393
selectedNodes.Remove(view);

Assets/com.alelievr.NodeGraphProcessor/Editor/Resources/GraphProcessorStyles/BaseNodeView.uss

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -106,49 +106,48 @@ ParameterNodeView #controls EnumField > VisualElement > VisualElement {
106106
--layer: -50;
107107
}
108108

109-
#input-container > .port-input-element > IntegerField,
110-
#input-container > .port-input-element > FloatField {
109+
#input-container > .port-input-element > * {
111110
min-width: 30px;
112-
max-width: 100px;
111+
max-width: 200px;
113112
}
114113

115-
#input-container > .port-input-element > ColorField,
116-
#input-container > .port-input-element > ObjectField,
117-
#input-container > .port-input-element > CurveField {
114+
#input-container > .port-input-element > PropertyField > ColorField,
115+
#input-container > .port-input-element > PropertyField > ObjectField,
116+
#input-container > .port-input-element > PropertyField > CurveField {
118117
margin-top: 0;
119118
margin-bottom: 0;
120119
}
121120

122-
#input-container > .port-input-element > TextField {
121+
#input-container > .port-input-element > PropertyField > TextField {
123122
min-width: 50px;
124-
max-width: 150px;
125123
}
126124

127-
#input-container > .port-input-element > CurveField {
125+
#input-container > .port-input-element > PropertyField > CurveField {
128126
width: 100px;
129127
}
130128

131-
#input-container > .port-input-element > Vector4Field Label,
132-
#input-container > .port-input-element > Vector3Field Label,
133-
#input-container > .port-input-element > Vector2Field Label,
134-
#input-container > .port-input-element > Vector3IntField Label,
135-
#input-container > .port-input-element > Vector2IntField Label {
129+
#input-container > .port-input-element > PropertyField > Vector4Field Label,
130+
#input-container > .port-input-element > PropertyField > Vector3Field Label,
131+
#input-container > .port-input-element > PropertyField > Vector2Field Label,
132+
#input-container > .port-input-element > PropertyField > Vector3IntField Label,
133+
#input-container > .port-input-element > PropertyField > Vector2IntField Label {
136134
font-size: 8px;
137135
min-width: 8px;
138136
flex-basis: 8px;
139137
padding-top: 2px;
140138
margin-right: 1px;
139+
max-height: 150px;
141140
}
142141

143-
#input-container > .port-input-element > Vector4Field FloatInput,
144-
#input-container > .port-input-element > Vector3Field FloatInput,
145-
#input-container > .port-input-element > Vector2Field FloatInput,
146-
#input-container > .port-input-element > Vector3IntField IntegerInput,
147-
#input-container > .port-input-element > Vector2IntField IntegerInput {
142+
#input-container > .port-input-element > PropertyField > Vector4Field FloatInput,
143+
#input-container > .port-input-element > PropertyField > Vector3Field FloatInput,
144+
#input-container > .port-input-element > PropertyField > Vector2Field FloatInput,
145+
#input-container > .port-input-element > PropertyField > Vector3IntField IntegerInput,
146+
#input-container > .port-input-element > PropertyField > Vector2IntField IntegerInput {
148147
min-width: 28px;
149148
}
150149

151-
#input-container > .port-input-element > * .unity-composite-field__field-spacer {
150+
#input-container > .port-input-element > PropertyField > * .unity-composite-field__field-spacer {
152151
flex-grow: 0.01;
153152
}
154153

@@ -167,7 +166,7 @@ ParameterNodeView #controls EnumField > VisualElement > VisualElement {
167166
margin: 0;
168167
}
169168

170-
#input-container > .port-input-element > ColorField {
169+
#input-container > .port-input-element > PropertyField > ColorField {
171170
width: 60px;
172171
}
173172

Assets/com.alelievr.NodeGraphProcessor/Editor/Utils/FieldFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace GraphProcessor
1212
{
13+
[Obsolete("Field Factory is not necessary anymore. You can use a SerializedProperty directly instead.")]
1314
public static class FieldFactory
1415
{
1516
static readonly Dictionary< Type, Type > fieldDrawers = new Dictionary< Type, Type >();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using UnityEngine;
2+
using UnityEditor;
3+
using UnityEditor.UIElements;
4+
using UnityEngine.UIElements;
5+
6+
namespace GraphProcessor
7+
{
8+
// We need a drawer to display Vector4 on a single line because by default it's a toggle
9+
[CustomPropertyDrawer(typeof(Vector4))]
10+
public class IngredientDrawerUIE : PropertyDrawer
11+
{
12+
public override VisualElement CreatePropertyGUI(SerializedProperty property)
13+
{
14+
var vectorField = new Vector4Field() { value = property.vector4Value };
15+
vectorField.RegisterValueChangedCallback(e => {
16+
property.vector4Value = e.newValue;
17+
});
18+
19+
return vectorField;
20+
}
21+
}
22+
}

Assets/com.alelievr.NodeGraphProcessor/Editor/Utils/Vector4Drawer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/com.alelievr.NodeGraphProcessor/Editor/Views/BaseGraphView.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,8 @@ int GetPriority(GraphElement e)
366366
RemoveElement(nodeView);
367367
if (Selection.activeObject == nodeInspector)
368368
UpdateNodeInspectorSelection();
369+
370+
SyncSerializedPropertyPathes();
369371
return true;
370372
case GroupView group:
371373
graph.RemoveGroup(group.group);
@@ -1386,6 +1388,16 @@ public RelayNodeView AddRelayNode(PortView inputPort, PortView outputPort, Vecto
13861388
return view;
13871389
}
13881390

1391+
/// <summary>
1392+
/// Update all the serialized property bindings (in case a node was deleted / added, the property pathes needs to be updated)
1393+
/// </summary>
1394+
public void SyncSerializedPropertyPathes()
1395+
{
1396+
foreach (var nodeView in nodeViews)
1397+
nodeView.SyncSerializedPropertyPathes();
1398+
nodeInspector.RefreshNodes();
1399+
}
1400+
13891401
/// <summary>
13901402
/// Call this function when you want to remove this view
13911403
/// </summary>

Assets/com.alelievr.NodeGraphProcessor/Editor/Views/BaseNodeView.cs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Collections;
99
using System.Linq;
1010
using UnityEditor.UIElements;
11+
using System.Text.RegularExpressions;
1112

1213
using Status = UnityEngine.UIElements.DropdownMenuAction.Status;
1314
using NodeView = UnityEditor.Experimental.GraphView.Node;
@@ -804,21 +805,37 @@ object GetInputFieldValue(FieldInfo info)
804805
protected VisualElement AddControlField(string fieldName, string label = null, bool showInputDrawer = false, Action valueChangedCallback = null)
805806
=> AddControlField(nodeTarget.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance), label, showInputDrawer, valueChangedCallback);
806807

808+
Regex s_ReplaceNodeIndexPropertyPath = new Regex(@"(^nodes.Array.data\[)(\d+)(\])");
809+
internal void SyncSerializedPropertyPathes()
810+
{
811+
int nodeIndex = owner.graph.nodes.FindIndex(n => n == nodeTarget);
812+
Debug.Log(nodeIndex);
813+
814+
// If the node is not found, then it means that it has been deleted from serialized data.
815+
if (nodeIndex == -1)
816+
return;
817+
818+
var nodeIndexString = nodeIndex.ToString();
819+
foreach (var propertyField in this.Query<PropertyField>().ToList())
820+
{
821+
propertyField.Unbind();
822+
// The property path look like this: nodes.Array.data[x].fieldName
823+
// And we want to update the value of x with the new node index:
824+
propertyField.bindingPath = s_ReplaceNodeIndexPropertyPath.Replace(propertyField.bindingPath, m => m.Groups[1].Value + nodeIndexString + m.Groups[3].Value);
825+
propertyField.Bind(owner.serializedGraph);
826+
}
827+
}
828+
807829
protected VisualElement AddControlField(FieldInfo field, string label = null, bool showInputDrawer = false, Action valueChangedCallback = null)
808830
{
809831
if (field == null)
810832
return null;
811-
812-
var element = FieldFactory.CreateField(field.FieldType, field.GetValue(nodeTarget), (newValue) => {
813-
owner.RegisterCompleteObjectUndo("Updated " + newValue);
814-
field.SetValue(nodeTarget, newValue);
815-
NotifyNodeChanged();
816-
valueChangedCallback?.Invoke();
817-
UpdateFieldVisibility(field.Name, newValue);
818-
// When you have the node inspector, it's possible to have multiple input fields pointing to the same
819-
// property. We need to update those manually otherwise they still have the old value in the inspector.
820-
UpdateOtherFieldValue(field, newValue);
821-
}, showInputDrawer ? "" : label);
833+
834+
// This doesn't work
835+
int i = owner.graph.nodes.FindIndex(n => n == nodeTarget);
836+
var prop = owner.serializedGraph.FindProperty("nodes").GetArrayElementAtIndex(i).FindPropertyRelative(field.Name);
837+
var element = new PropertyField(prop, showInputDrawer ? "" : label);
838+
element.Bind(owner.serializedGraph);
822839

823840
// Disallow picking scene objects when the graph is not linked to a scene
824841
if (element != null && !owner.graph.IsLinkedToScene())
@@ -843,9 +860,9 @@ protected VisualElement AddControlField(FieldInfo field, string label = null, bo
843860
}
844861
else
845862
{
846-
element.name = field.Name;
847863
controlsContainer.Add(element);
848864
}
865+
element.name = field.Name;
849866
}
850867
else
851868
{
@@ -886,6 +903,8 @@ protected void AddSettingField(FieldInfo field)
886903

887904
var label = field.GetCustomAttribute<SettingAttribute>().name;
888905

906+
// TODO: find the property path from the field
907+
// var element = new PropertyField();
889908
var element = FieldFactory.CreateField(field.FieldType, field.GetValue(nodeTarget), (newValue) => {
890909
owner.RegisterCompleteObjectUndo("Updated " + newValue);
891910
field.SetValue(nodeTarget, newValue);

Assets/com.alelievr.NodeGraphProcessor/Runtime/Graph/Attributes.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public NodeMenuItemAttribute(string menuTitle = null, Type onlyCompatibleWithGra
7979
/// Set a custom drawer for a field. It can then be created using the FieldFactory
8080
/// </summary>
8181
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
82+
[Obsolete("You can use the standard Unity CustomPropertyDrawer instead.")]
8283
public class FieldDrawerAttribute : Attribute
8384
{
8485
public Type fieldType;

Assets/com.alelievr.NodeGraphProcessor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "com.alelievr.node-graph-processor",
33
"displayName": "Node Graph Processor",
44
"version": "1.2.0",
5-
"unity": "2020.2",
5+
"unity": "2020.3",
66
"description": "Node graph editor framework focused on data processing using Unity UIElements and C# 4.7",
77
"keywords": [
88
"graph",

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1414
- Fixed the node create menu not listing all nodes when created from edge drag.
1515
- Fixed Int vector drawer display in nodes.
1616

17+
### Changed
18+
- Deprecated the FieldFactory and [FieldDrawer] system. You can use Unity's CustomPropertyDrawer instead.
19+
- SerializedProperties are now used to display the properties in the node, so they support Unity's default UI and attributes for all properties.
20+
1721
## [1.2.0]
1822

1923
### Added

0 commit comments

Comments
 (0)