Kursach_StealthAction/Assets/Scripts/PauseMenu.cs
2026-10-23 15:44:09 +03:00

624 lines
21 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.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.InputSystem;
public class PauseMenu : MonoBehaviour
{
[Header("Панели")]
public GameObject pauseMenuPanel;
public GameObject settingsPanel;
[Header("Кнопки панели действий")]
public Button resumeButton;
public Button settingsButton;
public Button restartButton;
public Button mainMenuButton;
public Button quitButton;
public Button backFromSettingsButton;
public Button resetDefaultsButton;
[Header("Вкладки")]
public Button[] tabButtons;
public GameObject[] tabPanels;
[Header("Настройки: Звук")]
public Slider volumeSlider;
public Text volumeValueText;
public Toggle muteToggle;
[Header("Настройки: Графика")]
public Dropdown qualityDropdown;
public Toggle fullscreenToggle;
public Dropdown resolutionDropdown;
public Toggle vsyncToggle;
[Header("Настройки: Управление")]
public Slider sensitivitySlider;
public Text sensitivityValueText;
public Toggle invertYToggle;
private bool isPaused = false;
private bool isInitializing = false;
private List<Resolution> filteredResolutions = new List<Resolution>();
public bool IsPaused => isPaused;
private void Awake()
{
Time.timeScale = 1f;
AutoWireUI();
}
private void Start()
{
AutoWireUI();
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
if (settingsPanel != null && settingsPanel != pauseMenuPanel) settingsPanel.SetActive(false);
SetupActionButtons();
SetupTabs();
InitializeSettingsUI();
}
private void Update()
{
// Не открываем меню паузы, если активен экран смерти, просмотр записки, клавиатура лифта или экран победы
if (DeathScreenUI.Instance != null && DeathScreenUI.Instance.IsShown) return;
if (NoteViewerUI.Instance != null && NoteViewerUI.Instance.IsOpen) return;
if (ElevatorKeypadUI.Instance != null && ElevatorKeypadUI.Instance.IsOpen) return;
if (LevelSuccessUI.Instance != null && LevelSuccessUI.Instance.IsOpen) return;
if (FinalVictoryUI.Instance != null && FinalVictoryUI.Instance.IsOpen) return;
bool togglePause = false;
var keyboard = Keyboard.current;
if (keyboard != null)
{
if (keyboard.escapeKey.wasPressedThisFrame ||
keyboard.pKey.wasPressedThisFrame ||
keyboard.pauseKey.wasPressedThisFrame)
{
togglePause = true;
}
}
#if ENABLE_LEGACY_INPUT_MANAGER
if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.P))
{
togglePause = true;
}
#endif
var gamepad = Gamepad.current;
if (gamepad != null && gamepad.startButton.wasPressedThisFrame)
{
togglePause = true;
}
if (togglePause)
{
if (isPaused)
{
if (settingsPanel != null && settingsPanel.activeSelf && settingsPanel != pauseMenuPanel)
{
CloseSettings();
}
else
{
ResumeGame();
}
}
else
{
PauseGame();
}
}
}
public void PauseGame()
{
isPaused = true;
Time.timeScale = 0f;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
if (pauseMenuPanel != null)
{
pauseMenuPanel.SetActive(true);
SwitchTab(0);
}
if (settingsPanel != null && settingsPanel != pauseMenuPanel)
{
settingsPanel.SetActive(false);
}
Debug.Log("[PauseMenu] Game PAUSED (Esc/P/Tab pressed). Time.timeScale=0.");
}
public void ResumeGame()
{
isPaused = false;
Time.timeScale = 1f;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
if (settingsPanel != null) settingsPanel.SetActive(false);
Debug.Log("[PauseMenu] Game RESUMED. Time.timeScale=1.");
}
public void RestartGame()
{
Time.timeScale = 1f;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
public void OpenSettings()
{
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
if (settingsPanel != null)
{
settingsPanel.SetActive(true);
InitializeSettingsUI();
SwitchTab(0);
}
}
public void CloseSettings()
{
PlayerPrefs.Save();
if (settingsPanel != null) settingsPanel.SetActive(false);
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(true);
}
public void ResetToDefaults()
{
isInitializing = true;
if (volumeSlider != null) volumeSlider.value = 1.0f;
if (muteToggle != null) muteToggle.isOn = false;
PlayerPrefs.SetFloat(GameSettings.KeyMasterVolume, 1.0f);
PlayerPrefs.SetInt(GameSettings.KeyIsMuted, 0);
AudioListener.volume = 1.0f;
UpdateVolumeLabel(1.0f, false);
int defQuality = Mathf.Clamp(QualitySettings.names.Length - 1, 0, QualitySettings.names.Length - 1);
if (qualityDropdown != null)
{
qualityDropdown.value = defQuality;
qualityDropdown.RefreshShownValue();
}
QualitySettings.SetQualityLevel(defQuality, true);
PlayerPrefs.SetInt(GameSettings.KeyQualityLevel, defQuality);
if (fullscreenToggle != null) fullscreenToggle.isOn = true;
Screen.fullScreen = true;
PlayerPrefs.SetInt(GameSettings.KeyFullscreen, 1);
if (resolutionDropdown != null && filteredResolutions.Count > 0)
{
int lastIndex = filteredResolutions.Count - 1;
resolutionDropdown.value = lastIndex;
resolutionDropdown.RefreshShownValue();
var res = filteredResolutions[lastIndex];
Screen.SetResolution(res.width, res.height, FullScreenMode.FullScreenWindow);
PlayerPrefs.SetInt(GameSettings.KeyResolutionWidth, res.width);
PlayerPrefs.SetInt(GameSettings.KeyResolutionHeight, res.height);
}
if (sensitivitySlider != null) sensitivitySlider.value = 1.0f;
PlayerPrefs.SetFloat(GameSettings.KeyMouseSensitivity, 1.0f);
UpdateSensitivityLabel(1.0f);
PlayerPrefs.Save();
isInitializing = false;
Debug.Log("[PauseMenu] Настройки сброшены на значения по умолчанию.");
}
public void ReturnToMainMenu()
{
Time.timeScale = 1f;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
SceneManager.LoadScene("MainMenu");
}
public void QuitGame()
{
PlayerPrefs.Save();
Application.Quit();
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#endif
}
public void SwitchTab(int tabIndex)
{
if (tabPanels != null)
{
for (int i = 0; i < tabPanels.Length; i++)
{
if (tabPanels[i] != null)
{
tabPanels[i].SetActive(i == tabIndex);
}
}
}
if (tabButtons != null)
{
for (int i = 0; i < tabButtons.Length; i++)
{
if (tabButtons[i] != null)
{
bool isActive = (i == tabIndex);
var img = tabButtons[i].GetComponent<Image>();
if (img != null)
{
img.color = isActive
? new Color(0.95f, 0.78f, 0.12f, 1.0f) // Золотистый активный
: new Color(0.08f, 0.08f, 0.08f, 0.85f);
}
var text = tabButtons[i].GetComponentInChildren<Text>();
if (text != null)
{
text.color = isActive
? new Color(0.06f, 0.06f, 0.06f, 1.0f)
: new Color(0.6f, 0.6f, 0.6f, 0.8f);
}
}
}
}
}
private void SetupTabs()
{
if (tabButtons != null)
{
for (int i = 0; i < tabButtons.Length; i++)
{
int index = i;
if (tabButtons[i] != null)
{
tabButtons[i].onClick.RemoveAllListeners();
tabButtons[i].onClick.AddListener(() => SwitchTab(index));
}
}
}
}
private void SetupActionButtons()
{
if (resumeButton != null)
{
resumeButton.onClick.RemoveAllListeners();
resumeButton.onClick.AddListener(ResumeGame);
}
if (settingsButton != null)
{
settingsButton.onClick.RemoveAllListeners();
settingsButton.onClick.AddListener(OpenSettings);
}
if (restartButton != null)
{
restartButton.onClick.RemoveAllListeners();
restartButton.onClick.AddListener(RestartGame);
}
if (mainMenuButton != null)
{
mainMenuButton.onClick.RemoveAllListeners();
mainMenuButton.onClick.AddListener(ReturnToMainMenu);
}
if (quitButton != null)
{
quitButton.onClick.RemoveAllListeners();
quitButton.onClick.AddListener(QuitGame);
}
if (backFromSettingsButton != null)
{
backFromSettingsButton.onClick.RemoveAllListeners();
backFromSettingsButton.onClick.AddListener(CloseSettings);
}
if (resetDefaultsButton != null)
{
resetDefaultsButton.onClick.RemoveAllListeners();
resetDefaultsButton.onClick.AddListener(ResetToDefaults);
}
}
public void AutoWireUI()
{
if (pauseMenuPanel == null)
{
var pPanel = transform.Find("PauseMenuPanel");
if (pPanel != null) pauseMenuPanel = pPanel.gameObject;
else
{
var root = transform.Find("PauseRootPanel");
if (root != null) pauseMenuPanel = root.gameObject;
}
}
if (settingsPanel == null)
{
var sPanel = transform.Find("SettingsPanel");
if (sPanel != null) settingsPanel = sPanel.gameObject;
}
// Кнопки в карточке паузы
Transform pauseCard = transform.Find("PauseMenuPanel/Pause_Card") ?? transform.Find("PauseMenuPanel");
if (pauseCard != null)
{
Transform btnBox = pauseCard.Find("Buttons_Container") ?? pauseCard;
if (resumeButton == null) resumeButton = btnBox.Find("Btn_Resume")?.GetComponent<Button>();
if (settingsButton == null) settingsButton = btnBox.Find("Btn_Settings")?.GetComponent<Button>();
if (restartButton == null) restartButton = btnBox.Find("Btn_Restart")?.GetComponent<Button>();
if (mainMenuButton == null) mainMenuButton = btnBox.Find("Btn_MainMenu")?.GetComponent<Button>();
if (quitButton == null) quitButton = btnBox.Find("Btn_Quit")?.GetComponent<Button>();
}
// Кнопки и контролы в SettingsPanel
Transform sCard = transform.Find("SettingsPanel/Settings_Card");
if (sCard != null)
{
Transform bottomBtns = sCard.Find("Settings_BottomButtons");
if (bottomBtns != null)
{
if (resetDefaultsButton == null) resetDefaultsButton = bottomBtns.Find("Button_ResetDefaults")?.GetComponent<Button>();
if (backFromSettingsButton == null) backFromSettingsButton = bottomBtns.Find("Button_Back")?.GetComponent<Button>();
}
Transform sList = sCard.Find("Settings_List");
if (sList != null)
{
if (volumeSlider == null) volumeSlider = sList.Find("Row_Volume/Slider")?.GetComponent<Slider>();
if (volumeValueText == null) volumeValueText = sList.Find("Row_Volume/ValueText")?.GetComponent<Text>();
if (muteToggle == null) muteToggle = sList.Find("Row_Mute/Toggle")?.GetComponent<Toggle>();
if (qualityDropdown == null) qualityDropdown = sList.Find("Row_Quality/Dropdown")?.GetComponent<Dropdown>();
if (fullscreenToggle == null) fullscreenToggle = sList.Find("Row_Fullscreen/Toggle")?.GetComponent<Toggle>();
if (resolutionDropdown == null) resolutionDropdown = sList.Find("Row_Resolution/Dropdown")?.GetComponent<Dropdown>();
if (sensitivitySlider == null) sensitivitySlider = sList.Find("Row_Sensitivity/Slider")?.GetComponent<Slider>();
if (sensitivityValueText == null) sensitivityValueText = sList.Find("Row_Sensitivity/ValueText")?.GetComponent<Text>();
}
}
}
private void InitializeSettingsUI()
{
isInitializing = true;
// Звук
float savedVolume = PlayerPrefs.GetFloat(GameSettings.KeyMasterVolume, 1.0f);
bool savedMute = PlayerPrefs.GetInt(GameSettings.KeyIsMuted, 0) == 1;
if (volumeSlider != null)
{
volumeSlider.minValue = 0f;
volumeSlider.maxValue = 1f;
volumeSlider.value = savedVolume;
volumeSlider.onValueChanged.RemoveAllListeners();
volumeSlider.onValueChanged.AddListener(OnVolumeChanged);
}
if (muteToggle != null)
{
muteToggle.isOn = savedMute;
muteToggle.onValueChanged.RemoveAllListeners();
muteToggle.onValueChanged.AddListener(OnMuteChanged);
}
UpdateVolumeLabel(savedVolume, savedMute);
// Качество графики
if (qualityDropdown != null)
{
qualityDropdown.ClearOptions();
List<string> options = new List<string>();
foreach (var q in QualitySettings.names)
{
options.Add(TranslateQuality(q));
}
qualityDropdown.AddOptions(options);
qualityDropdown.value = PlayerPrefs.GetInt(GameSettings.KeyQualityLevel, QualitySettings.GetQualityLevel());
qualityDropdown.RefreshShownValue();
qualityDropdown.onValueChanged.RemoveAllListeners();
qualityDropdown.onValueChanged.AddListener(OnQualityChanged);
}
// Полноэкранный режим
if (fullscreenToggle != null)
{
fullscreenToggle.isOn = PlayerPrefs.GetInt(GameSettings.KeyFullscreen, Screen.fullScreen ? 1 : 0) == 1;
fullscreenToggle.onValueChanged.RemoveAllListeners();
fullscreenToggle.onValueChanged.AddListener(OnFullscreenChanged);
}
// Разрешения экрана
PopulateResolutions();
// Вертикальная синхронизация
if (vsyncToggle != null)
{
vsyncToggle.isOn = QualitySettings.vSyncCount > 0;
vsyncToggle.onValueChanged.RemoveAllListeners();
vsyncToggle.onValueChanged.AddListener(OnVsyncChanged);
}
// Чувствительность
float savedSens = PlayerPrefs.GetFloat(GameSettings.KeyMouseSensitivity, 1.0f);
if (sensitivitySlider != null)
{
sensitivitySlider.minValue = 0.2f;
sensitivitySlider.maxValue = 3.0f;
sensitivitySlider.value = savedSens;
sensitivitySlider.onValueChanged.RemoveAllListeners();
sensitivitySlider.onValueChanged.AddListener(OnSensitivityChanged);
}
UpdateSensitivityLabel(savedSens);
// Инверсия по Y
if (invertYToggle != null)
{
invertYToggle.isOn = PlayerPrefs.GetInt("Settings_InvertY", 0) == 1;
invertYToggle.onValueChanged.RemoveAllListeners();
invertYToggle.onValueChanged.AddListener(OnInvertYChanged);
}
isInitializing = false;
}
private void PopulateResolutions()
{
if (resolutionDropdown == null) return;
resolutionDropdown.ClearOptions();
var allRes = Screen.resolutions;
filteredResolutions.Clear();
var options = new List<string>();
var seen = new HashSet<string>();
for (int i = allRes.Length - 1; i >= 0; i--)
{
var res = allRes[i];
string key = $"{res.width}x{res.height}";
if (!seen.Contains(key))
{
seen.Add(key);
filteredResolutions.Insert(0, res);
}
}
if (filteredResolutions.Count == 0)
{
filteredResolutions.Add(new Resolution { width = 1920, height = 1080 });
filteredResolutions.Add(new Resolution { width = 1280, height = 720 });
}
int currentIdx = 0;
int curW = Screen.width;
int curH = Screen.height;
for (int i = 0; i < filteredResolutions.Count; i++)
{
var r = filteredResolutions[i];
options.Add($"{r.width} x {r.height}");
if (r.width == curW && r.height == curH)
{
currentIdx = i;
}
}
resolutionDropdown.AddOptions(options);
resolutionDropdown.value = currentIdx;
resolutionDropdown.RefreshShownValue();
resolutionDropdown.onValueChanged.RemoveAllListeners();
resolutionDropdown.onValueChanged.AddListener(OnResolutionChanged);
}
private void OnResolutionChanged(int index)
{
if (isInitializing || index < 0 || index >= filteredResolutions.Count) return;
var r = filteredResolutions[index];
bool isFull = fullscreenToggle != null ? fullscreenToggle.isOn : Screen.fullScreen;
Screen.SetResolution(r.width, r.height, isFull);
PlayerPrefs.SetInt(GameSettings.KeyResolutionWidth, r.width);
PlayerPrefs.SetInt(GameSettings.KeyResolutionHeight, r.height);
}
private void OnVsyncChanged(bool enabled)
{
if (isInitializing) return;
QualitySettings.vSyncCount = enabled ? 1 : 0;
}
private void OnInvertYChanged(bool enabled)
{
if (isInitializing) return;
PlayerPrefs.SetInt("Settings_InvertY", enabled ? 1 : 0);
}
private void OnVolumeChanged(float val)
{
if (isInitializing) return;
PlayerPrefs.SetFloat(GameSettings.KeyMasterVolume, val);
bool isMuted = muteToggle != null && muteToggle.isOn;
if (!isMuted) AudioListener.volume = val;
UpdateVolumeLabel(val, isMuted);
}
private void OnMuteChanged(bool isMuted)
{
if (isInitializing) return;
PlayerPrefs.SetInt(GameSettings.KeyIsMuted, isMuted ? 1 : 0);
float currentVol = volumeSlider != null ? volumeSlider.value : 1.0f;
AudioListener.volume = isMuted ? 0f : currentVol;
UpdateVolumeLabel(currentVol, isMuted);
}
private void UpdateVolumeLabel(float vol, bool muted)
{
if (volumeValueText != null)
{
volumeValueText.text = muted ? "ВЫКЛ" : $"{Mathf.RoundToInt(vol * 100)}%";
}
}
private void OnQualityChanged(int index)
{
if (isInitializing) return;
QualitySettings.SetQualityLevel(index, true);
PlayerPrefs.SetInt(GameSettings.KeyQualityLevel, index);
}
private void OnFullscreenChanged(bool isFullscreen)
{
if (isInitializing) return;
Screen.fullScreen = isFullscreen;
PlayerPrefs.SetInt(GameSettings.KeyFullscreen, isFullscreen ? 1 : 0);
}
private void OnSensitivityChanged(float val)
{
if (isInitializing) return;
PlayerPrefs.SetFloat(GameSettings.KeyMouseSensitivity, val);
UpdateSensitivityLabel(val);
}
private void UpdateSensitivityLabel(float val)
{
if (sensitivityValueText != null)
{
sensitivityValueText.text = $"{val:F1}x";
}
}
private string TranslateQuality(string q)
{
switch (q.ToLower())
{
case "very low": return "Очень низкое";
case "low": return "Низкое";
case "medium": return "Среднее";
case "high": return "Высокое";
case "very high": return "Очень высокое";
case "ultra": return "Ультра";
default: return q;
}
}
}