226 lines
7.0 KiB
C#
226 lines
7.0 KiB
C#
using System;
|
||
using AibisDream.Framework;
|
||
using AibisDream.Kit;
|
||
using AibisDream.Utility;
|
||
using UnityEngine;
|
||
using UnityEngine.EventSystems;
|
||
|
||
namespace AibisDream.FixSystem
|
||
{
|
||
[RequireComponent(typeof(EventTriggerEx))]
|
||
public class Plug : MonoBehaviour, IInteraction
|
||
{
|
||
private static readonly int ShineFade = Shader.PropertyToID("_ShineFade");
|
||
|
||
// 插头常态排序:与线缆(Tools/47)同层且在其上,拖拽不再切层——
|
||
// 原型里插头永远画在线之上、画序不随交互变化;整套线缆系统被外部元素
|
||
// 遮挡时也必须整体一起被盖,不能插头浮出而线身沉底。
|
||
// Tools 整层高于 FixTop(屏幕 UI Canvas 在 FixTop/100),Tools/48 是插头
|
||
// 历史沿用且验证过不被面板遮挡的位置;剪线演出(Tools/50+)仍可盖住整套线缆
|
||
private const string NormalSortingLayer = "Tools";
|
||
private const int NormalSortingOrder = 48;
|
||
|
||
#region 插头当前信息
|
||
|
||
[SerializeField] private Vector3 startPosOffset = new(0.3f, -2f, 0);
|
||
private Vector3 _startPos;
|
||
|
||
private readonly Quaternion _defaultRotation = Quaternion.Euler(0, 0, 180);
|
||
|
||
#endregion
|
||
|
||
#region 索引
|
||
|
||
private CablePanel cablePanel;
|
||
private SpriteRenderer _sprite;
|
||
private Transform _plugRootPos;
|
||
private EventTriggerEx _trigger;
|
||
|
||
public Transform PlugRoot => _plugRootPos;
|
||
|
||
#endregion
|
||
|
||
public event Action<ISocket> OnInsertSocket;
|
||
public event Action OnPullUpSocket;
|
||
public event Action OnPlugPointerDown;
|
||
|
||
private bool _isDragging;
|
||
|
||
private void Awake()
|
||
{
|
||
InitComponentRef();
|
||
EventRegister();
|
||
_startPos = transform.position + startPosOffset;
|
||
|
||
// 预制体里序列化的还是旧的 Tools 层,启动时归一化;收起态由 CablePanel 之后覆盖
|
||
ApplyNormalSorting();
|
||
}
|
||
|
||
private void InitComponentRef()
|
||
{
|
||
cablePanel = transform.GetComponentInParent<CablePanel>(true);
|
||
_sprite = GetComponent<SpriteRenderer>();
|
||
_plugRootPos = transform.Find("Plug Root Pos");
|
||
_trigger = GetComponent<EventTriggerEx>();
|
||
|
||
// 处理插头高亮
|
||
_sprite.material.SetFloat(ShineFade, GlobalVariableKit.IsPlugHighLight ? 1 : 0);
|
||
}
|
||
|
||
private void EventRegister()
|
||
{
|
||
_trigger.Register(EventTriggerType.Drag, OnDrag);
|
||
_trigger.Register(EventTriggerType.PointerDown, OnPointerDown);
|
||
_trigger.Register(EventTriggerType.PointerUp, OnPointerUp);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 插入某个socket
|
||
/// </summary>
|
||
/// <param name="targetSocket">目标socket</param>
|
||
private void InsertSocket(ISocket targetSocket)
|
||
{
|
||
// 修改插头位置
|
||
transform.position = targetSocket.GetSocketPos().position;
|
||
|
||
// 处理插槽插入
|
||
targetSocket.PlugIn();
|
||
_sprite.enabled = false;
|
||
|
||
OnInsertSocket?.Invoke(targetSocket);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从某个Socket拔出来
|
||
/// </summary>
|
||
public void PullUpSocket()
|
||
{
|
||
_sprite.enabled = true;
|
||
ApplyNormalSorting();
|
||
|
||
OnPullUpSocket?.Invoke();
|
||
}
|
||
|
||
/// <summary>读档/静默:仅恢复插头精灵可见,不触发 CablePanel 事件。</summary>
|
||
public void PullUpSocketSilent()
|
||
{
|
||
_sprite.enabled = true;
|
||
ApplyNormalSorting();
|
||
}
|
||
|
||
/// <summary>恢复插头常态排序(收起态会被 CablePanel 压到线盘下方,放下时调回)。</summary>
|
||
public void ApplyNormalSorting()
|
||
{
|
||
_sprite.sortingLayerName = NormalSortingLayer;
|
||
_sprite.sortingOrder = NormalSortingOrder;
|
||
}
|
||
|
||
/// <summary>读档:无动画回到初始位。</summary>
|
||
public void RestoreAtStartPositionImmediate()
|
||
{
|
||
transform.rotation = _defaultRotation;
|
||
transform.position = _startPos;
|
||
}
|
||
|
||
/// <summary>读档:无动画插入指定 socket 的视觉终态。</summary>
|
||
public void RestoreInsertedAt(Transform socketPos)
|
||
{
|
||
if (socketPos == null) return;
|
||
transform.position = socketPos.position;
|
||
_sprite.enabled = false;
|
||
}
|
||
|
||
public void SetSpriteVisible(bool visible)
|
||
{
|
||
_sprite.enabled = visible;
|
||
}
|
||
|
||
private void OnDrag(BaseEventData eventData)
|
||
{
|
||
if (!_isDragging) return;
|
||
|
||
if (eventData is PointerEventData pointerData)
|
||
{
|
||
// 指针只驱动线缆送线与末端钉住目标,插头本体由绳末端带动(CablePanel.LateUpdate)
|
||
cablePanel.UpdateDragPointer(CameraKit.GetMouseWorldPos(pointerData.position));
|
||
}
|
||
}
|
||
|
||
private void OnPointerDown(BaseEventData eventData)
|
||
{
|
||
if (EventSystemEx.Instance.isLocked) return;
|
||
if (eventData is PointerEventData { button: PointerEventData.InputButton.Right })
|
||
return;
|
||
|
||
ApplyNormalSorting();
|
||
|
||
OnPlugPointerDown?.Invoke();
|
||
|
||
TryCloseHighlight();
|
||
|
||
_isDragging = true;
|
||
|
||
AudioManager.Instance.PlaySfx("event:/FollowInput/plugpick");
|
||
}
|
||
|
||
private void TryCloseHighlight()
|
||
{
|
||
if (!GlobalVariableKit.IsPlugHighLight) return;
|
||
GlobalVariableKit.IsPlugHighLight = false;
|
||
_sprite.material.SetFloat(ShineFade, 0);
|
||
}
|
||
|
||
private void OnPointerUp(BaseEventData eventData)
|
||
{
|
||
if (EventSystemEx.Instance.isLocked)
|
||
{
|
||
_isDragging = false;
|
||
return;
|
||
}
|
||
if (eventData is PointerEventData { button: PointerEventData.InputButton.Right })
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 停止拖拽
|
||
_isDragging = false;
|
||
|
||
// 寻找可吸附的Module
|
||
if (cablePanel.TryFindClosestModule(transform.position, out var targetModule))
|
||
{
|
||
InsertSocket(targetModule);
|
||
}
|
||
else
|
||
{
|
||
ReturnToStartPosition();
|
||
}
|
||
}
|
||
|
||
public void ReturnToStartPosition()
|
||
{
|
||
// 解除末端钉住,线缆自动回收到最短长度,插头挂在绳末端跟着回去
|
||
cablePanel.ReleasePlug();
|
||
}
|
||
|
||
void OnDrawGizmosSelected()
|
||
{
|
||
Gizmos.color = Color.yellow;
|
||
Gizmos.DrawWireSphere(transform.position, 0.5f);
|
||
}
|
||
|
||
public bool IsActive => true;
|
||
|
||
public bool IsAvailable => !cablePanel.isCableRetracted;
|
||
|
||
public GameObject GetGameObject()
|
||
{
|
||
return gameObject;
|
||
}
|
||
|
||
public Vector3 GetStartPos()
|
||
{
|
||
return _startPos;
|
||
}
|
||
}
|
||
}
|