using UnityEngine; using AibisDream.Kit; using AibisDream.Utility; using System.Linq; using System.Collections; using AibisDream.Framework; using AibisDream.FixSystem; using UnityEngine.EventSystems; namespace AibisDream { public class BlockPuzzleSystem : MonoBehaviour { [Header("物体索引")] // 物体索引 [SerializeField] public BlockPuzzleGrid grid; [SerializeField] private Transform shapeRoot; [SerializeField] private ShapeRecycleSlot shapeRecycleSlot; private BlockPuzzlePanel blockPuzzlePanel; [Header("数据")] [SerializeField] private BlockPuzzleData puzzleData; [SerializeField] private bool initializeOnStart = true; private BlockPuzzleValidator validator; private ShapeFactory shapeFactory; // 锁定状态 public bool IsLocked { get; private set; } // 缓存当前的吸附结果(由DragUpdate更新) private SnapResult _currentSnapResult; private void Start() { FixSystemCenter.SystemDic.Register(this); RepairSystemManager.Register(this); blockPuzzlePanel = FixPanelSystem.GetRepairPanel(); if (initializeOnStart) { Initialize(); } } private void OnDestroy() { FixSystemCenter.SystemDic.Unregister(); } public void Initialize(string puzzleName) { if (BlockPuzzleKit.TryLoadBlockPuzzleData(puzzleName, out var blockPuzzleData)) { Initialize(blockPuzzleData); } else { Debug.LogError($"加载 BlockPuzzleData 失败: {puzzleName}"); } } public void Initialize(BlockPuzzleData puzzleData) { this.puzzleData = puzzleData; ClearGame(); Initialize(); } public void Initialize() { float startTime = Time.realtimeSinceStartup; // 初始化网格 grid.Initialize(puzzleData.gridWidth, puzzleData.gridHeight, puzzleData.cellSize); // 批量预加载所有需要的BlockShapeData,避免循环中重复读取JSON文件 var shapeKeys = puzzleData.gridShapeDataInfos.Select(s => s.shapeKey).Distinct().ToArray(); var shapeDataDict = BlockPuzzleKit.LoadBlockShapeDataBatch(shapeKeys); // 初始化网格上图形 shapeFactory = new ShapeFactory(shapeRoot); foreach (var shapeData in puzzleData.gridShapeDataInfos) { // 使用预加载的数据创建形状,避免重复读取JSON if (shapeDataDict.TryGetValue(shapeData.shapeKey, out var blockShapeData)) { var shape = shapeFactory.CreateBlockShape(blockShapeData); shape.Rotate(shapeData.rotationAngle); grid.TrySnapToGrid(shape, shapeData.rootCell); shape.ShapeDragger.InteractionMode = InteractionMode.Click; } } grid.GridVisualizer.UpdateAllCellsVisual(); // 加载验证器 validator = ResourceKit.LoadAssetSync(puzzleData.validatorName); blockPuzzlePanel.SetProgressMaxValue(validator.CollectThresholds()); // 初始化侧边栏 var deviceDatas = BlockPuzzleKit.LoadBlockShapeDataBatch(puzzleData.shapeInRack); blockPuzzlePanel.DeviceButtonDatas = deviceDatas.Values.ToArray(); // 组装事件逻辑 AssembleEventLogic(); // 初始化时验证一次 validator.Validate(grid.GetShapes()); // 确保交互状态正确 UpdateInteractionState(); } private void SubmitGameResult() { // 检查系统是否锁定 if (IsLocked) { return; } var validateResult = validator.Validate(grid.GetShapes()); var shapesInGrid = grid.GetShapes().Select(s => s.BlockShapeData.blockShapeInfo.shapeName).ToArray(); YarnVariableStorage.Instance.SetValue("$shapesInGrid", string.Join(",", shapesInGrid)); // 如果验证通过, 则设置变量并弹出对话 if (validateResult.isPass) { SingleCastEventSystem.Global.Trigger(DialogEventEnum.StartNode, "BlockPuzzlePass"); } } public void ClearGame() { grid.Clear(); shapeRoot.DestroyAllChildren(); // 重置锁定状态 SetLocked(false); } // --------------------- 锁定状态管理 ------------------- /// /// 设置系统锁定状态 /// /// 是否锁定 public void SetLocked(bool locked) { IsLocked = locked; UpdateInteractionState(); } public IEnumerator LockSystem() { SetLocked(true); yield return TimelineCenter.Instance.PlayTimelineAsync("卡扣/卡扣锁定"); } public IEnumerator UnlockSystem() { yield return TimelineCenter.Instance.PlayTimelineAsync("卡扣/卡扣解锁"); SetLocked(false); } /// /// 更新所有交互组件的状态 /// private void UpdateInteractionState() { // 更新所有形状的拖拽状态 if (shapeFactory != null) { shapeFactory.SetAllShapesInteractable(!IsLocked); } // 更新按钮的交互状态 if (blockPuzzlePanel != null) { if (blockPuzzlePanel.LockButton != null) { blockPuzzlePanel.LockButton.GetComponent().SetLockedState(IsLocked); } if (blockPuzzlePanel.PopUpButton != null) { blockPuzzlePanel.PopUpButton.interactable = !IsLocked; } } } public void EnableDrag() { shapeFactory.SetAllShapesInteractionMode(InteractionMode.Drag); } public void LoadShapeRack() { blockPuzzlePanel.LoadBackupDevices(); } // --------------------- 维修面板同步 ------------------- private string selectedShapeName; /// /// 组装各系统之间相互逻辑 /// private void AssembleEventLogic() { // 由面板触发 blockPuzzlePanel.OnDeviceSelected += OnPanelShapeSelected; blockPuzzlePanel.OnSubmit.AddListener(SubmitGameResult); blockPuzzlePanel.OnPopUp.AddListener(PopUpShape); // 由Shape触发 - 使用新的事件系统 shapeFactory.OnDragStartDetailed += OnShapeDragStartDetailed; shapeFactory.OnDragEndDetailed += OnShapeDragEndDetailed; shapeFactory.OnDragUpdateDetailed += OnShapeDragUpdateDetailed; shapeFactory.OnClick += OnShapeClick; // 由系统触发 validator.OnValidate.AddListener(blockPuzzlePanel.SetVaildState); validator.OnValidate.AddListener(blockPuzzlePanel.OnProgressChanged); } private void OnPanelShapeSelected(BlockShapeInfo shapeData) { // 在屏幕上更新选中的图形 selectedShapeName = shapeData.shapeName; blockPuzzlePanel.ShowShapeInScreen(shapeData); } public void OnShapeClick(BlockShape blockShape) { // 点击形状 blockPuzzlePanel.ShowShapeInScreen(blockShape.BlockShapeData.blockShapeInfo); // 播放事件节点 YarnVariableStorage.Instance.SetValue("$selectedShape", blockShape.BlockShapeData.blockShapeInfo.shapeName); SingleCastEventSystem.Global.Trigger(DialogEventEnum.StartNode, "ShapeSelected"); } #region 新的事件驱动处理器 private void OnShapeDragStartDetailed(object sender, DragStartEventArgs args) { var blockShape = args.Shape; // 如果原本就在网格中,则先移除 grid.TryRemoveShapeFromGrid(blockShape); grid.ResetPreviewGrid(); // 显示网格 grid.GridVisualizer.SetGridVisible(true); // 显示Info if (blockShape?.BlockShapeData.blockShapeInfo.shapeName != null) { blockPuzzlePanel.ShowShapeInScreen(blockShape.BlockShapeData.blockShapeInfo); EventSystem.current.SetSelectedGameObject(null); selectedShapeName = null; } // 回收抽屉高亮,半开 shapeRecycleSlot.PreRecycle(); shapeRecycleSlot.SetRecycleAvaliable(true); // 每次拿起时也要校验 validator.Validate(grid.GetShapes()); } private void OnShapeDragUpdateDetailed(object sender, DragUpdateEventArgs args) { var blockShape = args.Shape; // 进行Snap检查并缓存结果 _currentSnapResult = grid.CheckSnapToGrid(blockShape); args.CurrentSnapResult = _currentSnapResult; // 在网格显示预览 grid.ShowSnapPreview(_currentSnapResult); // 更新回收槽状态 shapeRecycleSlot.UpdateSlotState(blockShape); } private void OnShapeDragEndDetailed(object sender, DragEndEventArgs args) { // 隐藏网格 grid.GridVisualizer.SetGridVisible(false); // 1. 首先尝试回收 if (TryHandleRecycle(args)) { return; } // 2. 然后尝试吸附到网格 if (TryHandleGridSnap(args)) { return; } // 3. 都未处理,保持未处理状态 args.IsHandled = false; args.ResultType = DragEndResultType.Dropped; // 重置预览网格 grid.ResetPreviewGrid(); grid.GridVisualizer.UpdateAllCellsVisual(); } /// /// 处理回收逻辑 /// private bool TryHandleRecycle(DragEndEventArgs args) { if (shapeRecycleSlot.CurrentState != PositionState.Open) { return false; } // 执行回收 shapeRecycleSlot.RecycleShape(args.Shape); // 清空屏幕并切换回LogScreen blockPuzzlePanel.ClearShapeInScreen(); blockPuzzlePanel.SwitchToLogScreen(); // 获取 Shape 名称 string shapeName = args.Shape.ShapeName; // 检查是否在不添加按钮的列表中 bool shouldAddButton = puzzleData.recycleNoButtonShapes == null || !puzzleData.recycleNoButtonShapes.Contains(shapeName); if (shouldAddButton) { // 向面板添加回收的形状 blockPuzzlePanel.OnDeviceRecycle(args.Shape); } else { SingleCastEventSystem.Global.Trigger(DialogEventEnum.StartNode, "ShapeRecycled"); } // 更新事件参数 args.IsHandled = true; args.FinalState = DragState.Idle; args.ResultType = DragEndResultType.Recycled; // 延时后进行销毁 ActionKit.Delay(1.0f, () => { shapeFactory.RecycleBlockShape(args.Shape); }).Start(this); return true; } /// /// 处理网格吸附逻辑 /// private bool TryHandleGridSnap(DragEndEventArgs args) { // 使用缓存的snap结果或重新检测 var snapResult = _currentSnapResult; if (!snapResult.canSnap) { snapResult = grid.CheckSnapToGrid(args.Shape); } if (!snapResult.canSnap) { return false; } // 执行网格吸附 grid.ResetPreviewGrid(); // 设置形状位置和状态 args.Shape.transform.position = grid.GridToWorld(snapResult.RootCell.x, snapResult.RootCell.y); args.Shape.transform.localScale = Vector3.one; // 更新网格状态 grid.TrySnapToGrid(args.Shape, snapResult.RootCell); // 更新事件参数 args.IsHandled = true; args.FinalState = DragState.Placed; args.ResultType = DragEndResultType.SnappedToGrid; // 验证放置 validator.Validate(grid.GetShapes()); // 处理Cursor var eventTrigger = args.Shape.GetComponent(); eventTrigger?.OnPointerUp(null); return true; } #endregion public void PopUpShape() { // 检查系统是否锁定 if (IsLocked) { return; } if (selectedShapeName == null) { return; } // 弹出形状 var blockShape = shapeFactory.CreateBlockShape(selectedShapeName); shapeRecycleSlot.PopUpShape(blockShape); blockShape.GetComponent().CurrentState = DragState.Idle; // 删除按钮 blockPuzzlePanel.RemoveDeviceButton(selectedShapeName); selectedShapeName = null; } // ---------------- 编辑器状态逻辑 ---------------- /// /// 仅加载配置项,不应用到游戏 /// public void LoadConfig() { if (BlockPuzzleKit.TryLoadBlockPuzzleData(puzzleData.puzzleName, out var blockPuzzleData)) { puzzleData = blockPuzzleData; Debug.Log("加载配置项成功"); } else { Debug.Log("加载配置项失败"); } } /// /// 将配置项应用到编辑器 /// public void ApplyConfig() { ClearGame(); shapeFactory = new ShapeFactory(shapeRoot); grid.InitializeInEditor(puzzleData.gridWidth, puzzleData.gridHeight, puzzleData.cellSize); // shapeRack.InitInEditor(puzzleData.shapeRackDataInfos); foreach (var shapeData in puzzleData.gridShapeDataInfos) { var shape = shapeFactory.CreateBlockShape(shapeData.shapeKey); shape.Rotate(shapeData.rotationAngle); grid.TrySnapToGrid(shape, shapeData.rootCell); } } public void SaveConfig() { var gridShapeDataInfos = grid.ShapeDict?.Values.ToArray(); // var shapeRackDataInfos = shapeRack.blockShapeDataList?.ToArray(); puzzleData.gridShapeDataInfos = gridShapeDataInfos; // puzzleData.shapeRackDataInfos = shapeRackDataInfos; BlockPuzzleKit.SaveBlockPuzzleData(puzzleData, puzzleData.puzzleName); } public void CreateShapeInEditor(string shapeKey) { if (shapeFactory == null) { shapeFactory = new ShapeFactory(shapeRoot); } shapeFactory.CreateBlockShape(shapeKey); } } }