EVERYTHING
This commit is contained in:
@@ -0,0 +1,934 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using BlockSpace.Voxels;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class Node : MonoBehaviour
|
||||
{
|
||||
private const float PortHighlightScale = 1.25f;
|
||||
|
||||
private const float PortPulseScale = 0.22f;
|
||||
|
||||
private const float PortPulseDuration = 0.16f;
|
||||
|
||||
private const float SelectedScale = 1.035f;
|
||||
|
||||
private static readonly Color SelectedTextColor = new Color(0.55f, 0.92f, 1f, 1f);
|
||||
|
||||
[Header("Identity")]
|
||||
[SerializeField]
|
||||
private int nodeId;
|
||||
|
||||
[Header("Definition")]
|
||||
public NodeDefinition Definition;
|
||||
|
||||
[Header("Runtime")]
|
||||
public List<NodePort> InputPorts = new List<NodePort>();
|
||||
|
||||
public List<NodePort> OutputPorts = new List<NodePort>();
|
||||
|
||||
private NodeBehavior behavior;
|
||||
|
||||
private NodeGraphManager graphManager;
|
||||
|
||||
private bool selected;
|
||||
|
||||
private bool visibleInEditMode = true;
|
||||
|
||||
private readonly List<NodeSerializedConnection> pendingSerializedConnections = new List<NodeSerializedConnection>();
|
||||
|
||||
private readonly Dictionary<string, BSValue> pendingInputValues = new Dictionary<string, BSValue>(StringComparer.Ordinal);
|
||||
|
||||
private readonly Dictionary<string, BSValue> pendingOutputValues = new Dictionary<string, BSValue>(StringComparer.Ordinal);
|
||||
|
||||
private readonly List<TMP_Text> cachedPortTexts = new List<TMP_Text>();
|
||||
|
||||
private readonly Dictionary<TMP_Text, Color> defaultTextColors = new Dictionary<TMP_Text, Color>();
|
||||
|
||||
private readonly List<Renderer> cachedRenderers = new List<Renderer>();
|
||||
|
||||
private Vector3 defaultScale = Vector3.one;
|
||||
|
||||
[Header("Node Name")]
|
||||
public TMP_Text NodeNameText;
|
||||
|
||||
[Header("Boards")]
|
||||
public GameObject SmallBoard;
|
||||
|
||||
public GameObject MediumBoard;
|
||||
|
||||
public GameObject LargeBoard;
|
||||
|
||||
public GameObject ExtraLargeBoard;
|
||||
|
||||
[Header("Input Port Parents")]
|
||||
public Transform InputRunPortParent;
|
||||
|
||||
public Transform InputValuePortParent;
|
||||
|
||||
[Header("Output Port Parents")]
|
||||
public Transform OutputRunPortParent;
|
||||
|
||||
public Transform OutputValuePortParent;
|
||||
|
||||
[Header("Input Text Parent")]
|
||||
public Transform InputTextParent;
|
||||
|
||||
[Header("Output Text Parent")]
|
||||
public Transform OutputTextParent;
|
||||
|
||||
[Header("Port Prefabs")]
|
||||
public GameObject InputRunPortPrefab;
|
||||
|
||||
public GameObject InputValuePortPrefab;
|
||||
|
||||
public GameObject OutputRunPortPrefab;
|
||||
|
||||
public GameObject OutputValuePortPrefab;
|
||||
|
||||
[Header("Text Prefab")]
|
||||
public TMP_Text PortTextPrefab;
|
||||
|
||||
[Header("Port Layout")]
|
||||
public float FirstPortY;
|
||||
|
||||
public float PortYOffset = -1.25f;
|
||||
|
||||
[Header("Text Layout")]
|
||||
public float FirstTextY = 0.0869f;
|
||||
|
||||
public float TextYOffset = -0.0618f;
|
||||
|
||||
private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor");
|
||||
|
||||
private static readonly int ColorId = Shader.PropertyToID("_Color");
|
||||
|
||||
private static readonly int TintColorId = Shader.PropertyToID("_TintColor");
|
||||
|
||||
public NodeBoardSize BoardSize { get; private set; }
|
||||
|
||||
public int NodeId => nodeId;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
defaultScale = base.transform.localScale;
|
||||
CaptureSerializedRuntimeState();
|
||||
ReinitializeFromDefinition();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
NodeGraphManager.Instance?.RegisterNode(this);
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
UpdatePortVisualState();
|
||||
UpdatePortTintState();
|
||||
}
|
||||
|
||||
public void AssignGraph(NodeGraphManager manager)
|
||||
{
|
||||
graphManager = manager;
|
||||
for (int i = 0; i < InputPorts.Count; i++)
|
||||
{
|
||||
InputPorts[i].Owner = this;
|
||||
}
|
||||
for (int j = 0; j < OutputPorts.Count; j++)
|
||||
{
|
||||
OutputPorts[j].Owner = this;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNodeId(int id)
|
||||
{
|
||||
nodeId = Mathf.Max(0, id);
|
||||
}
|
||||
|
||||
public void ReinitializeFromDefinition()
|
||||
{
|
||||
if (Definition == null)
|
||||
{
|
||||
InputPorts.Clear();
|
||||
OutputPorts.Clear();
|
||||
ClearVisualCaches();
|
||||
return;
|
||||
}
|
||||
BuildPorts();
|
||||
BoardSize = Definition.GetBoardSize();
|
||||
BuildVisuals();
|
||||
CreateBehavior();
|
||||
ApplySelectionVisual();
|
||||
ApplyVisibility();
|
||||
}
|
||||
|
||||
public bool TryGetPort(string portName, PortDirection direction, out NodePort port)
|
||||
{
|
||||
List<NodePort> list = ((direction == PortDirection.Input) ? InputPorts : OutputPorts);
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
NodePort nodePort = list[i];
|
||||
if (nodePort != null && string.Equals(nodePort.Name, portName, StringComparison.Ordinal))
|
||||
{
|
||||
port = nodePort;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
port = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetPort(string portName, PortDirection direction, PortKind kind, out NodePort port)
|
||||
{
|
||||
if (TryGetPort(portName, direction, out port) && port.Kind == kind)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
port = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public BSValue GetInputValue(string portName)
|
||||
{
|
||||
if (!TryGetPort(portName, PortDirection.Input, PortKind.Value, out var port))
|
||||
{
|
||||
return BSValue.None;
|
||||
}
|
||||
return port.Value;
|
||||
}
|
||||
|
||||
public BSValue GetOutputValue(string portName)
|
||||
{
|
||||
if (!TryGetPort(portName, PortDirection.Output, PortKind.Value, out var port))
|
||||
{
|
||||
return BSValue.None;
|
||||
}
|
||||
return port.Value;
|
||||
}
|
||||
|
||||
public bool TryGetInputGroup(string portName, out VoxelGroup group)
|
||||
{
|
||||
group = null;
|
||||
if (TryGetPort(portName, PortDirection.Input, PortKind.Value, out var port))
|
||||
{
|
||||
return port.Value.TryResolveGroup(out group);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public VoxelGroup GetInputGroup(string portName)
|
||||
{
|
||||
TryGetInputGroup(portName, out var group);
|
||||
return group;
|
||||
}
|
||||
|
||||
public void SetInputValue(string portName, BSValue value)
|
||||
{
|
||||
if (TryGetPort(portName, PortDirection.Input, PortKind.Value, out var port))
|
||||
{
|
||||
if (graphManager != null)
|
||||
{
|
||||
graphManager.AssignInputValue(this, port, value, broadcast: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetInputValueLocal(port, value, pulsePort: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetOutputValue(string portName, BSValue value)
|
||||
{
|
||||
if (TryGetPort(portName, PortDirection.Output, PortKind.Value, out var port))
|
||||
{
|
||||
if (graphManager != null)
|
||||
{
|
||||
graphManager.ApplyOutputValue(this, port, value, broadcast: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetOutputValueLocal(port, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetOutputValueLocalOnly(string portName, BSValue value)
|
||||
{
|
||||
if (TryGetPort(portName, PortDirection.Output, PortKind.Value, out var port))
|
||||
{
|
||||
if (graphManager != null)
|
||||
{
|
||||
graphManager.ApplyOutputValue(this, port, value, broadcast: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetOutputValueLocal(port, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerRun(string outputPortName)
|
||||
{
|
||||
if (TryGetPort(outputPortName, PortDirection.Output, PortKind.Run, out var port))
|
||||
{
|
||||
if (graphManager != null)
|
||||
{
|
||||
graphManager.TriggerOutputRun(this, port, broadcast: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
TriggerRunLocal(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ReceiveRun(string inputPortName)
|
||||
{
|
||||
if (TryGetPort(inputPortName, PortDirection.Input, PortKind.Run, out var port))
|
||||
{
|
||||
PulsePort(port);
|
||||
behavior?.OnRun(inputPortName);
|
||||
}
|
||||
}
|
||||
|
||||
public void TickBehavior()
|
||||
{
|
||||
behavior?.OnGraphUpdate();
|
||||
}
|
||||
|
||||
public bool Connect(string outputPortName, Node targetNode, string inputPortName)
|
||||
{
|
||||
if (graphManager == null || targetNode == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return graphManager.Connect(this, outputPortName, targetNode, inputPortName, broadcast: true);
|
||||
}
|
||||
|
||||
public void Disconnect(string outputPortName, Node targetNode, string inputPortName)
|
||||
{
|
||||
if (!(graphManager == null) && !(targetNode == null))
|
||||
{
|
||||
graphManager.Disconnect(this, outputPortName, targetNode, inputPortName, broadcast: true);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSelected(bool isSelected)
|
||||
{
|
||||
if (selected != isSelected)
|
||||
{
|
||||
selected = isSelected;
|
||||
ApplySelectionVisual();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetVisibleInEditMode(bool visible)
|
||||
{
|
||||
if (visibleInEditMode != visible)
|
||||
{
|
||||
visibleInEditMode = visible;
|
||||
ApplyVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
public Bounds GetWorldBounds()
|
||||
{
|
||||
if (cachedRenderers.Count == 0)
|
||||
{
|
||||
CacheVisuals();
|
||||
}
|
||||
if (cachedRenderers.Count == 0)
|
||||
{
|
||||
return new Bounds(base.transform.position, Vector3.one * 0.2f);
|
||||
}
|
||||
Bounds result = new Bounds(cachedRenderers[0].bounds.center, cachedRenderers[0].bounds.size);
|
||||
for (int i = 1; i < cachedRenderers.Count; i++)
|
||||
{
|
||||
if (cachedRenderers[i] != null)
|
||||
{
|
||||
result.Encapsulate(cachedRenderers[i].bounds);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Vector3 GetPortWorldPosition(NodePort port)
|
||||
{
|
||||
if (port != null && port.VisualTransform != null)
|
||||
{
|
||||
return port.VisualTransform.position;
|
||||
}
|
||||
return base.transform.position;
|
||||
}
|
||||
|
||||
public Vector3 GetPortWorldDirection(NodePort port)
|
||||
{
|
||||
if (port == null)
|
||||
{
|
||||
return base.transform.forward;
|
||||
}
|
||||
if (port.VisualTransform != null)
|
||||
{
|
||||
if (port.Direction != PortDirection.Output)
|
||||
{
|
||||
return -port.VisualTransform.right;
|
||||
}
|
||||
return port.VisualTransform.right;
|
||||
}
|
||||
if (port.Direction != PortDirection.Output)
|
||||
{
|
||||
return -base.transform.right;
|
||||
}
|
||||
return base.transform.right;
|
||||
}
|
||||
|
||||
internal void SetInputValueLocal(NodePort port, BSValue value, bool pulsePort)
|
||||
{
|
||||
if (port != null && port.Direction == PortDirection.Input && port.Kind == PortKind.Value)
|
||||
{
|
||||
BSValue bSValue = value.Normalize();
|
||||
bool num = !BSValueEquals(port.Value, bSValue);
|
||||
port.Value = bSValue;
|
||||
UpdatePortLabel(port);
|
||||
if (pulsePort)
|
||||
{
|
||||
PulsePort(port);
|
||||
}
|
||||
if (num)
|
||||
{
|
||||
behavior?.OnInputValueChanged(port.Name, port.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetOutputValueLocal(NodePort port, BSValue value)
|
||||
{
|
||||
if (port == null || port.Direction != PortDirection.Output || port.Kind != PortKind.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
port.Value = value.Normalize();
|
||||
UpdatePortLabel(port);
|
||||
PulsePort(port);
|
||||
for (int i = 0; i < port.Connections.Count; i++)
|
||||
{
|
||||
NodePort nodePort = port.Connections[i];
|
||||
if (nodePort != null && !(nodePort.Owner == null))
|
||||
{
|
||||
nodePort.Owner.SetInputValueLocal(nodePort, port.Value, pulsePort: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void TriggerRunLocal(NodePort port)
|
||||
{
|
||||
if (port == null || port.Direction != PortDirection.Output || port.Kind != PortKind.Run)
|
||||
{
|
||||
return;
|
||||
}
|
||||
PulsePort(port);
|
||||
for (int i = 0; i < port.Connections.Count; i++)
|
||||
{
|
||||
NodePort nodePort = port.Connections[i];
|
||||
if (nodePort != null && !(nodePort.Owner == null))
|
||||
{
|
||||
nodePort.Owner.ReceiveRun(nodePort.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void PulsePort(NodePort port)
|
||||
{
|
||||
if (port != null)
|
||||
{
|
||||
port.PulseUntil = Mathf.Max(port.PulseUntil, Time.unscaledTime + 0.16f);
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetPortHighlight(NodePort port, bool highlighted)
|
||||
{
|
||||
if (port != null)
|
||||
{
|
||||
port.Highlighted = highlighted;
|
||||
}
|
||||
}
|
||||
|
||||
internal List<NodeSerializedConnection> ConsumePendingSerializedConnections()
|
||||
{
|
||||
List<NodeSerializedConnection> result = new List<NodeSerializedConnection>(pendingSerializedConnections);
|
||||
pendingSerializedConnections.Clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void CaptureSerializedRuntimeState()
|
||||
{
|
||||
pendingSerializedConnections.Clear();
|
||||
pendingInputValues.Clear();
|
||||
pendingOutputValues.Clear();
|
||||
CapturePortState(InputPorts, pendingInputValues, captureConnections: false);
|
||||
CapturePortState(OutputPorts, pendingOutputValues, captureConnections: true);
|
||||
}
|
||||
|
||||
private void CapturePortState(List<NodePort> ports, Dictionary<string, BSValue> valueStore, bool captureConnections)
|
||||
{
|
||||
if (ports == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < ports.Count; i++)
|
||||
{
|
||||
NodePort nodePort = ports[i];
|
||||
if (nodePort == null || string.IsNullOrEmpty(nodePort.Name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
valueStore[nodePort.Name] = nodePort.Value.Normalize();
|
||||
if (!captureConnections || nodePort.Direction != PortDirection.Output || nodePort.Connections == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < nodePort.Connections.Count; j++)
|
||||
{
|
||||
NodePort nodePort2 = nodePort.Connections[j];
|
||||
if (nodePort2 != null && !(nodePort2.Owner == null) && !string.IsNullOrEmpty(nodePort2.Name))
|
||||
{
|
||||
pendingSerializedConnections.Add(new NodeSerializedConnection
|
||||
{
|
||||
outputPortName = nodePort.Name,
|
||||
inputNode = nodePort2.Owner,
|
||||
inputPortName = nodePort2.Name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildPorts()
|
||||
{
|
||||
InputPorts.Clear();
|
||||
OutputPorts.Clear();
|
||||
for (int i = 0; i < Definition.InputPorts.Count; i++)
|
||||
{
|
||||
NodePortDefinition nodePortDefinition = Definition.InputPorts[i];
|
||||
pendingInputValues.TryGetValue(nodePortDefinition.PortName, out var value);
|
||||
InputPorts.Add(new NodePort
|
||||
{
|
||||
Index = i,
|
||||
Name = nodePortDefinition.PortName,
|
||||
Direction = PortDirection.Input,
|
||||
Kind = nodePortDefinition.Kind,
|
||||
Value = (value.IsInitialized ? value.Normalize() : BSValue.FromText(nodePortDefinition.DefaultValue)),
|
||||
Owner = this
|
||||
});
|
||||
}
|
||||
for (int j = 0; j < Definition.OutputPorts.Count; j++)
|
||||
{
|
||||
NodePortDefinition nodePortDefinition2 = Definition.OutputPorts[j];
|
||||
pendingOutputValues.TryGetValue(nodePortDefinition2.PortName, out var value2);
|
||||
OutputPorts.Add(new NodePort
|
||||
{
|
||||
Index = j,
|
||||
Name = nodePortDefinition2.PortName,
|
||||
Direction = PortDirection.Output,
|
||||
Kind = nodePortDefinition2.Kind,
|
||||
Value = (value2.IsInitialized ? value2.Normalize() : BSValue.FromText(nodePortDefinition2.DefaultValue)),
|
||||
Owner = this
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildVisuals()
|
||||
{
|
||||
ApplyBoardSize();
|
||||
ApplyNodeName();
|
||||
ClearChildren(InputRunPortParent);
|
||||
ClearChildren(InputValuePortParent);
|
||||
ClearChildren(OutputRunPortParent);
|
||||
ClearChildren(OutputValuePortParent);
|
||||
ClearChildren(InputTextParent);
|
||||
ClearChildren(OutputTextParent);
|
||||
ClearVisualCaches();
|
||||
BuildInputVisuals();
|
||||
BuildOutputVisuals();
|
||||
CacheVisuals();
|
||||
}
|
||||
|
||||
private void ApplyBoardSize()
|
||||
{
|
||||
if (SmallBoard != null)
|
||||
{
|
||||
SmallBoard.SetActive(value: false);
|
||||
}
|
||||
if (MediumBoard != null)
|
||||
{
|
||||
MediumBoard.SetActive(value: false);
|
||||
}
|
||||
if (LargeBoard != null)
|
||||
{
|
||||
LargeBoard.SetActive(value: false);
|
||||
}
|
||||
if (ExtraLargeBoard != null)
|
||||
{
|
||||
ExtraLargeBoard.SetActive(value: false);
|
||||
}
|
||||
switch (BoardSize)
|
||||
{
|
||||
case NodeBoardSize.Small:
|
||||
if (SmallBoard != null)
|
||||
{
|
||||
SmallBoard.SetActive(value: true);
|
||||
}
|
||||
break;
|
||||
case NodeBoardSize.Medium:
|
||||
if (MediumBoard != null)
|
||||
{
|
||||
MediumBoard.SetActive(value: true);
|
||||
}
|
||||
break;
|
||||
case NodeBoardSize.Large:
|
||||
if (LargeBoard != null)
|
||||
{
|
||||
LargeBoard.SetActive(value: true);
|
||||
}
|
||||
break;
|
||||
case NodeBoardSize.ExtraLarge:
|
||||
if (ExtraLargeBoard != null)
|
||||
{
|
||||
ExtraLargeBoard.SetActive(value: true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyNodeName()
|
||||
{
|
||||
if (NodeNameText != null)
|
||||
{
|
||||
NodeNameText.text = ((Definition != null) ? Definition.NodeName : "Node");
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildInputVisuals()
|
||||
{
|
||||
for (int i = 0; i < InputPorts.Count; i++)
|
||||
{
|
||||
NodePort nodePort = InputPorts[i];
|
||||
bool num = nodePort.Kind == PortKind.Run;
|
||||
Transform transform = (num ? InputRunPortParent : InputValuePortParent);
|
||||
GameObject gameObject = (num ? InputRunPortPrefab : InputValuePortPrefab);
|
||||
if (!(transform == null) && !(gameObject == null))
|
||||
{
|
||||
GameObject gameObject2 = UnityEngine.Object.Instantiate(gameObject, transform);
|
||||
gameObject2.name = nodePort.Name;
|
||||
Vector3 localPosition = gameObject2.transform.localPosition;
|
||||
localPosition.y = FirstPortY + PortYOffset * (float)i;
|
||||
gameObject2.transform.localPosition = localPosition;
|
||||
nodePort.AttachVisual(gameObject2.transform);
|
||||
nodePort.AttachVisualRenderers(gameObject2.GetComponentsInChildren<Renderer>(includeInactive: true));
|
||||
if (PortTextPrefab != null && InputTextParent != null)
|
||||
{
|
||||
TMP_Text tMP_Text = UnityEngine.Object.Instantiate(PortTextPrefab, InputTextParent);
|
||||
tMP_Text.name = nodePort.Name + " Text";
|
||||
Vector3 localPosition2 = tMP_Text.transform.localPosition;
|
||||
localPosition2.y = FirstTextY + TextYOffset * (float)i;
|
||||
tMP_Text.transform.localPosition = localPosition2;
|
||||
nodePort.AttachLabel(tMP_Text);
|
||||
UpdatePortLabel(nodePort);
|
||||
RegisterPortText(tMP_Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildOutputVisuals()
|
||||
{
|
||||
for (int i = 0; i < OutputPorts.Count; i++)
|
||||
{
|
||||
NodePort nodePort = OutputPorts[i];
|
||||
bool num = nodePort.Kind == PortKind.Run;
|
||||
Transform transform = (num ? OutputRunPortParent : OutputValuePortParent);
|
||||
GameObject gameObject = (num ? OutputRunPortPrefab : OutputValuePortPrefab);
|
||||
if (!(transform == null) && !(gameObject == null))
|
||||
{
|
||||
GameObject gameObject2 = UnityEngine.Object.Instantiate(gameObject, transform);
|
||||
gameObject2.name = nodePort.Name;
|
||||
Vector3 localPosition = gameObject2.transform.localPosition;
|
||||
localPosition.y = FirstPortY + PortYOffset * (float)i;
|
||||
gameObject2.transform.localPosition = localPosition;
|
||||
nodePort.AttachVisual(gameObject2.transform);
|
||||
nodePort.AttachVisualRenderers(gameObject2.GetComponentsInChildren<Renderer>(includeInactive: true));
|
||||
if (PortTextPrefab != null && OutputTextParent != null)
|
||||
{
|
||||
TMP_Text tMP_Text = UnityEngine.Object.Instantiate(PortTextPrefab, OutputTextParent);
|
||||
tMP_Text.name = nodePort.Name + " Text";
|
||||
Vector3 localPosition2 = tMP_Text.transform.localPosition;
|
||||
localPosition2.y = FirstTextY + TextYOffset * (float)i;
|
||||
tMP_Text.transform.localPosition = localPosition2;
|
||||
nodePort.AttachLabel(tMP_Text);
|
||||
UpdatePortLabel(nodePort);
|
||||
RegisterPortText(tMP_Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePortLabel(NodePort port)
|
||||
{
|
||||
if (port != null && !(port.LabelText == null))
|
||||
{
|
||||
port.LabelText.text = ((port.Kind == PortKind.Value) ? (port.Name + ": " + FormatPortValue(port.Value)) : port.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private static string FormatPortValue(BSValue value)
|
||||
{
|
||||
value = value.Normalize();
|
||||
return value.Kind switch
|
||||
{
|
||||
BSValueKind.None => "None",
|
||||
BSValueKind.Number => value.AsText(),
|
||||
BSValueKind.Text => string.IsNullOrEmpty(value.AsText()) ? "\"\"" : value.AsText(),
|
||||
BSValueKind.Bool => value.AsBool() ? "True" : "False",
|
||||
BSValueKind.Player => $"Player {value.AsPlayerId()}",
|
||||
BSValueKind.Group => $"Group {value.AsGroupId()}",
|
||||
_ => value.ToString(),
|
||||
};
|
||||
}
|
||||
|
||||
private void RegisterPortText(TMP_Text text)
|
||||
{
|
||||
if (!(text == null))
|
||||
{
|
||||
cachedPortTexts.Add(text);
|
||||
if (!defaultTextColors.ContainsKey(text))
|
||||
{
|
||||
defaultTextColors.Add(text, text.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearVisualCaches()
|
||||
{
|
||||
cachedPortTexts.Clear();
|
||||
defaultTextColors.Clear();
|
||||
cachedRenderers.Clear();
|
||||
}
|
||||
|
||||
private void CacheVisuals()
|
||||
{
|
||||
cachedRenderers.Clear();
|
||||
cachedRenderers.AddRange(GetComponentsInChildren<Renderer>(includeInactive: true));
|
||||
cachedPortTexts.Clear();
|
||||
defaultTextColors.Clear();
|
||||
TMP_Text[] componentsInChildren = GetComponentsInChildren<TMP_Text>(includeInactive: true);
|
||||
for (int i = 0; i < componentsInChildren.Length; i++)
|
||||
{
|
||||
RegisterPortText(componentsInChildren[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplySelectionVisual()
|
||||
{
|
||||
base.transform.localScale = defaultScale * (selected ? 1.035f : 1f);
|
||||
for (int i = 0; i < cachedPortTexts.Count; i++)
|
||||
{
|
||||
TMP_Text tMP_Text = cachedPortTexts[i];
|
||||
if (!(tMP_Text == null))
|
||||
{
|
||||
Color value;
|
||||
Color color = (defaultTextColors.TryGetValue(tMP_Text, out value) ? value : Color.white);
|
||||
tMP_Text.color = (selected ? SelectedTextColor : color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyVisibility()
|
||||
{
|
||||
for (int i = 0; i < cachedRenderers.Count; i++)
|
||||
{
|
||||
if (cachedRenderers[i] != null)
|
||||
{
|
||||
cachedRenderers[i].enabled = visibleInEditMode;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < cachedPortTexts.Count; j++)
|
||||
{
|
||||
if (cachedPortTexts[j] != null)
|
||||
{
|
||||
cachedPortTexts[j].enabled = visibleInEditMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePortVisualState()
|
||||
{
|
||||
UpdatePortVisualState(InputPorts);
|
||||
UpdatePortVisualState(OutputPorts);
|
||||
}
|
||||
|
||||
private void UpdatePortTintState()
|
||||
{
|
||||
UpdatePortTintState(InputPorts);
|
||||
UpdatePortTintState(OutputPorts);
|
||||
}
|
||||
|
||||
private void UpdatePortTintState(List<NodePort> ports)
|
||||
{
|
||||
for (int i = 0; i < ports.Count; i++)
|
||||
{
|
||||
NodePort nodePort = ports[i];
|
||||
if (nodePort == null || nodePort.Kind != PortKind.Value || nodePort.VisualTransform == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (nodePort.VisualRenderers == null)
|
||||
{
|
||||
nodePort.AttachVisualRenderers(nodePort.VisualTransform.GetComponentsInChildren<Renderer>(includeInactive: true));
|
||||
}
|
||||
if (nodePort.VisualRenderers == null || nodePort.VisualRenderers.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
BSValueKind kind = ((nodePort.Direction != PortDirection.Input) ? nodePort.Value.Normalize().Kind : ((nodePort.SourceGroupId > 0) ? BSValueKind.Group : ((nodePort.IncomingConnection == null) ? nodePort.Value.Normalize().Kind : nodePort.IncomingConnection.Value.Normalize().Kind)));
|
||||
Color color = NodeWirePalette.ForValueKind(kind);
|
||||
if (nodePort.LastTint == color)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
nodePort.LastTint = color;
|
||||
NodePort nodePort2 = nodePort;
|
||||
if (nodePort2.VisualBlock == null)
|
||||
{
|
||||
nodePort2.VisualBlock = new MaterialPropertyBlock();
|
||||
}
|
||||
nodePort.VisualBlock.Clear();
|
||||
nodePort.VisualBlock.SetColor(BaseColorId, color);
|
||||
nodePort.VisualBlock.SetColor(ColorId, color);
|
||||
nodePort.VisualBlock.SetColor(TintColorId, color);
|
||||
for (int j = 0; j < nodePort.VisualRenderers.Length; j++)
|
||||
{
|
||||
Renderer renderer = nodePort.VisualRenderers[j];
|
||||
if (!(renderer == null))
|
||||
{
|
||||
renderer.SetPropertyBlock(nodePort.VisualBlock);
|
||||
Material sharedMaterial = renderer.sharedMaterial;
|
||||
if (sharedMaterial != null && !sharedMaterial.HasProperty(BaseColorId) && !sharedMaterial.HasProperty(ColorId) && !sharedMaterial.HasProperty(TintColorId))
|
||||
{
|
||||
renderer.material.color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePortVisualState(List<NodePort> ports)
|
||||
{
|
||||
for (int i = 0; i < ports.Count; i++)
|
||||
{
|
||||
NodePort nodePort = ports[i];
|
||||
if (nodePort != null && !(nodePort.VisualTransform == null))
|
||||
{
|
||||
float num = 0f;
|
||||
if (nodePort.PulseUntil > Time.unscaledTime)
|
||||
{
|
||||
num = Mathf.Clamp01((nodePort.PulseUntil - Time.unscaledTime) / 0.16f);
|
||||
}
|
||||
float num2 = (nodePort.Highlighted ? 1.25f : 1f);
|
||||
num2 += num * 0.22f;
|
||||
nodePort.VisualTransform.localScale = nodePort.BaseLocalScale * num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearChildren(Transform parent)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int num = parent.childCount - 1; num >= 0; num--)
|
||||
{
|
||||
Transform child = parent.GetChild(num);
|
||||
if (!(child == null))
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
UnityEngine.Object.Destroy(child.gameObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(child.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateBehavior()
|
||||
{
|
||||
if (behavior != null)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
UnityEngine.Object.Destroy(behavior);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(behavior);
|
||||
}
|
||||
behavior = null;
|
||||
}
|
||||
if (Definition == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Type type = FindType(Definition.BehaviorClassName);
|
||||
if (!(type == null) && typeof(NodeBehavior).IsAssignableFrom(type))
|
||||
{
|
||||
behavior = base.gameObject.AddComponent(type) as NodeBehavior;
|
||||
if (behavior != null)
|
||||
{
|
||||
behavior.Node = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Type FindType(string typeName)
|
||||
{
|
||||
Type type = Type.GetType(typeName);
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
for (int i = 0; i < assemblies.Length; i++)
|
||||
{
|
||||
type = assemblies[i].GetType(typeName);
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool BSValueEquals(BSValue a, BSValue b)
|
||||
{
|
||||
a = a.Normalize();
|
||||
b = b.Normalize();
|
||||
if (a.Kind != b.Kind)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return a.Kind switch
|
||||
{
|
||||
BSValueKind.Number => Math.Abs(a.Number - b.Number) <= 0.0001,
|
||||
BSValueKind.Text => string.Equals(a.Text ?? string.Empty, b.Text ?? string.Empty, StringComparison.Ordinal),
|
||||
BSValueKind.Bool => a.Bool == b.Bool,
|
||||
BSValueKind.Player => a.PlayerId == b.PlayerId,
|
||||
BSValueKind.Group => a.GroupId == b.GroupId,
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user