diff --git a/Assets/Scripts/MiniGame/HuoShan/SalesSystem/SalesManager.cs b/Assets/Scripts/MiniGame/HuoShan/SalesSystem/SalesManager.cs index 29ef32f09..431bb2cef 100644 --- a/Assets/Scripts/MiniGame/HuoShan/SalesSystem/SalesManager.cs +++ b/Assets/Scripts/MiniGame/HuoShan/SalesSystem/SalesManager.cs @@ -4,7 +4,9 @@ using Cinemachine; using AibisDream; using AibisDream.FixSystem; using AibisDream.Framework; +using System.Collections; using System.Collections.Generic; +using DG.Tweening; using AibisDream.MiniGame.HuoShan; namespace AibisDream.MiniGame.Language @@ -49,6 +51,9 @@ namespace AibisDream.MiniGame.Language [Tooltip("每轮转动完成后调用的 Yarn 节点名,可通过 $salesTurnIndex 分支不同内容")] [SerializeField] private string crankCompleteNode = "销售模块转动完成"; + [Tooltip("滑片开始转动时调用的 Yarn 节点名,配合 ChipModule 解释正在做的步骤,可通过 $salesTurnIndex 分支")] + [SerializeField] private string crankSlideStartNode = "销售转动_开始"; + // [Header("销售模块深入 - 阶段事件(滑片进度阈值)")] // [Tooltip("语义组织阶段时调用的 Yarn 节点名(滑片进度 ≥ 1/3)")] // [SerializeField] private string phaseSemanticNode = "语义组织达到"; @@ -59,7 +64,37 @@ namespace AibisDream.MiniGame.Language // [Tooltip("风格阶段时调用的 Yarn 节点名(滑片进度 ≥ 1)")] // [SerializeField] private string phaseStyleNode = "风格达到"; + [Header("处理器深入模式")] + [Tooltip("盖子 SpriteRenderer(深入模式下淡出)")] + [SerializeField] private SpriteRenderer processorCover; + + [Tooltip("旋钮控制器(不填则从 saleView 下查找)")] + [SerializeField] private KnobController knobController; + + [Tooltip("辉光管粒子效果(不填则从 saleView 下查找)")] + [SerializeField] private GlowTubeEffect glowTubeEffect; + + [Header("SaleView 进入动画")] + [Tooltip("进入动画控制器(不填则从 saleView 下查找 SaleViewEnterAnimation)")] + [SerializeField] private SaleViewEnterAnimation saleViewEnterAnimation; + + [Tooltip("深入模式缩放倍数")] + [SerializeField] private float deepModeScale = 1.2f; + + [Tooltip("深入模式 X 偏移(负方向)")] + [SerializeField] private float deepModeOffsetX = -5f; + + [Tooltip("深入模式动画时长")] + [SerializeField] private float deepModeTransitionDuration = 0.6f; + + [Tooltip("盖子淡出时长")] + [SerializeField] private float coverFadeDuration = 0.5f; + private readonly List registeredCameras = new(); + private bool _isProcessorDeepMode; + private Vector3 _saleViewOriginalPos; + private Vector3 _saleViewOriginalScale; + private Sequence _deepModeSequence; private int _currentTurnIndex; // 当前已完成第几轮(1-based) @@ -78,6 +113,15 @@ namespace AibisDream.MiniGame.Language /// 滑片控制器(供 Yarn 命令等通过 SalesManager 获取) public SliderController SliderController => sliderController; + /// 旋钮控制器 + public KnobController KnobController => knobController; + + /// 辉光管效果 + public GlowTubeEffect GlowTubeEffect => glowTubeEffect; + + /// 是否处于处理器深入模式 + public bool IsProcessorDeepMode => _isProcessorDeepMode; + private void Awake() { // 对话气泡槽组(SaleSystem 下名为 "Bubble Slots" 的 GameObject) @@ -99,12 +143,17 @@ namespace AibisDream.MiniGame.Language RegisterToSystem(); RegisterCameras(); FindSaleView(); + FindSaleViewEnterAnimation(); FindCrankController(); FindSliderController(); + FindKnobController(); + FindGlowTubeEffect(); + FindProcessorCover(); } private void OnDestroy() { + _deepModeSequence?.Kill(); UnregisterCameras(); UnsubscribeFromCrankSlider(); } @@ -137,6 +186,18 @@ namespace AibisDream.MiniGame.Language } } + /// + /// 查找 SaleView 进入动画(从 saleView 下查找) + /// + private void FindSaleViewEnterAnimation() + { + if (saleViewEnterAnimation != null) return; + var root = saleView != null ? saleView.transform : transform; + saleViewEnterAnimation = root.GetComponentInChildren(true); + if (saleViewEnterAnimation != null) + Debug.Log("[SalesManager] 找到 SaleViewEnterAnimation"); + } + /// /// 查找发条控制器(从 saleView 或自身下查找) /// @@ -228,6 +289,11 @@ namespace AibisDream.MiniGame.Language #endif if (_currentTurnIndex > totalTurns) return; + // 滑片开始转动前,先触发 ChipModule 解释当前步骤(Stage3 等配合) + StorageSystem.Instance?.SetValue("$salesTurnIndex", (float)_currentTurnIndex); + if (!string.IsNullOrEmpty(crankSlideStartNode)) + DialogController.Instance?.StartDialogNode(crankSlideStartNode); + if (sliderController != null) { // 滑片移动至当前轮对应的段,时长与发条回位一致 @@ -337,6 +403,7 @@ namespace AibisDream.MiniGame.Language if (saleView != null) { saleView.SetActive(true); + saleViewEnterAnimation?.PlayEnterAnimation(); Debug.Log("[SalesManager] 销售系统已打开"); } else @@ -351,6 +418,7 @@ namespace AibisDream.MiniGame.Language public void CloseView() { UnsubscribeFromCrankSlider(); + saleViewEnterAnimation?.ResetToIdle(); if (saleView != null) { saleView.SetActive(false); @@ -388,5 +456,167 @@ namespace AibisDream.MiniGame.Language sliderController?.ResetPosition(); ResetPhase(); } + + #region 处理器深入模式 + + private void FindKnobController() + { + if (knobController != null) return; + var root = saleView != null ? saleView.transform : transform; + knobController = root.GetComponentInChildren(true); + if (knobController == null) + knobController = GetComponentInChildren(true); + if (knobController != null) + Debug.Log("[SalesManager] Found KnobController"); + } + + private void FindGlowTubeEffect() + { + if (glowTubeEffect != null) return; + var root = saleView != null ? saleView.transform : transform; + glowTubeEffect = root.GetComponentInChildren(true); + if (glowTubeEffect == null) + glowTubeEffect = GetComponentInChildren(true); + if (glowTubeEffect != null) + Debug.Log("[SalesManager] Found GlowTubeEffect"); + } + + private void FindProcessorCover() + { + if (processorCover != null) return; + var root = saleView != null ? saleView.transform : transform; + foreach (var t in root.GetComponentsInChildren(true)) + { + if (t.name == "\u76d6\u5b50") + { + processorCover = t.GetComponent(); + if (processorCover != null) + Debug.Log("[SalesManager] Found processor cover"); + break; + } + } + } + + /// + /// 进入处理器深入模式:面板放大右移 → 盖子淡出 → 启动旋钮和辉光管 + /// + public void EnterProcessorDeepMode() + { + if (_isProcessorDeepMode) return; + if (saleView == null) + { + Debug.LogError("[SalesManager] SaleView is null, cannot enter processor deep mode", this); + return; + } + + _isProcessorDeepMode = true; + StartCoroutine(EnterProcessorDeepModeRoutine()); + } + + private IEnumerator EnterProcessorDeepModeRoutine() + { + _deepModeSequence?.Kill(); + + var viewTransform = saleView.transform; + _saleViewOriginalPos = viewTransform.localPosition; + _saleViewOriginalScale = viewTransform.localScale; + + // Activate cover so we can fade it out + if (processorCover != null) + { + processorCover.gameObject.SetActive(true); + var c = processorCover.color; + processorCover.color = new Color(c.r, c.g, c.b, 1f); + } + + // Build animation sequence + _deepModeSequence = DOTween.Sequence(); + + // Step 1: Scale up + shift X + Vector3 targetPos = _saleViewOriginalPos + new Vector3(deepModeOffsetX, 0f, 0f); + Vector3 targetScale = _saleViewOriginalScale * deepModeScale; + + _deepModeSequence.Append( + viewTransform.DOLocalMove(targetPos, deepModeTransitionDuration).SetEase(Ease.OutCubic) + ); + _deepModeSequence.Join( + viewTransform.DOScale(targetScale, deepModeTransitionDuration).SetEase(Ease.OutCubic) + ); + + // Step 2: Fade out cover + if (processorCover != null) + { + _deepModeSequence.Append( + processorCover.DOFade(0f, coverFadeDuration).SetEase(Ease.InQuad) + ); + _deepModeSequence.AppendCallback(() => + { + processorCover.gameObject.SetActive(false); + }); + } + + // Step 3: Enable knob + glow tube + _deepModeSequence.AppendCallback(() => + { + if (glowTubeEffect != null) glowTubeEffect.gameObject.SetActive(true); + if (knobController != null) + { + knobController.gameObject.SetActive(true); + knobController.Reset(); + } + Debug.Log("[SalesManager] Processor deep mode entered"); + }); + + yield return _deepModeSequence.WaitForCompletion(); + } + + /// + /// 退出处理器深入模式:恢复面板位置/缩放、恢复盖子 + /// + public void ExitProcessorDeepMode() + { + if (!_isProcessorDeepMode) return; + _isProcessorDeepMode = false; + StartCoroutine(ExitProcessorDeepModeRoutine()); + } + + private IEnumerator ExitProcessorDeepModeRoutine() + { + _deepModeSequence?.Kill(); + + if (knobController != null) knobController.gameObject.SetActive(false); + if (glowTubeEffect != null) glowTubeEffect.gameObject.SetActive(false); + + _deepModeSequence = DOTween.Sequence(); + + // Restore cover + if (processorCover != null) + { + processorCover.gameObject.SetActive(true); + var c = processorCover.color; + processorCover.color = new Color(c.r, c.g, c.b, 0f); + _deepModeSequence.Append( + processorCover.DOFade(1f, coverFadeDuration).SetEase(Ease.OutQuad) + ); + } + + // Restore position and scale + var viewTransform = saleView.transform; + _deepModeSequence.Append( + viewTransform.DOLocalMove(_saleViewOriginalPos, deepModeTransitionDuration).SetEase(Ease.InOutCubic) + ); + _deepModeSequence.Join( + viewTransform.DOScale(_saleViewOriginalScale, deepModeTransitionDuration).SetEase(Ease.InOutCubic) + ); + + _deepModeSequence.AppendCallback(() => + { + Debug.Log("[SalesManager] Processor deep mode exited"); + }); + + yield return _deepModeSequence.WaitForCompletion(); + } + + #endregion } } diff --git a/Assets/Scripts/MiniGame/HuoShan/SalesSystem/SalesYarnCommand.cs b/Assets/Scripts/MiniGame/HuoShan/SalesSystem/SalesYarnCommand.cs index 4a626681c..d6569a8b7 100644 --- a/Assets/Scripts/MiniGame/HuoShan/SalesSystem/SalesYarnCommand.cs +++ b/Assets/Scripts/MiniGame/HuoShan/SalesSystem/SalesYarnCommand.cs @@ -140,7 +140,7 @@ namespace AibisDream.MiniGame.HuoShan if (sliderController != null) { Debug.Log($"[SalesYarnCommand] 移动滑片到位置{normalizedPosition},时长{duration}秒"); - + sliderController.SlideToNormalized(normalizedPosition, duration); yield return new WaitForSeconds(duration); } @@ -322,18 +322,50 @@ namespace AibisDream.MiniGame.HuoShan } /// - /// 进入处理器深入模式(面板右移) + /// 进入处理器深入模式(面板放大右移 + 盖子淡出 + 旋钮/辉光管启动) /// 用法: <> /// [YarnCommand("enter_processor_mode")] public static IEnumerator EnterProcessorMode() { - Debug.Log("[SalesYarnCommand] 进入处理器深入模式"); + var manager = GetSalesManager(); + if (manager == null) + { + Debug.LogWarning("[SalesYarnCommand] SalesManager not found"); + yield break; + } - // 触发面板右移动画 - // 可以使用DOTween或Timeline + Debug.Log("[SalesYarnCommand] Entering processor deep mode"); + manager.EnterProcessorDeepMode(); - yield return new WaitForSeconds(1f); + while (manager.IsProcessorDeepMode == false) + yield return null; + + // Wait a frame for everything to settle + yield return null; + } + + /// + /// 退出处理器深入模式(恢复面板位置/缩放、恢复盖子) + /// 用法: <> + /// + [YarnCommand("exit_processor_mode")] + public static IEnumerator ExitProcessorMode() + { + var manager = GetSalesManager(); + if (manager == null) + { + Debug.LogWarning("[SalesYarnCommand] SalesManager not found"); + yield break; + } + + Debug.Log("[SalesYarnCommand] Exiting processor deep mode"); + manager.ExitProcessorDeepMode(); + + while (manager.IsProcessorDeepMode) + yield return null; + + yield return null; } ///