using System.Collections.Generic; using DG.Tweening; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using Yarn.Unity; using AibisDream; public class ToolManager : MonoBehaviour { public static ToolManager Instance { get; private set; } public GameObject toolBox; // 工具盒的UI对象 private Tool currentTool; public List toolPrefabs; private Dictionary toolPrefabDictionary; public Canvas toolCanvas; private bool isBoxShow = false; public bool HasTool => currentTool != null; // 判断玩家是否已获得工具 private Module currentModule; public Transform faceCanvas; private Vector3 originalCanvasPosition; // 原始面板位置 private bool isInRepiarMode=false; private void Awake() { // 确保 ToolManager 只有一个实例,并且这个实例是唯一的 if (Instance != null && Instance != this) { Destroy(gameObject); // 如果实例已经存在,销毁当前实例 } else { Instance = this; // 保持唯一实例 //DontDestroyOnLoad(gameObject); // 不销毁这个工具管理器 } } private void Start() { originalCanvasPosition=faceCanvas.position; currentModule=null; toolBox.SetActive(false); // 初始隐藏工具盒 toolPrefabDictionary = new Dictionary(); foreach (GameObject toolPrefab in toolPrefabs) { Tool tool = toolPrefab.GetComponent(); if (tool != null) { toolPrefabDictionary[tool.gameObject.name] = toolPrefab; } } } public void TryStartRepairMode(Module module) { // 如果当前工具是螺丝刀,调用Module的EnterRepairMode方法 if (currentTool is Screwdriver&&module.isallowedRepair&&isInRepiarMode==false) { //module.StartRepairIfToolIsScrewdriver(currentTool); currentModule=module; EnterRepairMode(); } else { Debug.Log("no tool or not allowed"); } } public void EnterRepairMode() { isInRepiarMode=true; //isRepairMode = true; currentModule.RemoveAllPlugsFromSockets(); // 使用 DOTween 对 Canvas 的位置和缩放进行平滑过渡 faceCanvas.DOMove(currentModule.repairCanvasPosition, 1) .SetEase(Ease.OutQuad) // 移动面板 .OnComplete(() => currentModule.EnableScrewsInteraction(true)); // 动画完成后才启用交互 faceCanvas.DOScale(currentModule.repairCanvasScale, 1) .SetEase(Ease.OutQuad) .OnComplete(() => DialogController.Instance.StartDialogNode("EnterRepairMode")); // 缩放面板 } [YarnCommand("ExitRepairMode")] public void ExitRepairMode() { isInRepiarMode=false; // 使用 DOTween 对 Canvas 的位置和缩放进行平滑过渡 faceCanvas.DOMove(originalCanvasPosition, 1) .SetEase(Ease.InQuad); faceCanvas.DOScale(1f, 1) .SetEase(Ease.InQuad); // 恢复面板缩放 ShowToolBoxAfterTask(); currentModule=null; } [YarnCommand("ShowTool")] public void ShowTool(string toolName) { if (toolPrefabDictionary.TryGetValue(toolName, out GameObject toolPrefab)) { // 实例化工具 GameObject toolInstance = Instantiate(toolPrefab, toolBox.transform); currentTool = toolInstance.GetComponent(); toolBox.SetActive(true); isBoxShow = true; // 工具盒上移动画 toolBox.transform.DOMoveY(-4f, 0.5f).SetEase(Ease.OutBounce); // 添加点击事件以启动工具跟随鼠标 AddToolClickEvent(toolInstance); currentTool.GetComponent().blocksRaycasts=true; } else { Debug.LogWarning($"Tool '{toolName}' not found in tool manager."); } } private void AddToolClickEvent(GameObject toolInstance) { EventTrigger eventTrigger = toolInstance.GetComponent(); if (eventTrigger == null) { eventTrigger = toolInstance.AddComponent(); } // 清除之前可能存在的点击事件,避免重复添加 eventTrigger.triggers.Clear(); EventTrigger.Entry clickEntry = new EventTrigger.Entry { eventID = EventTriggerType.PointerClick }; // 点击事件:当点击工具时,使其开始跟随鼠标 clickEntry.callback.AddListener((data) => { currentTool.transform.SetParent(toolCanvas.transform); currentTool.StartFollowMouse(); currentTool.GetComponent().blocksRaycasts=false; currentTool.UseTool(); //RemoveToolClickEvent(eventTrigger); // 移除点击事件,防止再触发 HideTool(); }); eventTrigger.triggers.Add(clickEntry); } // 移除工具的点击事 // 显示工具盒并添加归还工具的点击事件 public void ShowToolBoxAfterTask() { toolBox.SetActive(true); isBoxShow = true; toolBox.transform.DOMoveY(-3.7f, 0.5f).SetEase(Ease.OutBounce); // 为工具盒添加一次性点击事件 AddToolBoxReturnEvent(); } private void AddToolBoxReturnEvent() { EventTrigger toolBoxTrigger = toolBox.GetComponent(); if (toolBoxTrigger == null) { toolBoxTrigger = toolBox.AddComponent(); } // 清除之前的事件,确保归还工具的事件仅触发一次 toolBoxTrigger.triggers.Clear(); EventTrigger.Entry boxClickEntry = new EventTrigger.Entry { eventID = EventTriggerType.PointerClick }; boxClickEntry.callback.AddListener((data) => { ReturnTool(); // 点击工具盒时归还工具 }); toolBoxTrigger.triggers.Add(boxClickEntry); } public void HideTool() { toolBox.transform.DOMoveY(-6.3f, 0.5f).SetEase(Ease.InBack).OnComplete(() => { toolBox.SetActive(false); isBoxShow = false; // 在工具盒的子物体中查找并删除工具对象 foreach (Transform child in toolBox.transform) { Tool tool = child.GetComponent(); if (tool != null) { Destroy(child.gameObject); // 删除工具对象 currentTool = null; // 清空当前工具的引用 } } // currentTool.ReturnTool(); // currentTool = null; }); } private void Update() { if (currentTool != null && currentTool.IsFollowingMouse) { //Vector2 imageSize = toolImage.rect.size; //Cursor.visible = false; Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); mousePos+=currentTool.offset; currentTool.transform.position = new Vector3(mousePos.x, mousePos.y, 0); } if(Input.GetKeyDown(KeyCode.O)) { ShowTool("ScrewDriver"); } if(Input.GetKeyDown(KeyCode.P)) { ShowToolBoxAfterTask(); } } public void ReturnTool() { if (currentTool != null) { Debug.Log("Returning tool and stopping follow mouse."); // 停止工具跟随鼠标 currentTool.StopFollowMouse(); // 将工具放回工具盒 currentTool.transform.SetParent(toolBox.transform); currentTool.transform.localPosition = Vector3.zero; currentTool.ReturnTool(); currentTool = null; // 重新添加点击事件,以便可以再次点击 //AddToolClickEvent(currentTool.gameObject); HideTool(); //Cursor.visible = true; } } }