using UnityEngine; using Yarn.Unity; using System; using System.Collections.Generic; using System.Collections; using AibisDream; using System.Linq; using DG.Tweening; public class LineManager : MonoBehaviour { //public GameObject interactiveLineSegmentPrefab; 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(); public IEnumerable GetLineSegmentNames() { return lineSegmentDictionary.Keys; } private InteractiveLineSegment currentLineSegment; // 当前要被剪断的线段 private const float LONG_PRESS_THRESHOLD = 3.0f; // 长按阈值,可以根据需要调整 private float longPressTime = 0.0f; // 长按时间 private float detectionRadius=0.4f; public void CutLine(InteractiveLineSegment originalLineSegment, Vector3 splitPoint) { // 如果线段不可剪断,就直接返回,不进行剪断操作 if (!originalLineSegment.IsCuttable) { return; } // Create the first new line segment GameObject firstLineSegmentObject = Instantiate(physicLineSegmentPrefab, transform); PhysicLineSegment firstLineSegment = firstLineSegmentObject.GetComponent(); firstLineSegment.Initialize(originalLineSegment.StartTransform.position, splitPoint); // Create the second new line segment GameObject secondLineSegmentObject = Instantiate(physicLineSegmentPrefab, transform); PhysicLineSegment secondLineSegment = secondLineSegmentObject.GetComponent(); secondLineSegment.Initialize(originalLineSegment.EndTransform.position,splitPoint); originalLineSegment.Option.SelectOption(); // Immediately destroy the original line segment Destroy(originalLineSegment.gameObject); } 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) { lineSegment.Option.SelectOption(); return; } longPressTime += Time.deltaTime; Vector3 midpoint = (lineSegment.StartPoint + lineSegment.EndPoint) / 2; // Make the scissors shake and the line segment turn red if (longPressTime < LONG_PRESS_THRESHOLD) { customCursor.Shake(longPressTime * 5.0f, 10.0f); // 抖动强度随时间增加 //lineSegment.TurnRed(longPressTime / LONG_PRESS_THRESHOLD); // 线段变红的程度随时间增加 // Calculate the midpoint of the line segment // Move the scissors towards the midpoint //customCursor.transform.DOMove(midpoint, 0.1f); } else { // Cut the line segment CutLine(lineSegment,midpoint); } } private void ExitLineSegment() { if (currentLineSegment != null) { currentLineSegment.TurnGrey(); } 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); } private void Start() { // 查找场景中的所有 InteractiveLineSegment 并添加到字典中 InteractiveLineSegment[] lineSegments = FindObjectsOfType(); foreach (InteractiveLineSegment lineSegment in lineSegments) { lineSegmentDictionary.Add(lineSegment.name, lineSegment); Debug.Log("Added " + lineSegment.name + " to lineSegmentDictionary"); } } 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; } }