using System.Collections; using AibisDream.Framework; using UnityEngine; namespace AibisDream.FixSystem { /// /// Directs Fix scene mode transitions. This is a scene cue board, not a gameplay state machine: /// cues orchestrate cameras, timelines, UI masks, bubbles and interaction setup. /// public class FixSceneDirector { public FixSceneMode CurrentMode { get; private set; } public string CurrentArgs { get; private set; } = ""; public bool HasMode { get; private set; } public bool IsTransitioning { get; private set; } private IFixSceneCue _currentCue; public IEnumerator Init(FixSceneMode initMode) { yield return TransitionInternal(initMode, "", FixTransitionMode.Immediate); } public IEnumerator TransitionTo(FixSceneMode nextMode, string args = "") { yield return TransitionInternal(nextMode, args, FixTransitionMode.Animated); } public IEnumerator TransitionToImmediate(FixSceneMode nextMode, string args = "") { yield return TransitionInternal(nextMode, args, FixTransitionMode.Immediate); } public IEnumerator QuitCurrentMode() { if (_currentCue != null) { var transition = new FixTransition(CurrentMode, FixSceneMode.Default, "", FixTransitionMode.Animated); yield return _currentCue.Exit(transition); } CurrentArgs = ""; _currentCue = null; CurrentMode = FixSceneMode.Default; HasMode = false; IsTransitioning = false; } /// /// Clears director state without running cue exits. Used while the owning scene is /// being destroyed, when cue dependencies may already have been torn down. /// public void Reset() { CurrentArgs = ""; _currentCue = null; CurrentMode = FixSceneMode.Default; HasMode = false; IsTransitioning = false; } private IEnumerator TransitionInternal(FixSceneMode nextMode, string args, FixTransitionMode mode) { if (IsTransitioning && mode == FixTransitionMode.Animated) { Debug.LogWarning($"[FixSceneDirector] Transition ignored while another transition is running: {CurrentMode} -> {nextMode}"); yield break; } if (HasMode && CurrentMode.Equals(nextMode)) { yield break; } IsTransitioning = true; var transition = new FixTransition(HasMode ? CurrentMode : null, nextMode, args, mode); if (mode == FixTransitionMode.Animated && _currentCue != null) { yield return _currentCue.Exit(transition); } _currentCue = CreateCue(nextMode); CurrentMode = nextMode; CurrentArgs = args ?? ""; HasMode = true; EnumEventSystem.Global.Send(EventEnum.FixSceneModeChanged, nextMode); if (mode == FixTransitionMode.Immediate) { yield return _currentCue.EnterImmediate(transition); } else { yield return _currentCue.Enter(transition); } IsTransitioning = false; } private static IFixSceneCue CreateCue(FixSceneMode nextMode) { return nextMode switch { FixSceneMode.Default => new DefaultCue(), FixSceneMode.Clinic => new ClinicCue(), FixSceneMode.BodyModule => new BodyModuleCue(), FixSceneMode.Memory => new MemoryCue(), FixSceneMode.Eye => new EyeCue(), FixSceneMode.UF => new UfCue(), FixSceneMode.Expression => new ExpressionCue(), FixSceneMode.Emo => new EmoCue(), FixSceneMode.Op => new OpCue(), FixSceneMode.EmoCut => new EmoCutCue(), FixSceneMode.MemoryCut => new MemoryCutCue(), FixSceneMode.LogicCut => new LogicCutCue(), FixSceneMode.Dream => new DreamCue(), FixSceneMode.AnalysisMode => new AnalysisModeCue(), FixSceneMode.Sales => new SalesCue(), FixSceneMode.BlockPuzzle => new BlockPuzzleCue(), _ => new DefaultCue() }; } } }