1
0
mirror of https://github.com/Siccity/xNode.git synced 2026-02-06 07:14:56 +08:00

Added more nodes to LogicToy, improved editor code

This commit is contained in:
Thor Brigsted 2019-09-25 15:50:51 +02:00
parent c43fcbe542
commit 247377793c
14 changed files with 389 additions and 185 deletions

8
Examples/LogicToy.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9ac562a0423fff74ea984a2d355e4df9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -8,9 +8,18 @@ using XNode.Examples.LogicToy;
namespace XNodeEditor.Examples.LogicToy {
[CustomNodeGraphEditor(typeof(LogicGraph))]
public class LogicGraphEditor : NodeGraphEditor {
private class NoodleTimer {
public NodePort output, input;
readonly Color boolColor = new Color(0.1f, 0.6f, 0.6f);
private List<ObjectLastOnTimer> lastOnTimers = new List<ObjectLastOnTimer>();
private double lastFrame;
/// <summary> Used for tracking when an arbitrary object was last 'on' for fading effects </summary>
private class ObjectLastOnTimer {
public object obj;
public double lastOnTime;
public ObjectLastOnTimer(object obj, bool on) {
this.obj = obj;
}
}
/// <summary>
@ -26,16 +35,56 @@ namespace XNodeEditor.Examples.LogicToy {
public override void OnGUI() {
// Repaint each frame
window.Repaint();
// Timer
if (Event.current.type == EventType.Repaint) {
for (int i = 0; i < target.nodes.Count; i++) {
ITimerTick timerTick = target.nodes[i] as ITimerTick;
if (timerTick != null) {
float deltaTime = (float) (EditorApplication.timeSinceStartup - lastFrame);
timerTick.Tick(deltaTime);
}
}
}
lastFrame = EditorApplication.timeSinceStartup;
}
/// <summary> Controls graph noodle colors </summary>
public override Color GetNoodleColor(NodePort output, NodePort input) {
LogicNode node = output.node as LogicNode;
LogicNodeEditor nodeEditor = NodeEditor.GetEditor(node, window) as LogicNodeEditor;
Color baseColor = base.GetNoodleColor(output, input);
float t = (float) (EditorApplication.timeSinceStartup - nodeEditor.lastOnTime);
t *= 2f;
return Color.Lerp(Color.yellow, baseColor, t);
return GetLerpColor(baseColor, Color.yellow, output, (bool) node.GetValue(output));
}
/// <summary> Controls graph type colors </summary>
public override Color GetTypeColor(System.Type type) {
if (type == typeof(bool)) return boolColor;
else return GetTypeColor(type);
}
/// <summary> Returns the time at which an arbitrary object was last 'on' </summary>
public double GetLastOnTime(object obj, bool high) {
ObjectLastOnTimer timer = lastOnTimers.FirstOrDefault(x => x.obj == obj);
if (timer == null) {
timer = new ObjectLastOnTimer(obj, high);
lastOnTimers.Add(timer);
}
if (high) timer.lastOnTime = EditorApplication.timeSinceStartup;
return timer.lastOnTime;
}
/// <summary> Returns a color based on if or when an arbitrary object was last 'on' </summary>
public Color GetLerpColor(Color off, Color on, object obj, bool high) {
double lastOnTime = GetLastOnTime(obj, high);
if (high) return on;
else {
float t = (float) (EditorApplication.timeSinceStartup - lastOnTime);
t *= 8f;
if (t < 1) return Color.Lerp(on, off, t);
else return off;
}
}
}
}

View File

@ -1,17 +1,19 @@
using UnityEditor;
using UnityEngine;
using XNode;
using XNode.Examples.LogicToy;
namespace XNodeEditor.Examples.LogicToy {
[CustomNodeEditor(typeof(LogicNode))]
public class LogicNodeEditor : NodeEditor {
private LogicNode node;
public double lastOnTime;
private LogicGraphEditor graphEditor;
public override void OnHeaderGUI() {
// Initialization
if (node == null) {
node = target as LogicNode;
graphEditor = NodeGraphEditor.GetEditor(target.graph, window) as LogicGraphEditor;
}
base.OnHeaderGUI();
@ -19,16 +21,7 @@ namespace XNodeEditor.Examples.LogicToy {
dotRect.size = new Vector2(16, 16);
dotRect.y += 6;
if (node.on) {
GUI.color = Color.green;
lastOnTime = EditorApplication.timeSinceStartup;
} else {
float t = (float) (EditorApplication.timeSinceStartup - lastOnTime);
t *= 2f;
if (t < 1) {
GUI.color = Color.Lerp(Color.green, Color.red, t);
} else GUI.color = Color.red;
}
GUI.color = graphEditor.GetLerpColor(Color.red, Color.green, node, node.led);
GUI.DrawTexture(dotRect, NodeEditorResources.dot);
GUI.color = Color.white;
}

View File

@ -1,27 +0,0 @@
using UnityEditor;
using UnityEngine;
using XNode.Examples.LogicToy;
namespace XNodeEditor.Examples.LogicToy {
[CustomNodeEditor(typeof(PulseNode))]
public class PulseNodeEditor : LogicNodeEditor {
private PulseNode node;
public override void OnBodyGUI() {
// Initialization
if (node == null) {
node = target as PulseNode;
lastOnTime = EditorApplication.timeSinceStartup;
}
// Timer
if (EditorApplication.timeSinceStartup - lastOnTime > node.interval) {
lastOnTime = EditorApplication.timeSinceStartup;
node.FirePulse();
}
// Basic GUI
base.OnBodyGUI();
}
}
}

View File

@ -14,9 +14,11 @@ MonoBehaviour:
nodes:
- {fileID: 114046633862954194}
- {fileID: 114880916489599218}
- {fileID: 114572916788169214}
- {fileID: 114104949491275850}
- {fileID: 114524369431968588}
- {fileID: 114945579453429622}
- {fileID: 114944478030018250}
- {fileID: 114194736576219100}
- {fileID: 114558631167130670}
- {fileID: 114481634605117190}
--- !u!114 &114046633862954194
MonoBehaviour:
m_ObjectHideFlags: 0
@ -29,29 +31,104 @@ MonoBehaviour:
m_Name: Pulse
m_EditorClassIdentifier:
graph: {fileID: 11400000}
position: {x: -248, y: -88}
position: {x: -264, y: -248}
ports:
keys:
- output
values:
- _fieldName: output
_node: {fileID: 114046633862954194}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: input
node: {fileID: 114880916489599218}
reroutePoints: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
interval: 2
output: 0
--- !u!114 &114194736576219100
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7d4066122e5859498bbf1f1db2593cf, type: 3}
m_Name: Toggle
m_EditorClassIdentifier:
graph: {fileID: 11400000}
position: {x: -72, y: -8}
ports:
keys:
- input
- output
values:
- _fieldName: input
_node: {fileID: 114194736576219100}
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: output
node: {fileID: 114944478030018250}
reroutePoints: []
- fieldName: output
node: {fileID: 114481634605117190}
reroutePoints: []
_direction: 0
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
- _fieldName: output
_node: {fileID: 114194736576219100}
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: input
node: {fileID: 114524369431968588}
node: {fileID: 114945579453429622}
reroutePoints: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
input: 0
output: 0
--- !u!114 &114481634605117190
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 54822dcd4ea0525409ad71a5fa416755, type: 3}
m_Name: Pulse
m_EditorClassIdentifier:
graph: {fileID: 11400000}
position: {x: -264, y: 72}
ports:
keys:
- output
values:
- _fieldName: output
_node: {fileID: 114481634605117190}
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: input
node: {fileID: 114194736576219100}
reroutePoints: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
interval: 1
output: {fileID: 0}
--- !u!114 &114104949491275850
output: 0
--- !u!114 &114558631167130670
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -63,120 +140,35 @@ MonoBehaviour:
m_Name: Toggle
m_EditorClassIdentifier:
graph: {fileID: 11400000}
position: {x: 264, y: -40}
position: {x: 312, y: -88}
ports:
keys:
- input
- output
values:
- _fieldName: input
_node: {fileID: 114104949491275850}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
_node: {fileID: 114558631167130670}
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: output
node: {fileID: 114572916788169214}
node: {fileID: 114945579453429622}
reroutePoints: []
_direction: 0
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
- _fieldName: output
_node: {fileID: 114104949491275850}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
_node: {fileID: 114558631167130670}
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
input: {fileID: 0}
output: {fileID: 0}
--- !u!114 &114524369431968588
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7d4066122e5859498bbf1f1db2593cf, type: 3}
m_Name: Toggle
m_EditorClassIdentifier:
graph: {fileID: 11400000}
position: {x: -56, y: -8}
ports:
keys:
- input
- output
values:
- _fieldName: input
_node: {fileID: 114524369431968588}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
connections:
- fieldName: output
node: {fileID: 114046633862954194}
reroutePoints: []
_direction: 0
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
- _fieldName: output
_node: {fileID: 114524369431968588}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
connections: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
input: {fileID: 0}
output: {fileID: 0}
--- !u!114 &114572916788169214
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7d4066122e5859498bbf1f1db2593cf, type: 3}
m_Name: Toggle
m_EditorClassIdentifier:
graph: {fileID: 11400000}
position: {x: 88, y: -168}
ports:
keys:
- input
- output
values:
- _fieldName: input
_node: {fileID: 114572916788169214}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
connections:
- fieldName: output
node: {fileID: 114880916489599218}
reroutePoints: []
_direction: 0
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
- _fieldName: output
_node: {fileID: 114572916788169214}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
connections:
- fieldName: input
node: {fileID: 114104949491275850}
reroutePoints: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
input: {fileID: 0}
output: {fileID: 0}
input: 0
output: 0
--- !u!114 &114880916489599218
MonoBehaviour:
m_ObjectHideFlags: 0
@ -197,8 +189,8 @@ MonoBehaviour:
values:
- _fieldName: input
_node: {fileID: 114880916489599218}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: output
node: {fileID: 114046633862954194}
@ -209,15 +201,93 @@ MonoBehaviour:
_dynamic: 0
- _fieldName: output
_node: {fileID: 114880916489599218}
_typeQualifiedName: XNode.Examples.LogicToy.LogicNode, Assembly-CSharp, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: input
node: {fileID: 114572916788169214}
node: {fileID: 114945579453429622}
reroutePoints: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
input: {fileID: 0}
output: {fileID: 0}
input: 0
output: 0
--- !u!114 &114944478030018250
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 54822dcd4ea0525409ad71a5fa416755, type: 3}
m_Name: Pulse
m_EditorClassIdentifier:
graph: {fileID: 11400000}
position: {x: -264, y: -88}
ports:
keys:
- output
values:
- _fieldName: output
_node: {fileID: 114944478030018250}
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: input
node: {fileID: 114194736576219100}
reroutePoints: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
interval: 1
output: 0
--- !u!114 &114945579453429622
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c88b3b7abe7eb324baec5d03dfa998ab, type: 3}
m_Name: And
m_EditorClassIdentifier:
graph: {fileID: 11400000}
position: {x: 120, y: -88}
ports:
keys:
- input
- output
values:
- _fieldName: input
_node: {fileID: 114945579453429622}
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: output
node: {fileID: 114194736576219100}
reroutePoints: []
- fieldName: output
node: {fileID: 114880916489599218}
reroutePoints: []
_direction: 0
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
- _fieldName: output
_node: {fileID: 114945579453429622}
_typeQualifiedName: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
connections:
- fieldName: input
node: {fileID: 114558631167130670}
reroutePoints: []
_direction: 1
_connectionType: 0
_typeConstraint: 0
_dynamic: 0
input: 0
output: 0

View File

@ -0,0 +1,5 @@
namespace XNode.Examples.LogicToy {
public interface ITimerTick {
void Tick(float timeDelta);
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 16a713ef662e1bd4086b83032f1d97c9
guid: 46533d584cdbed04db785406b8361397
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -0,0 +1,25 @@
using System.Linq;
using UnityEngine;
namespace XNode.Examples.LogicToy {
[NodeWidth(140)]
public class AndNode : LogicNode {
[Input] public bool input;
[Output] public bool output;
public override bool led { get { return output; } }
protected override void OnInputChanged() {
bool newInput = GetPort("input").GetInputValues<bool>().All(x => x);
if (input != newInput) {
input = newInput;
output = newInput;
SendSignal(GetPort("output"));
}
}
public override object GetValue(NodePort port) {
return output;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c88b3b7abe7eb324baec5d03dfa998ab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,22 +1,31 @@
namespace XNode.Examples.LogicToy {
using System;
using UnityEngine;
namespace XNode.Examples.LogicToy {
/// <summary> Base node for the LogicToy system </summary>
public abstract class LogicNode : Node {
public abstract bool on { get; }
public Action onStateChange;
public abstract bool led { get; }
protected abstract void OnTrigger();
public void SendPulse(NodePort port) {
public void SendSignal(NodePort output) {
// Loop through port connections
int connectionCount = port.ConnectionCount;
int connectionCount = output.ConnectionCount;
for (int i = 0; i < connectionCount; i++) {
NodePort connectedPort = port.GetConnection(i);
NodePort connectedPort = output.GetConnection(i);
// Get connected ports logic node
LogicNode logicNode = connectedPort.node as LogicNode;
LogicNode connectedNode = connectedPort.node as LogicNode;
// Trigger it
if (logicNode != null) logicNode.OnTrigger();
if (connectedNode != null) connectedNode.OnInputChanged();
}
if (onStateChange != null) onStateChange();
}
protected abstract void OnInputChanged();
public override void OnCreateConnection(NodePort from, NodePort to) {
OnInputChanged();
}
}
}

View File

@ -0,0 +1,25 @@
using System.Linq;
using UnityEngine;
namespace XNode.Examples.LogicToy {
[NodeWidth(140)]
public class NotNode : LogicNode {
[Input] public bool input;
[Output] public bool output = true;
public override bool led { get { return output; } }
protected override void OnInputChanged() {
bool newInput = GetPort("input").GetInputValues<bool>().Any(x => x);
if (input != newInput) {
input = newInput;
output = !newInput;
SendSignal(GetPort("output"));
}
}
public override object GetValue(NodePort port) {
return output;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c4bb0f0e96df60a4690ca03082a93b44
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,16 +1,31 @@
namespace XNode.Examples.LogicToy {
[NodeWidth(140)]
public class PulseNode : LogicNode {
public float interval = 1f;
[Output] public LogicNode output;
public override bool on { get { return false; } }
using UnityEngine;
/// <summary> Called from editor </summary>
public void FirePulse() {
SendPulse(GetPort("output"));
namespace XNode.Examples.LogicToy {
[NodeWidth(140)]
public class PulseNode : LogicNode, ITimerTick {
public float interval = 1f;
[Output] public bool output;
public override bool led { get { return output; } }
private float timer;
public void Tick(float deltaTime) {
timer += deltaTime;
if (!output && timer > interval) {
timer -= interval;
output = true;
SendSignal(GetPort("output"));
} else if (output) {
output = false;
SendSignal(GetPort("output"));
}
}
/// <summary> This node has no inputs, so this does nothing </summary>
protected override void OnTrigger() { }
/// <summary> This node can not receive signals, so this is not used </summary>
protected override void OnInputChanged() { }
public override object GetValue(NodePort port) {
return output;
}
}
}

View File

@ -1,17 +1,27 @@
using UnityEngine;
using System.Linq;
using UnityEngine;
namespace XNode.Examples.LogicToy {
[NodeWidth(140)]
public class ToggleNode : LogicNode {
private bool _on;
[Input] public LogicNode input;
[Output] public LogicNode output;
public override bool on { get { return _on; } }
[Input] public bool input;
[Output] public bool output;
public override bool led { get { return output; } }
/// <summary> This node has no inputs, so this does nothing </summary>
protected override void OnTrigger() {
_on = !_on;
if (on) SendPulse(GetPort("output"));
protected override void OnInputChanged() {
bool newInput = GetPort("input").GetInputValues<bool>().Any(x => x);
if (!input && newInput) {
input = newInput;
output = !output;
SendSignal(GetPort("output"));
} else if (input && !newInput) {
input = newInput;
}
}
public override object GetValue(NodePort port) {
return output;
}
}
}