feat(fix-system): 支持 Fix 系统任务面板与身体模块状态读档恢复
This commit is contained in:
@@ -72,7 +72,7 @@ namespace AibisDream.FixSystem
|
||||
RepairSystemManager.Register(this);
|
||||
}
|
||||
|
||||
/// <summary>捕获插线模块持久状态(分组 + UF + Chip)。</summary>
|
||||
/// <summary>捕获插线模块持久状态(分组 + UF + Chip + 高亮/报警)。</summary>
|
||||
public BodyModuleSnapshotDto CaptureBodyModuleSnapshot()
|
||||
{
|
||||
var dto = new BodyModuleSnapshotDto
|
||||
@@ -86,6 +86,13 @@ namespace AibisDream.FixSystem
|
||||
var chipModule = FindBodyModuleByName("Color")?.GetComponent<ChipModule>();
|
||||
chipModule?.CaptureState(dto);
|
||||
|
||||
foreach (var module in EnumerateAllBodyModules())
|
||||
{
|
||||
var name = module.data.moduleName;
|
||||
if (module.IsHighlighted) dto.highlightedModules.Add(name);
|
||||
if (module.IsAlarmed) dto.alarmedModules.Add(name);
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -105,6 +112,31 @@ namespace AibisDream.FixSystem
|
||||
|
||||
var chipModule = FindBodyModuleByName("Color")?.GetComponent<ChipModule>();
|
||||
chipModule?.ApplyState(dto);
|
||||
|
||||
var highlighted = new HashSet<string>(dto.highlightedModules ?? Enumerable.Empty<string>());
|
||||
var alarmed = new HashSet<string>(dto.alarmedModules ?? Enumerable.Empty<string>());
|
||||
|
||||
foreach (var module in EnumerateAllBodyModules())
|
||||
{
|
||||
var name = module.data.moduleName;
|
||||
module.Highlight(highlighted.Contains(name));
|
||||
module.Alarm(alarmed.Contains(name));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<BodyModule> EnumerateAllBodyModules()
|
||||
{
|
||||
if (_bodyModuleGroup != null)
|
||||
{
|
||||
foreach (var module in _bodyModuleGroup.GetComponentsInChildren<BodyModule>(true))
|
||||
yield return module;
|
||||
}
|
||||
|
||||
if (_headModuleGroup != null)
|
||||
{
|
||||
foreach (var module in _headModuleGroup.GetComponentsInChildren<BodyModule>(true))
|
||||
yield return module;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace AibisDream.FixSystem
|
||||
/// Yarn 可能在 Start 里异步加载材质完成前就调用 ModuleHightLight,需记下来待加载后再套材质。
|
||||
/// </summary>
|
||||
private bool _wantsHighlight;
|
||||
private bool _wantsAlarm;
|
||||
|
||||
public bool IsHighlighted => _wantsHighlight;
|
||||
public bool IsAlarmed => _wantsAlarm;
|
||||
|
||||
[SerializeField]
|
||||
private SpriteRenderer targetSpriteRenderer; // 目标的 SpriteRenderer
|
||||
@@ -99,7 +103,7 @@ namespace AibisDream.FixSystem
|
||||
else
|
||||
Debug.LogError("[BodyModule] Failed to load AlarmMaterial");
|
||||
|
||||
ApplyHighlightVisual();
|
||||
ApplyModuleVisual();
|
||||
}
|
||||
|
||||
#region 插槽功能
|
||||
@@ -165,23 +169,25 @@ namespace AibisDream.FixSystem
|
||||
public void Highlight(bool enable)
|
||||
{
|
||||
_wantsHighlight = enable;
|
||||
ApplyHighlightVisual();
|
||||
}
|
||||
|
||||
private void ApplyHighlightVisual()
|
||||
{
|
||||
if (targetSpriteRenderer == null || _highlightMaterial == null) return;
|
||||
if (_alarmMaterial != null && targetSpriteRenderer.material == _alarmMaterial) return;
|
||||
|
||||
targetSpriteRenderer.material = _wantsHighlight ? _highlightMaterial : _originalMaterial;
|
||||
ApplyModuleVisual();
|
||||
}
|
||||
|
||||
public void Alarm(bool enable)
|
||||
{
|
||||
if (targetSpriteRenderer != null && _alarmMaterial != null)
|
||||
{
|
||||
targetSpriteRenderer.material = enable ? _alarmMaterial : _originalMaterial;
|
||||
}
|
||||
_wantsAlarm = enable;
|
||||
ApplyModuleVisual();
|
||||
}
|
||||
|
||||
private void ApplyModuleVisual()
|
||||
{
|
||||
if (targetSpriteRenderer == null) return;
|
||||
|
||||
if (_wantsAlarm && _alarmMaterial != null)
|
||||
targetSpriteRenderer.material = _alarmMaterial;
|
||||
else if (_wantsHighlight && _highlightMaterial != null)
|
||||
targetSpriteRenderer.material = _highlightMaterial;
|
||||
else
|
||||
targetSpriteRenderer.material = _originalMaterial;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -22,6 +22,15 @@ namespace AibisDream.FixSystem
|
||||
SystemDic ??= new IOCContainer();
|
||||
Context = new FixSceneContext(SystemDic);
|
||||
Director = new FixSceneDirector();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (SaveRestoreOrchestrator.IsRestoring)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StartCoroutine(Director.Init(defaultMode));
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +149,11 @@ namespace AibisDream.FixSystem
|
||||
dto.pluggedModuleName = null;
|
||||
}
|
||||
|
||||
if (taskPanel != null)
|
||||
{
|
||||
taskPanel.CaptureSnapshot(out dto.isTaskPanelVisible, dto.tasks);
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -164,6 +169,8 @@ namespace AibisDream.FixSystem
|
||||
}
|
||||
|
||||
GetRepairPanel<CablePanel>()?.ApplyCableSnapshot(dto.isCableRetracted, dto.pluggedModuleName);
|
||||
|
||||
taskPanel?.ApplySnapshot(dto.isTaskPanelVisible, dto.tasks, immediate: true);
|
||||
}
|
||||
|
||||
/// <summary>读档终态:跳过 StartAllSystems 动画,直接写面板壳层状态。</summary>
|
||||
|
||||
@@ -111,6 +111,17 @@ namespace AibisDream.FixSystem
|
||||
|
||||
if (retracted)
|
||||
{
|
||||
if (ShouldSkipRetractOnRestore())
|
||||
{
|
||||
if (isCableRetracted)
|
||||
{
|
||||
DropDownCableImmediate();
|
||||
}
|
||||
|
||||
curSocket = null;
|
||||
return;
|
||||
}
|
||||
|
||||
SetRetractCable();
|
||||
curSocket = null;
|
||||
return;
|
||||
@@ -153,6 +164,7 @@ namespace AibisDream.FixSystem
|
||||
var socketPos = module.GetSocketPos();
|
||||
PlugRef.RestoreInsertedAt(socketPos);
|
||||
CableRef.SetEndPos(socketPos);
|
||||
SetCableMode(CableMode.Visual);
|
||||
BodyModuleSystem.CloseModuleSlots(null);
|
||||
}
|
||||
|
||||
@@ -166,6 +178,13 @@ namespace AibisDream.FixSystem
|
||||
PlugRef.SetSpriteVisible(true);
|
||||
}
|
||||
|
||||
private static bool ShouldSkipRetractOnRestore()
|
||||
{
|
||||
return FixSystemCenter.Instance != null
|
||||
&& FixSystemCenter.Director.HasMode
|
||||
&& FixSystemCenter.Director.CurrentMode == FixSceneMode.BodyModule;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 获取线缆方向并更新转盘旋转
|
||||
@@ -177,10 +196,14 @@ namespace AibisDream.FixSystem
|
||||
|
||||
public void ResetPlug()
|
||||
{
|
||||
// 不在初始插孔里,就从当前插孔拔出来,插回初始插孔
|
||||
PlugRef.PullUpSocket();
|
||||
if (IsPlugInSocket())
|
||||
{
|
||||
PlugRef.PullUpSocket();
|
||||
}
|
||||
|
||||
BodyModuleSystem.CloseModuleSlots(null);
|
||||
PlugRef.ReturnToStartPosition();
|
||||
DropDownCableImmediate();
|
||||
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/mods_close");
|
||||
AudioManager.Instance.PlaySfx("event:/FollowInput/plugdrop");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using AibisDream.Framework;
|
||||
using AibisDream.SaveSystem;
|
||||
using AibisDream.Utility;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
@@ -10,6 +11,9 @@ namespace AibisDream.FixSystem
|
||||
{
|
||||
public class TaskPanel : MonoBehaviour, ILineView
|
||||
{
|
||||
private const float HiddenLocalX = -10.32f;
|
||||
private const float ShownLocalX = -7.12f;
|
||||
|
||||
#region 索引
|
||||
|
||||
[SerializeField] private Transform taskRoot;
|
||||
@@ -26,8 +30,9 @@ namespace AibisDream.FixSystem
|
||||
|
||||
public void ShowPanel()
|
||||
{
|
||||
taskRoot.DOLocalMoveX(-7.12f, 1f);
|
||||
taskRoot.DOLocalMoveX(ShownLocalX, 1f);
|
||||
}
|
||||
|
||||
public void CompleteTask(string lineId)
|
||||
{
|
||||
if (_taskDict.Remove(lineId, out var taskItem))
|
||||
@@ -54,15 +59,70 @@ namespace AibisDream.FixSystem
|
||||
return;
|
||||
}
|
||||
|
||||
var taskItem = Instantiate(_taskItemPrefab, taskListParent);
|
||||
var task = taskItem.GetComponent<TMP_Text>();
|
||||
task.text = $"\u25cf {token.lineInfo.lineText}";
|
||||
AddTaskItem(token.lineInfo.lineId, $"\u25cf {token.lineInfo.lineText}");
|
||||
token.TextStart();
|
||||
|
||||
_taskDict[token.lineInfo.lineId] = taskItem;
|
||||
token.TextShown();
|
||||
token.ForceAdvance();
|
||||
}
|
||||
|
||||
public void CaptureSnapshot(out bool isPanelVisible, List<TaskEntrySnapshotDto> tasks)
|
||||
{
|
||||
isPanelVisible = Mathf.Approximately(taskRoot.localPosition.x, ShownLocalX);
|
||||
tasks.Clear();
|
||||
|
||||
foreach (var kv in _taskDict)
|
||||
{
|
||||
var text = kv.Value.GetComponent<TMP_Text>()?.text ?? string.Empty;
|
||||
tasks.Add(new TaskEntrySnapshotDto
|
||||
{
|
||||
lineId = kv.Key,
|
||||
text = text
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplySnapshot(bool isPanelVisible, List<TaskEntrySnapshotDto> tasks, bool immediate)
|
||||
{
|
||||
ClearTasks();
|
||||
|
||||
if (tasks != null)
|
||||
{
|
||||
foreach (var entry in tasks)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry.lineId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AddTaskItem(entry.lineId, entry.text);
|
||||
}
|
||||
}
|
||||
|
||||
if (immediate)
|
||||
{
|
||||
taskRoot.DOKill();
|
||||
SetPanelVisibleImmediate(isPanelVisible);
|
||||
}
|
||||
else if (isPanelVisible)
|
||||
{
|
||||
ShowPanel();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddTaskItem(string lineId, string text)
|
||||
{
|
||||
var taskItem = Instantiate(_taskItemPrefab, taskListParent);
|
||||
var task = taskItem.GetComponent<TMP_Text>();
|
||||
task.text = text;
|
||||
_taskDict[lineId] = taskItem;
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(taskListParent.GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
private void SetPanelVisibleImmediate(bool visible)
|
||||
{
|
||||
var pos = taskRoot.localPosition;
|
||||
pos.x = visible ? ShownLocalX : HiddenLocalX;
|
||||
taskRoot.localPosition = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.SaveSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// sections["fixPanel"]:FixPanel 壳层 + 线缆/插头。RestoreOrder=66,在 fix 之后、bodyModule 之前。
|
||||
/// sections["fixPanel"]:FixPanel 壳层 + 线缆/插头 + TaskPanel。RestoreOrder=66,在 fix(65) 之后写回面板/线缆/任务快照。
|
||||
/// </summary>
|
||||
public class FixPanelSnapshotProvider : ISyncSnapshotProvider
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user