#if UNITY_EDITOR || DEVELOPMENT_BUILD using System.Collections; using System.Collections.Generic; using AibisDream.Framework; using AibisDream.FixSystem; using AibisDream.SaveSystem; using UnityEngine; using UnityEngine.SceneManagement; namespace AibisDream { public class PeipeiMemoryJumpTool : MonoBehaviour { private const string TargetSceneKey = "Scene/PeipeiFixScene"; private const string TargetSceneName = "PeipeiFixScene"; private const float WaitTimeout = 15f; private const float UiMargin = 16f; private const float DevButtonWidth = 96f; private const float DevButtonHeight = 34f; private const float CommandButtonWidth = 220f; private const float CommandButtonHeight = 34f; private const float StatusWidth = 360f; private const float StatusHeight = 28f; private const int DevCommandCount = 1; private static readonly PunchTape[] TestPunchTapes = { new("EyeView", "\u5929\u7a7a", "liuying1-3"), new("EyeView", "\u6d77\u62a5", "liuying1-1"), new("EyeView", "\u690d\u7269", "liuying1-2") }; private static PeipeiMemoryJumpTool instance; private bool isJumping; private bool menuOpen; private string status = ""; private float statusVisibleUntil; private GUIStyle buttonStyle; private GUIStyle menuBoxStyle; private GUIStyle statusStyle; [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] private static void Bootstrap() { if (instance != null) return; var existing = FindObjectOfType(); if (existing != null) { instance = existing; DontDestroyOnLoad(existing.gameObject); return; } var toolObject = new GameObject("[Dev] Peipei Memory Jump Tool"); DontDestroyOnLoad(toolObject); instance = toolObject.AddComponent(); } private void OnGUI() { EnsureStyles(); float buttonX = Screen.width - UiMargin - DevButtonWidth; float buttonY = Screen.height - UiMargin - DevButtonHeight; var devButtonRect = new Rect(buttonX, buttonY, DevButtonWidth, DevButtonHeight); if (menuOpen) DrawCommandMenu(devButtonRect); string label = isJumping ? "Busy..." : "Dev"; if (GUI.Button(devButtonRect, label, buttonStyle)) menuOpen = !menuOpen; if (!string.IsNullOrEmpty(status) && Time.unscaledTime < statusVisibleUntil) { float menuHeight = GetMenuHeight(); float statusY = menuOpen ? buttonY - menuHeight - StatusHeight - UiMargin : buttonY - StatusHeight - 8f; var statusRect = new Rect( Screen.width - UiMargin - StatusWidth, Mathf.Max(UiMargin, statusY), StatusWidth, StatusHeight); GUI.Label(statusRect, status, statusStyle); } } private void DrawCommandMenu(Rect devButtonRect) { float menuHeight = GetMenuHeight(); float menuX = Screen.width - UiMargin - CommandButtonWidth; float menuY = devButtonRect.y - menuHeight - 8f; var menuRect = new Rect(menuX, menuY, CommandButtonWidth, menuHeight); GUI.Box(menuRect, GUIContent.none, menuBoxStyle); var commandRect = new Rect( menuRect.x + 6f, menuRect.y + 6f, menuRect.width - 12f, CommandButtonHeight); DrawCommandButton(commandRect, "Jump: Peipei Memory", !isJumping, () => StartCoroutine(JumpToMemory())); } private static float GetMenuHeight() { return DevCommandCount * CommandButtonHeight + 12f; } private void DrawCommandButton(Rect rect, string label, bool enabled, System.Action action) { GUI.enabled = enabled; if (GUI.Button(rect, label, buttonStyle)) { menuOpen = false; action?.Invoke(); } GUI.enabled = true; } private IEnumerator JumpToMemory() { if (isJumping) yield break; isJumping = true; SetStatus("Preparing Peipei memory jump..."); BeginGameLoopForJump(); StopCurrentDialog(); if (!IsPeipeiFixSceneLoaded()) { if (SceneLoader.Instance == null) { SetStatus("Jump failed: SceneLoader is not ready.", 5f); isJumping = false; yield break; } SetStatus("Loading Peipei fix scene..."); yield return SceneLoader.Instance.LoadSceneAsync(TargetSceneKey); } yield return null; SetStatus("Waiting for fix systems..."); bool ready = false; float deadline = Time.unscaledTime + WaitTimeout; while (Time.unscaledTime < deadline) { if (FixSystemCenter.Instance != null && FixSystemCenter.Instance.IsDirectorReady && FixSystemCenter.SystemDic.Get() != null && FixPanelSystem.GetRepairPanel() != null) { ready = true; break; } yield return null; } if (!ready) { SetStatus("Jump failed: Peipei memory systems were not ready.", 5f); isJumping = false; yield break; } SeedTestPunchTapes(); SetStatus("Entering memory module..."); yield return FixSystemCenter.Instance.TransitionToImmediate(FixSceneMode.Memory); PunchTapeManager.Instance.OpenFavoritesPanel(); SetStatus("Peipei memory module is ready.", 3f); isJumping = false; } private static bool IsPeipeiFixSceneLoaded() { if (SceneLoader.Instance != null && SceneLoader.Instance.CurrentSceneName == TargetSceneKey) return true; return SceneManager.GetSceneByName(TargetSceneName).isLoaded; } private static void BeginGameLoopForJump() { if (GameManager.Instance != null && GameManager.Instance.state.isInGame) return; EnumEventSystem.Global.Send(GameLoopEnum.GameStart); } private static void StopCurrentDialog() { if (DialogController.Instance != null && DialogController.Instance.DialogueRunner != null) DialogController.Instance.StopDialog(); else if (DialogUIManager.Instance != null) DialogUIManager.Instance.HideDialog(); } private static void SeedTestPunchTapes() { if (PunchTapeManager.Instance == null) return; var snapshot = new PunchTapeSnapshotDto { favorites = new List(TestPunchTapes.Length) }; foreach (var tape in TestPunchTapes) snapshot.favorites.Add(new PunchTape(tape.Category, tape.ClueName, tape.MemoryIndex)); PunchTapeManager.Instance.ApplyPunchTapeSnapshot(snapshot); } private void SetStatus(string message, float visibleSeconds = 30f) { status = message; statusVisibleUntil = Time.unscaledTime + visibleSeconds; Debug.Log($"[PeipeiMemoryJumpTool] {message}"); } private void EnsureStyles() { if (buttonStyle != null && statusStyle != null) return; buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 15, alignment = TextAnchor.MiddleCenter }; menuBoxStyle = new GUIStyle(GUI.skin.box) { padding = new RectOffset(6, 6, 6, 6) }; statusStyle = new GUIStyle(GUI.skin.box) { fontSize = 13, alignment = TextAnchor.MiddleLeft, padding = new RectOffset(8, 8, 4, 4) }; } } } #endif