Files
aibis-dream/Assets/Scripts/FixSystem/Line/LineManager.cs
T
2025-02-23 03:06:14 +08:00

430 lines
14 KiB
C#

using UnityEngine;
using Yarn.Unity;
using System;
using System.Collections.Generic;
using System.Collections;
using AibisDream;
using System.Linq;
using DG.Tweening;
using AibisDream.FixSystem;
[System.Serializable]
public class LineSegmentInfo
{
public string Name;
public Transform StartTransform;
public Transform EndTransform;
}
public class LineManager : MonoBehaviour
{
public InteractiveLineSegment interactiveLineSegmentPrefab; // InteractiveLineSegment 的预制体
[SerializeField] private List<LineSegmentInfo> lineSegmentInfos; // 线段信息的列表
// 线段字典,用于快速查找
public GameObject physicLineSegmentPrefab;
//public CustomCursor customCursor; // 自定义光标,你可以在 Inspector 中设置
private bool isScissorsMode;
public bool IsScissorsMode
{
get { return isScissorsMode; }
set
{
isScissorsMode = value;
if (isScissorsMode)
{
//SetScissorsCursor();
}
else
{
//ResetCursor();
}
}
}
private Dictionary<string, InteractiveLineSegment> lineSegmentDictionary =
new Dictionary<string, InteractiveLineSegment>();
private bool isTryLineCut = false;
private bool isLineCut = false;
public IEnumerable<string> GetLineSegmentNames()
{
return lineSegmentDictionary.Keys;
}
private InteractiveLineSegment currentLineSegment; // 当前要被剪断的线段
private const float LONG_PRESS_THRESHOLD = 0.01f; // 长按阈值,可以根据需要调整
private float longPressTime = 0.0f; // 长按时间
private float detectionRadius = 0.25f;
// [YarnCommand("wait_for_LineCut")]
// public IEnumerator WaitForClose()
// {
// // 这里等待关闭按钮点击事件
// while (!isTryLineCut)
// {
// yield return null; // 每帧检查一次
// }
// isTryLineCut=false;
// if(isLineCut)
// {
// DialogController.Instance.SetVariable("$isLineCut",true);
// DialogController.Instance.StartDialogNode("CutLine");
// }
// //ToolManager.Instance.ShowToolBoxAfterTask();
// }
private void Awake()
{
Init();
}
public void Init()
{
FixSystemCenter.SystemDic.Register(this);
}
private void SaveCutLine(string lineName)
{
PlayerPrefs.SetString(lineName, "cut");
PlayerPrefs.Save();
}
private bool IsLineCut(string lineName)
{
return PlayerPrefs.HasKey(lineName);
}
public void CutLine(InteractiveLineSegment originalLineSegment, Vector3 splitPoint)
{
// 如果线段不可剪断,就直接返回,不进行剪断操作
if (!originalLineSegment.IsCuttable)
{
return;
}
AudioManager.RandomPlayInteraction("wire_cut");
// Create the first new line segment
GameObject firstLineSegmentObject = Instantiate(physicLineSegmentPrefab, transform);
PhysicLineSegment firstLineSegment = firstLineSegmentObject.GetComponent<PhysicLineSegment>();
firstLineSegment.Initialize(originalLineSegment.StartTransform.position, splitPoint);
firstLineSegment.lineRenderer.startColor = originalLineSegment.lineRenderer.startColor;
firstLineSegment.lineRenderer.endColor = originalLineSegment.lineRenderer.endColor;
// Create the second new line segment
GameObject secondLineSegmentObject = Instantiate(physicLineSegmentPrefab, transform);
PhysicLineSegment secondLineSegment = secondLineSegmentObject.GetComponent<PhysicLineSegment>();
secondLineSegment.Initialize(originalLineSegment.EndTransform.position, splitPoint);
secondLineSegment.lineRenderer.startColor = originalLineSegment.lineRenderer.startColor;
secondLineSegment.lineRenderer.endColor = originalLineSegment.lineRenderer.endColor;
// Immediately destroy the original line segment
Destroy(originalLineSegment.gameObject);
Debug.Log("线销毁了");
StartCoroutine(ScreenEffectManager.Instance.FlashRed(0.3f));
StartCoroutine(ScreenEffectManager.Instance.ShakeScreen());
SaveCutLine(originalLineSegment.name);
// Start the coroutine to destroy the new line segments after fade in and out
StartCoroutine(
DestroyNewSegmentsAfterFade(firstLineSegmentObject, secondLineSegmentObject, originalLineSegment));
}
private IEnumerator DestroyNewSegmentsAfterFade(GameObject firstLineSegmentObject,
GameObject secondLineSegmentObject, InteractiveLineSegment originalLineSegment)
{
yield return new WaitForSeconds(1.5f);
ToolManager.Instance.ShowToolBoxAfterTask();
yield return StartCoroutine(ScreenEffectManager.Instance.FadeIn(1));
Destroy(firstLineSegmentObject);
Destroy(secondLineSegmentObject);
yield return StartCoroutine(ScreenEffectManager.Instance.FadeOut(1));
isLineCut = true;
DialogController.Instance.SetVariable("$isLineCut", true);
DialogController.Instance.StartDialogNode("CutLine");
//originalLineSegment.Option.SelectOption();
}
private void AddPhysicsComponents(GameObject lineSegmentObject)
{
// Add Rigidbody2D
Rigidbody2D rb = lineSegmentObject.AddComponent<Rigidbody2D>();
rb.gravityScale = 1; // Enable gravity
// Add HingeJoint2D
HingeJoint2D hinge = lineSegmentObject.AddComponent<HingeJoint2D>();
hinge.anchor = Vector2.zero; // Set the anchor at one end of the line segment
}
public void BindOptionToLineSegment(string lineSegmentName, YarnOption option)
{
InteractiveLineSegment lineSegment = GetLineSegmentByName(lineSegmentName);
if (lineSegment != null)
{
if (option != null)
{
lineSegment.Option = option;
Debug.Log("Binded option to " + lineSegmentName);
}
else
{
Debug.LogError("Option is null for " + lineSegmentName);
}
}
}
private void EnterLineSegment(InteractiveLineSegment lineSegment)
{
if (currentLineSegment != null)
{
lineSegment.OnHoverExit();
}
lineSegment.OnHover();
currentLineSegment = lineSegment;
}
private void LongPressLineSegment(InteractiveLineSegment lineSegment)
{
if (!lineSegment.IsCuttable)
{
DialogController.Instance.SetVariable("$isLineCut", false);
DialogController.Instance.StartDialogNode("CutLine");
Debug.Log("not cuttable");
//lineSegment.Option.SelectOption();
return;
}
longPressTime += Time.deltaTime;
Vector3 midpoint = (lineSegment.StartPoint + lineSegment.EndPoint) / 2;
float distance = Vector3.Distance(midpoint, lineSegment.StartPoint);
// Make the scissors shake and the line segment turn red
// if (longPressTime < LONG_PRESS_THRESHOLD)
// {
// customCursor.Shake(longPressTime * 5.0f, 10.0f); // 抖动强度随时间增加
// float progress = longPressTime / LONG_PRESS_THRESHOLD;
// // Calculate the new position of the color gradient
// float newPosition = progress * distance;
// }
// else
// {
// Cut the line segment
CutLine(lineSegment, midpoint);
IsScissorsMode = false;
Debug.Log("线剪断触发了");
// }
}
private void ExitLineSegment()
{
if (currentLineSegment != null)
{
currentLineSegment.OnHoverExit();
}
currentLineSegment = null;
}
private void Update()
{
if (isScissorsMode)
{
// Get the position of the mouse in world coordinates
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
// Check if there is a line segment in the scissors' detection range
Collider2D hitCollider = Physics2D.OverlapCircle(mousePosition, detectionRadius);
InteractiveLineSegment hitLineSegment =
hitCollider != null ? hitCollider.GetComponent<InteractiveLineSegment>() : null;
if (hitLineSegment != null)
{
EnterLineSegment(hitLineSegment);
if (Input.GetMouseButtonDown(0))
{
longPressTime = 0.0f;
}
else if (Input.GetMouseButton(0))
{
LongPressLineSegment(hitLineSegment);
}
else if (Input.GetMouseButtonUp(0))
{
longPressTime = 0.0f;
//customCursor.ResetRotation(); // 假设你有一个方法来重置剪刀的旋转
//currentLineSegment.ResetColor(); // 假设你有一个方法来重置线段的颜色
}
}
else
{
ExitLineSegment();
}
}
}
// private void SetScissorsCursor()
// {
// // 启用自定义光标
// customCursor.gameObject.SetActive(true);
// }
// private void ResetCursor()
// {
// // 禁用自定义光标
// customCursor.gameObject.SetActive(false);
// }
[YarnCommand("reconnected_line")]
public void Reconnected(string input)
{
// Use GetLineSegmentName method to find the recognized name
string recognizedName = GetLineSegmentName(input);
if (recognizedName == null)
{
Debug.LogError("Invalid LineSegmentInfo name: " + input);
return;
}
// Find the LineSegmentInfo with the recognized name
LineSegmentInfo lineSegmentInfo = lineSegmentInfos.Find(info => info.Name == recognizedName);
if (lineSegmentInfo == null)
{
Debug.LogError("Invalid LineSegmentInfo name: " + recognizedName);
return;
}
// If the line is already cut, skip it
// if (!IsLineCut(lineSegmentInfo.Name))
// {
// return;
// }
// Instantiate a new line segment with the given info
InteractiveLineSegment newSegment = Instantiate(interactiveLineSegmentPrefab, transform);
newSegment.StartTransform = lineSegmentInfo.StartTransform;
newSegment.EndTransform = lineSegmentInfo.EndTransform;
newSegment.Initialize();
}
[YarnCommand("delete_line")]
public void DeleteLine(string input)
{
// Use GetLineSegmentName method to find the recognized name
string recognizedName = GetLineSegmentName(input);
if (recognizedName == null)
{
Debug.LogError("Invalid LineSegmentInfo name: " + input);
return;
}
if (lineSegmentDictionary.ContainsKey(recognizedName))
{
InteractiveLineSegment lineSegmentToRemove = lineSegmentDictionary[recognizedName];
if (lineSegmentToRemove == null || lineSegmentToRemove.gameObject == null)
{
Debug.LogWarning("Line segment already removed: " + recognizedName);
return;
}
// Destroy the line segment GameObject
Destroy(lineSegmentToRemove.gameObject);
Debug.Log("Line segment removed: " + recognizedName);
}
else
{
Debug.LogError("Line segment not found in dictionary: " + recognizedName);
}
}
private void Start()
{
foreach (LineSegmentInfo lineSegmentInfo in lineSegmentInfos)
{
if (IsLineCut(lineSegmentInfo.Name))
{
continue;
}
InteractiveLineSegment newSegment = Instantiate(interactiveLineSegmentPrefab, transform);
newSegment.StartTransform = lineSegmentInfo.StartTransform;
newSegment.EndTransform = lineSegmentInfo.EndTransform;
newSegment.Initialize();
lineSegmentDictionary.Add(lineSegmentInfo.Name, newSegment);
}
}
public InteractiveLineSegment GetLineSegmentByName(string lineSegmentName)
{
if (lineSegmentDictionary.TryGetValue(lineSegmentName, out InteractiveLineSegment lineSegment))
{
return lineSegment;
}
else
{
Debug.LogError("Invalid line segment name: " + lineSegmentName);
return null;
}
}
public string GetLineSegmentName(string input)
{
// 转换为小写并移除所有的下划线
string[] inputWords = input.ToLower().Split('_');
foreach (var lineSegmentName in lineSegmentDictionary.Keys)
{
// 转换为小写并移除所有的下划线
string[] lineSegmentWords = lineSegmentName.ToLower().Split('_');
// 检查是否包含相同的单词
if (inputWords.All(word => lineSegmentWords.Contains(word)) &&
lineSegmentWords.All(word => inputWords.Contains(word)))
{
return lineSegmentName;
}
}
return null;
}
// Yarn 命令,设置线段的可剪断性
[YarnCommand("set_line_cuttable")]
public void SetLineCuttable(string lineSegmentName, bool isCuttable)
{
string recognizedName = GetLineSegmentName(lineSegmentName);
if (recognizedName != null)
{
InteractiveLineSegment lineSegment = GetLineSegmentByName(recognizedName);
if (lineSegment != null)
{
lineSegment.IsCuttable = isCuttable;
}
}
else
{
Debug.LogError("Invalid line segment name: " + lineSegmentName);
}
}
// Yarn 命令,设置剪刀模式
[YarnCommand("set_scissors_mode")]
public void SetScissorsMode(bool isEnabled)
{
IsScissorsMode = isEnabled;
}
}