Files
aibis-dream/Assets/Scripts/FixSystem/Line/LineManager.cs
T
2024-08-28 17:04:13 +08:00

261 lines
7.6 KiB
C#

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<string, InteractiveLineSegment> lineSegmentDictionary = new Dictionary<string, InteractiveLineSegment>();
public IEnumerable<string> 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<PhysicLineSegment>();
firstLineSegment.Initialize(originalLineSegment.StartTransform.position, splitPoint);
// Create the second new line segment
GameObject secondLineSegmentObject = Instantiate(physicLineSegmentPrefab, transform);
PhysicLineSegment secondLineSegment = secondLineSegmentObject.GetComponent<PhysicLineSegment>();
secondLineSegment.Initialize(originalLineSegment.EndTransform.position,splitPoint);
// Immediately destroy the original line segment
Destroy(originalLineSegment.gameObject);
}
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)
{
lineSegment.Option = option;
}
}
private void EnterLineSegment(InteractiveLineSegment lineSegment)
{
if (currentLineSegment != null)
{
lineSegment.OnHoverExit();
}
lineSegment.OnHover();
currentLineSegment = lineSegment;
}
private void LongPressLineSegment(InteractiveLineSegment lineSegment)
{
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<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);
}
private void Start()
{
// 查找场景中的所有 InteractiveLineSegment 并添加到字典中
InteractiveLineSegment[] lineSegments = FindObjectsOfType<InteractiveLineSegment>();
foreach (InteractiveLineSegment lineSegment in lineSegments)
{
lineSegmentDictionary.Add(lineSegment.name, lineSegment);
}
}
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;
}
}