Files
aibis-dream/Assets/Scripts/MiniGame/BlockPuzzle/Class/BlockPuzzleSystem.cs
T

460 lines
15 KiB
C#

using UnityEngine;
using Cinemachine;
using AibisDream.Kit;
using AibisDream.Utility;
using System.Linq;
using AibisDream.Framework;
using AibisDream.FixSystem;
using UnityEngine.EventSystems;
namespace AibisDream
{
public class BlockPuzzleSystem : Singleton<BlockPuzzleSystem>
{
[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);
blockPuzzlePanel = FixPanelSystem.GetRepairPanel<BlockPuzzlePanel>();
if (initializeOnStart)
{
Initialize();
}
CameraKit.Instance?.RegisterCamera(CameraEnum.BlockPuzzle, GetComponentInChildren<ICinemachineCamera>());
}
public override void OnSingletonDestroy()
{
FixSystemCenter.SystemDic.Unregister<BlockPuzzleSystem>();
CameraKit.Instance?.UnRegisterCamera(CameraEnum.BlockPuzzle);
}
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<BlockPuzzleValidator>(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());
// 如果验证通过, 则设置变量并弹出对话
if (validateResult.isPass)
{
// StorageSystem.Instance.SetValue("$block_puzzle_pass", true);
// DialogController.Instance.StartDialogNode("方块拼图完成");
Debug.Log("方块拼图完成");
}
}
public void ClearGame()
{
grid.Clear();
shapeRoot.DestroyAllChildren();
// 重置锁定状态
SetLocked(false);
}
// --------------------- 锁定状态管理 -------------------
/// <summary>
/// 设置系统锁定状态
/// </summary>
/// <param name="locked">是否锁定</param>
public void SetLocked(bool locked)
{
IsLocked = locked;
UpdateInteractionState();
}
/// <summary>
/// 更新所有交互组件的状态
/// </summary>
private void UpdateInteractionState()
{
// 更新所有形状的拖拽状态
if (shapeFactory != null)
{
shapeFactory.SetAllShapesInteractable(!IsLocked);
}
// 更新按钮的交互状态
if (blockPuzzlePanel != null)
{
if (blockPuzzlePanel.LockButton != null)
{
blockPuzzlePanel.LockButton.GetComponent<BlockSubmitHander>().SetLockedState(IsLocked);
}
if (blockPuzzlePanel.PopUpButton != null)
{
blockPuzzlePanel.PopUpButton.interactable = !IsLocked;
}
}
}
public void EnableDrag()
{
shapeFactory.SetAllShapesInteractionMode(InteractionMode.Drag);
}
public void PlayShapeAnimation(string triggerName)
{
// 播放Timeline
TimelineCenter.Instance.PlayTimeline("维修面板");
}
public void LoadShapeRack()
{
blockPuzzlePanel.LoadBackupDevices();
}
// --------------------- 维修面板同步 -------------------
private string selectedShapeName;
/// <summary>
/// 组装各系统之间相互逻辑
/// </summary>
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);
}
// 旧的事件处理方法已迁移到新的详细事件处理器
// OnShapeDragStart -> OnShapeDragStartDetailed
// OnShapeDragEnd -> OnShapeDragEndDetailed
// OnShapeDragUpdate -> OnShapeDragUpdateDetailed
public void OnShapeClick(BlockShape blockShape)
{
// 点击形状
blockPuzzlePanel.ShowShapeInScreen(blockShape.BlockShapeData.blockShapeInfo);
}
#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)
{
var blockShape = args.Shape;
// 隐藏网格
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();
}
/// <summary>
/// 处理回收逻辑
/// </summary>
private bool TryHandleRecycle(DragEndEventArgs args)
{
if (shapeRecycleSlot.CurrentState != PositionState.Open)
{
return false;
}
// 执行回收
shapeRecycleSlot.RecycleShape(args.Shape);
// 清空屏幕并切换回LogScreen
blockPuzzlePanel.ClearShapeInScreen();
blockPuzzlePanel.SwitchToLogScreen();
// 向面板添加回收的形状
blockPuzzlePanel.OnDeviceRecycle(args.Shape);
// 更新事件参数
args.IsHandled = true;
args.FinalState = DragState.Idle;
args.ResultType = DragEndResultType.Recycled;
// 延时后进行销毁
ActionKit.Delay(1.0f, () => {
shapeFactory.RecycleBlockShape(args.Shape);
}).Start(this);
return true;
}
/// <summary>
/// 处理网格吸附逻辑
/// </summary>
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<EventTriggerEx>();
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<ShapeDragger>().CurrentState = DragState.Idle;
// 删除按钮
blockPuzzlePanel.RemoveDeviceButton(selectedShapeName);
selectedShapeName = null;
}
// ---------------- 编辑器状态逻辑 ----------------
/// <summary>
/// 仅加载配置项,不应用到游戏
/// </summary>
public void LoadConfig()
{
if (BlockPuzzleKit.TryLoadBlockPuzzleData(puzzleData.puzzleName, out var blockPuzzleData))
{
puzzleData = blockPuzzleData;
Debug.Log("加载配置项成功");
}
else
{
Debug.Log("加载配置项失败");
}
}
/// <summary>
/// 将配置项应用到编辑器
/// </summary>
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);
}
}
}