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 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 lineSegmentDictionary = new Dictionary(); private bool isTryLineCut = false; private bool isLineCut = false; public IEnumerable 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(); 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(); 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(); rb.gravityScale = 1; // Enable gravity // Add HingeJoint2D HingeJoint2D hinge = lineSegmentObject.AddComponent(); 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() : 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; } }