Files
aibis-dream/Assets/Scripts/FixSystem/PunchTape/PunchTapeManager.cs
T

208 lines
6.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using AibisDream.Kit;
using AibisDream.SaveSystem;
using UnityEngine;
namespace AibisDream.FixSystem
{
/// <summary>
/// 打孔带系统入口:收藏数据、Yarn 命令、弹窗与收藏夹面板代理。
/// </summary>
public class PunchTapeManager : Singleton<PunchTapeManager>
{
public GameObject punchTapecluePrefab;
[SerializeField] private PunchTapeCatalog punchTapeCatalog;
public PunchTapeCatalog Catalog => punchTapeCatalog;
[SerializeField] private PunchTapeFavoritesPanel favoritesPanel;
public PunchTapeFavoritesPanel FavoritesPanel => favoritesPanel;
[SerializeField] private PunchTapePrinter punchTapePrinter;
public PunchTapePrinter PunchTapePrinter => punchTapePrinter;
private readonly List<PunchTape> _favorites = new();
private GameObject currentPunchTapeGO;
/// <summary>收藏列表变更时通知 <see cref="PunchTapeFavoritesPanel"/> 等订阅方。</summary>
public event Action OnCollectionChanged;
public IReadOnlyList<PunchTape> GetFavorites()
{
return _favorites;
}
public PunchTapeSnapshotDto CapturePunchTapeSnapshot()
{
return new PunchTapeSnapshotDto
{
favorites = _favorites.Select(t => new PunchTape(t.DefinitionId)
{
used = t.used
}).ToList()
};
}
public void ApplyPunchTapeSnapshot(PunchTapeSnapshotDto dto)
{
_favorites.Clear();
if (dto?.favorites != null)
{
foreach (var tape in dto.favorites)
{
if (!TryGetDefinition(tape, out _))
{
Debug.LogWarning(
$"[PunchTapeManager] 存档中的打孔带 ID '{tape?.DefinitionId ?? "<null>"}' 无法解析,已跳过。",
this);
continue;
}
if (!_favorites.Contains(tape))
_favorites.Add(tape);
}
}
OnCollectionChanged?.Invoke();
}
public void AddPunchTape(PunchTape punchTape)
{
if (punchTape == null) return;
if (!TryGetDefinition(punchTape, out _))
{
Debug.LogError($"[PunchTapeManager] 无法收藏未知打孔带 '{punchTape.DefinitionId}'。", this);
return;
}
if (_favorites.Contains(punchTape))
return;
_favorites.Add(punchTape);
OnCollectionChanged?.Invoke();
}
public void RemovePunchTape(PunchTape punchTape)
{
if (punchTape == null) return;
if (!_favorites.Remove(punchTape))
return;
OnCollectionChanged?.Invoke();
}
public void OpenFavoritesPanel()
{
if (favoritesPanel == null)
{
Debug.LogWarning("[PunchTapeManager] 未指定 _favoritesPanel,无法打开收藏夹面板。", this);
return;
}
favoritesPanel.OpenPanel();
}
public void CloseFavoritesPanel()
{
if (favoritesPanel == null)
{
Debug.LogWarning("[PunchTapeManager] 未指定 _favoritesPanel,无法关闭收藏夹面板。", this);
return;
}
favoritesPanel.ClosePanel();
}
public bool TryGetDefinition(string definitionId, out PunchTapeDefinition definition)
{
definition = null;
if (punchTapeCatalog == null)
{
Debug.LogError("[PunchTapeManager] 未配置 PunchTapeCatalog。", this);
return false;
}
var catalogErrors = punchTapeCatalog.GetValidationErrors();
if (catalogErrors.Count > 0)
{
Debug.LogError(
$"[PunchTapeManager] PunchTapeCatalog 配置无效:\n{string.Join("\n", catalogErrors)}",
this);
return false;
}
if (!punchTapeCatalog.TryGetDefinition(definitionId, out definition))
{
Debug.LogError($"[PunchTapeManager] 未找到打孔带 ID '{definitionId}'。", this);
definition = null;
return false;
}
if (!definition.TryValidate(out var error))
{
Debug.LogError($"[PunchTapeManager] 打孔带 ID '{definitionId}' 无效:{error}", this);
definition = null;
return false;
}
return true;
}
public bool TryGetDefinition(PunchTape punchTape, out PunchTapeDefinition definition)
{
return TryGetDefinition(punchTape?.DefinitionId, out definition);
}
public void GeneratePunchTapeWindow(string definitionId, bool directlyAddToFavorites = false)
{
if (!TryGetDefinition(definitionId, out var definition))
return;
PunchTape punchTape = new PunchTape(definitionId);
if (directlyAddToFavorites)
{
AddPunchTape(punchTape);
return;
}
GameObject go = Instantiate(punchTapecluePrefab, favoritesPanel.transform);
PunchTapeItem item = go.GetComponent<PunchTapeItem>();
if (item == null)
{
Debug.LogError("[PunchTapeManager] 生成 Prefab 缺少 PunchTapeItem。", go);
Destroy(go);
return;
}
currentPunchTapeGO = go;
item.Setup(punchTape, definition);
}
/// <summary>
/// 将当前弹窗中的打孔带收入收藏。兼容旧 Yarn&lt;&lt;CollectionClue ClueManager&gt;&gt; 会传入参数,仍应执行收藏。
/// </summary>
public void CollectPunchTapeFromWindow()
{
if (currentPunchTapeGO == null)
{
Debug.LogWarning("PunchTapeManager: 没有当前打孔带窗口,无法收藏。");
return;
}
PunchTapeItem item = currentPunchTapeGO.GetComponent<PunchTapeItem>();
if (item == null)
{
Debug.LogWarning("PunchTapeManager: 当前物体上缺少 PunchTapeItem。");
return;
}
AddPunchTape(item.GetPunchTapeData());
Destroy(currentPunchTapeGO.gameObject);
currentPunchTapeGO = null;
}
}
}