136 lines
4.7 KiB
C#
136 lines
4.7 KiB
C#
using System;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
namespace Ichni.NodeScript
|
|
{
|
|
public class NodeObject : MonoBehaviour, IDragHandler, IPointerClickHandler
|
|
{
|
|
public TMP_Text TitleText;
|
|
public NodeBase nodeBase;
|
|
public Image statusImage;
|
|
|
|
public Transform inputsRoot;
|
|
public Transform outputsRoot;
|
|
public Transform middleRoot;
|
|
|
|
public GameObject connectorSlotPrefabI;
|
|
public GameObject connectorSlotPrefabO;
|
|
public GameObject dropdownPrefab;
|
|
public GameObject inputPrefab;
|
|
|
|
bool _selected;
|
|
public bool Selected
|
|
{
|
|
get => _selected;
|
|
set
|
|
{
|
|
_selected = value;
|
|
if (_bg == null) _bg = GetComponent<Image>();
|
|
if (_bg != null) _bg.color = value ? new Color(0.3f, 0.5f, 0.9f, 0.4f) : new Color(0.15f, 0.15f, 0.15f, 0.3f);
|
|
}
|
|
}
|
|
Image _bg;
|
|
|
|
public void Init()
|
|
{
|
|
if (nodeBase == null) return;
|
|
TitleText.text = nodeBase.NodeName;
|
|
nodeBase.nodeObject = this;
|
|
|
|
_bg = GetComponent<Image>();
|
|
if (_bg == null) { _bg = gameObject.AddComponent<Image>(); _bg.color = new Color(0.15f, 0.15f, 0.15f, 0.3f); }
|
|
|
|
nodeBase.InitConnectors();
|
|
BuildConnectors();
|
|
nodeBase.BuildUI(new NodeUIBuilder(middleRoot, dropdownPrefab, inputPrefab));
|
|
NodeManager.Instance?.ComputeLValues();
|
|
UpdateLDisplay();
|
|
}
|
|
|
|
public void UpdateLDisplay()
|
|
{
|
|
if (TitleText != null && nodeBase != null)
|
|
TitleText.text = $"{nodeBase.NodeName} (L:{nodeBase.L})";
|
|
}
|
|
|
|
public void UpdateStatusDisplay()
|
|
{
|
|
if (statusImage == null || nodeBase == null) return;
|
|
statusImage.color = nodeBase.Status switch
|
|
{
|
|
NodeStatus.Ready => new Color(0.3f, 0.3f, 0.3f, 0.8f),
|
|
NodeStatus.Hang => new Color(0.8f, 0.6f, 0.1f, 0.9f),
|
|
NodeStatus.Complete => new Color(0.2f, 0.8f, 0.3f, 0.9f),
|
|
_ => Color.white,
|
|
};
|
|
}
|
|
|
|
// ========== 选中 / 拖拽 ==========
|
|
public void OnPointerClick(PointerEventData e)
|
|
{
|
|
if (e.button != PointerEventData.InputButton.Left) return;
|
|
NodeManager.Instance.SelectNode(this, e);
|
|
}
|
|
|
|
public void OnDrag(PointerEventData eventData)
|
|
{
|
|
if (eventData.button != PointerEventData.InputButton.Left) return;
|
|
var rt = GetComponent<RectTransform>();
|
|
rt.anchoredPosition += eventData.delta / GetComponentInParent<Canvas>().scaleFactor;
|
|
NodeManager.Instance.RefreshAllLines();
|
|
}
|
|
|
|
// ========== 插槽构建 ==========
|
|
void BuildConnectors()
|
|
{
|
|
foreach (var (name, connector, type) in nodeBase.GetInputs())
|
|
CreateSlot(name, connector, true);
|
|
|
|
foreach (var (name, connector, type) in nodeBase.GetOutputs())
|
|
CreateSlot(name, connector, false);
|
|
}
|
|
|
|
void CreateSlot(string name, object connector, bool isInput)
|
|
{
|
|
IInput inp = connector as IInput;
|
|
IOutput outp = connector as IOutput;
|
|
if (inp == null && outp == null) return;
|
|
|
|
var conName = inp?.Name ?? outp.Name;
|
|
if (inp != null) inp.Name = name;
|
|
if (outp != null) outp.Name = name;
|
|
|
|
var prefab = isInput ? connectorSlotPrefabI : connectorSlotPrefabO;
|
|
var parent = isInput ? inputsRoot : outputsRoot;
|
|
if (prefab == null || parent == null) return;
|
|
|
|
var go = Instantiate(prefab, parent);
|
|
var img = go.GetComponentInChildren<Image>();
|
|
if (img == null)
|
|
{
|
|
var imgGo = new GameObject("Dot", typeof(Image));
|
|
imgGo.transform.SetParent(go.transform, false);
|
|
img = imgGo.GetComponent<Image>();
|
|
}
|
|
img.color = (inp as IInput)?.ConnectorColor ?? (outp as IOutput)?.ConnectorColor ?? Color.white;
|
|
img.raycastTarget = true;
|
|
|
|
var text = go.GetComponentInChildren<TMP_Text>();
|
|
if (text != null) text.text = name;
|
|
|
|
var imgRt = img.GetComponent<RectTransform>();
|
|
if (imgRt.sizeDelta.sqrMagnitude < 1f) imgRt.sizeDelta = new Vector2(20, 20);
|
|
|
|
var slot = img.GetComponent<ConnectorSlot>();
|
|
if (slot == null) slot = img.gameObject.AddComponent<ConnectorSlot>();
|
|
slot.isInput = isInput;
|
|
slot.connectorIn = inp;
|
|
slot.connectorOut = outp;
|
|
slot.ownerNode = this;
|
|
}
|
|
}
|
|
}
|