Comments (1)
Thanks to Sheepy in the discord for pointing me in the rght direction I've managed to resolve this a different route.
Here's my code:
using System.Collections.Generic;
using System.Reflection;
using GraphProcessor;
using UnityEngine;
[System.Serializable]
public abstract class BaseActionNode<T> : BaseNode where T : TeleAction
{
[Input(name = "In")]
public ICollection<TeleAction> input;
[Input("Action Data")]
public Dictionary<string, object> actionData = new Dictionary<string, object>();
[Output(name = "Out")]
public ICollection<TeleAction> output;
[SerializeField] public T action;
public override bool isRenamable => true;
private bool IsStartNode => this.GetPort("input", null).GetEdges().Count == 0;
protected override void Process()
{
if (IsStartNode) input = new List<TeleAction>();
UpdateActionWithCustomPortData();
T actionClone = System.Activator.CreateInstance(typeof(T), action) as T;
input.Add(actionClone);
output = input;
}
protected virtual void UpdateActionWithCustomPortData()
{
// We clone due to reference issues
Dictionary<string, object> actionDataClone = new Dictionary<string, object>(actionData);
foreach (var field in GetInputFieldsOfAction())
{
if (!actionDataClone.ContainsKey(field.fieldInfo.Name))
{
field.fieldInfo.SetValue(action, default);
}
else
{
field.fieldInfo.SetValue(action, actionDataClone[field.fieldInfo.Name]);
}
}
actionData.Clear();
}
#region Reflection Generation Of Ports
private List<FieldPortInfo> GetInputFieldsOfAction()
{
List<FieldPortInfo> foundInputFields = new List<FieldPortInfo>();
foreach (var field in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
{
foreach (var attribute in field.GetCustomAttributes(typeof(InputAttribute), true))
{
if (attribute.GetType() != typeof(InputAttribute)) continue;
foundInputFields.Add(new FieldPortInfo(field, attribute as InputAttribute));
break;
}
}
return foundInputFields;
}
[CustomPortInput(nameof(actionData), typeof(object))]
protected void PullInputs(List<SerializableEdge> connectedEdges)
{
if (actionData == null) actionData = new Dictionary<string, object>();
foreach (SerializableEdge t in connectedEdges)
{
actionData.Add(t.inputPortIdentifier, t.passThroughBuffer);
}
}
[CustomPortBehavior(nameof(actionData))]
protected IEnumerable<PortData> ActionDataBehaviour(List<SerializableEdge> edges)
{
foreach (var field in GetInputFieldsOfAction())
{
yield return new PortData
{
displayName = field.inputAttribute.name,
displayType = field.fieldInfo.FieldType,
identifier = field.fieldInfo.Name,
acceptMultipleEdges = false,
};
}
}
#endregion
}
public struct FieldPortInfo
{
public FieldInfo fieldInfo;
public InputAttribute inputAttribute;
public FieldPortInfo(FieldInfo fieldInfo, InputAttribute inputAttribute)
{
this.fieldInfo = fieldInfo;
this.inputAttribute = inputAttribute;
}
}
With this code I'm able to get fields from a class inheriting from TeleAction with the Input attribute. I then use those fields to dynamically add input ports in the editor. I then take the data from those ports and update my action via reflection.
This is generic so any TeleAction type can have a node by just creating a child class. One thing to note if doing this yourself is that for the "CustomPortBehavior" & "CustomPortInput" methods to work in the children they need to be at least "protection" level methods.
NODE Script
using GraphProcessor;
[System.Serializable, NodeMenuItem("Custom/BoolActionNode")]
public class BoolActionNode : BaseActionNode<BoolDecisionAction>
{
public override string name => "BoolActionNode";
}
Relevant TeleAction
public class BoolDecisionAction : DecisionAction<BoolVariable[]>
{
[SerializeField, Input("Decision")] protected BoolVariable[] decisionObject;
[Input("True Actions"), SerializeReference] protected List<TeleAction> trueActions;
[Input("False Actions"), SerializeReference] protected List<TeleAction> falseActions;
public override IEnumerator DoAction(IOriginator originator) {}
}
This way I only have to edit the TeleAction file, no cross-referencing or missing a variable because I edited one file and not the other.
from nodegraphprocessor.
Related Issues (20)
- Node categories
- CustomPortBehaviour With PropertyDrawer HOT 1
- Undo break dynamic output
- Default input and output parameters
- Is there a way to move port and parameter text locations?
- Undo will lose all group view ! HOT 3
- Nothing shows up in the context menu upon import.
- Is this project abandoned? HOT 15
- Calling `AddExposedParameter` in `BaseGraph.OnEnable` causes all ports and edges to disappear. HOT 3
- CustomPortBehavior from base class not respected.
- This asset causes large delays for entering playmode and recompiling assemblies
- Expanding Exposed Parameter Resets Name
- `FilterCreateNodeMenuEntries` Not working when I create Node by drag HOT 1
- I cant set the value in Parameter Window
- Huge GC alloc, sky high Cpu spikes, almost unusable at runtime
- 关于黑板变量赋值被锁定的问题
- Node in stack can't be dragged out and are stuck HOT 1
- Visual glitches on edges when they're bent at ~180 degrees HOT 1
- Leting user to edit graph in game mode
- ForNode can't work together with WaitNode
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nodegraphprocessor.