Kursach_StealthAction/Assets/Scripts/Editor/PauseMenuBuilder.cs
2026-10-19 20:14:24 +03:00

463 lines
20 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.EventSystems;
using UnityEngine.InputSystem.UI;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
public static class PauseMenuBuilder
{
private static DefaultControls.Resources uiResources;
private static Font standardFont;
[MenuItem("Tools/Add Pause Menu to SampleScene")]
public static string Build()
{
standardFont = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
uiResources = new DefaultControls.Resources
{
standard = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UISprite.psd"),
background = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Background.psd"),
knob = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Knob.psd"),
checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Checkmark.psd"),
dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/DropdownArrow.psd"),
mask = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UIMask.psd")
};
// Открываем сцену геймплея
Scene gameplayScene = EditorSceneManager.OpenScene("Assets/Scenes/SampleScene.unity", OpenSceneMode.Single);
// Проверяем, есть ли уже EventSystem
if (Object.FindAnyObjectByType<EventSystem>() == null)
{
GameObject esGo = new GameObject("EventSystem");
esGo.AddComponent<EventSystem>();
esGo.AddComponent<InputSystemUIInputModule>();
}
// Удаляем старый PauseMenu, если был
var old = GameObject.Find("PauseCanvas");
if (old != null) Object.DestroyImmediate(old);
// Создаем Canvas паузы
GameObject canvasGo = new GameObject("PauseCanvas");
Canvas canvas = canvasGo.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = 100; // Поверх всего
CanvasScaler scaler = canvasGo.AddComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(1920, 1080);
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
scaler.matchWidthOrHeight = 0.5f;
canvasGo.AddComponent<GraphicRaycaster>();
PauseMenu pauseMenu = canvasGo.AddComponent<PauseMenu>();
// 1. Панель паузы (PauseMenuPanel)
GameObject pausePanel = CreateImage("PauseMenuPanel", canvasGo.transform,
new Color(0.02f, 0.035f, 0.055f, 0.88f),
Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero);
GameObject card = CreateImage("Pause_Card", pausePanel.transform,
new Color(0.06f, 0.09f, 0.14f, 0.98f),
new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f),
new Vector2(460f, 520f), Vector2.zero);
Outline outline = card.AddComponent<Outline>();
outline.effectColor = new Color(0.00f, 0.85f, 0.95f, 0.45f);
outline.effectDistance = new Vector2(2f, -2f);
CreateText("Pause_Title", card.transform,
"ПАУЗА",
34, FontStyle.Bold, TextAnchor.MiddleCenter,
new Color(0.92f, 0.97f, 1f, 1f),
new Vector2(0.05f, 0.84f), new Vector2(0.95f, 0.96f), Vector2.zero, Vector2.zero);
CreateImage("Pause_Divider", card.transform,
new Color(0.00f, 0.85f, 0.95f, 0.40f),
new Vector2(0.10f, 0.82f), new Vector2(0.90f, 0.825f), Vector2.zero, Vector2.zero);
GameObject btnContainer = CreateEmptyRect("Buttons_Container", card.transform,
new Vector2(0.08f, 0.06f), new Vector2(0.92f, 0.78f), Vector2.zero, Vector2.zero);
VerticalLayoutGroup vLayout = btnContainer.AddComponent<VerticalLayoutGroup>();
vLayout.spacing = 16f;
vLayout.childAlignment = TextAnchor.MiddleCenter;
vLayout.childControlWidth = true;
vLayout.childControlHeight = false;
vLayout.childForceExpandWidth = true;
vLayout.childForceExpandHeight = false;
Button resumeBtn = CreateStyledButton("Btn_Resume", btnContainer.transform,
"► ПРОДОЛЖИТЬ",
new Color(0.08f, 0.22f, 0.32f, 0.95f),
new Color(0.00f, 0.65f, 0.85f, 1.0f),
new Color(0.04f, 0.14f, 0.22f, 1.0f),
new Color(0.90f, 0.98f, 1.0f, 1.0f),
60f, 22);
Button settingsBtn = CreateStyledButton("Btn_Settings", btnContainer.transform,
"⚙ НАСТРОЙКИ",
new Color(0.07f, 0.12f, 0.18f, 0.90f),
new Color(0.18f, 0.38f, 0.52f, 1.0f),
new Color(0.04f, 0.08f, 0.12f, 1.0f),
new Color(0.85f, 0.92f, 0.98f, 1.0f),
56f, 20);
Button menuBtn = CreateStyledButton("Btn_MainMenu", btnContainer.transform,
"⌂ ГЛАВНОЕ МЕНЮ",
new Color(0.07f, 0.12f, 0.18f, 0.90f),
new Color(0.18f, 0.38f, 0.52f, 1.0f),
new Color(0.04f, 0.08f, 0.12f, 1.0f),
new Color(0.85f, 0.92f, 0.98f, 1.0f),
56f, 20);
Button quitBtn = CreateStyledButton("Btn_Quit", btnContainer.transform,
"✖ ВЫХОД ИЗ ИГРЫ",
new Color(0.18f, 0.08f, 0.10f, 0.90f),
new Color(0.55f, 0.16f, 0.22f, 1.0f),
new Color(0.10f, 0.04f, 0.06f, 1.0f),
new Color(0.95f, 0.85f, 0.85f, 1.0f),
56f, 20);
// 2. Панель настроек (SettingsPanel)
GameObject settingsPanel = CreateEmptyRect("SettingsPanel", canvasGo.transform,
Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero);
CreateImage("Backdrop_Dim", settingsPanel.transform,
new Color(0.01f, 0.02f, 0.03f, 0.80f),
Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero);
GameObject settingsCard = CreateImage("Settings_Card", settingsPanel.transform,
new Color(0.05f, 0.08f, 0.12f, 0.98f),
new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f),
new Vector2(880f, 680f), Vector2.zero);
Outline setOutline = settingsCard.AddComponent<Outline>();
setOutline.effectColor = new Color(0.00f, 0.85f, 0.95f, 0.50f);
setOutline.effectDistance = new Vector2(2f, -2f);
CreateText("Settings_Header", settingsCard.transform,
"НАСТРОЙКИ",
28, FontStyle.Bold, TextAnchor.MiddleCenter,
new Color(0.90f, 0.97f, 1.0f, 1.0f),
new Vector2(0.05f, 0.90f), new Vector2(0.95f, 0.98f), Vector2.zero, Vector2.zero);
CreateImage("Settings_Divider", settingsCard.transform,
new Color(0.00f, 0.85f, 0.95f, 0.35f),
new Vector2(0.05f, 0.89f), new Vector2(0.95f, 0.895f), Vector2.zero, Vector2.zero);
GameObject settingsList = CreateEmptyRect("Settings_List", settingsCard.transform,
new Vector2(0.06f, 0.14f), new Vector2(0.94f, 0.87f), Vector2.zero, Vector2.zero);
VerticalLayoutGroup sLayout = settingsList.AddComponent<VerticalLayoutGroup>();
sLayout.spacing = 16f;
sLayout.childAlignment = TextAnchor.UpperCenter;
sLayout.childControlWidth = true;
sLayout.childControlHeight = false;
sLayout.childForceExpandWidth = true;
sLayout.childForceExpandHeight = false;
// Разделы
CreateCategoryHeader("HEADER_AUDIO", settingsList.transform, "— АУДИО —");
var volumeRow = CreateSliderRow("Row_Volume", settingsList.transform, "Общая громкость", 0f, 1f, 1f, "%");
Toggle muteToggle = CreateToggleRow("Row_Mute", settingsList.transform, "Отключить звук");
CreateCategoryHeader("HEADER_GRAPHICS", settingsList.transform, "— ГРАФИКА —");
Dropdown qualityDropdown = CreateDropdownRow("Row_Quality", settingsList.transform, "Качество графики");
Toggle fullscreenToggle = CreateToggleRow("Row_Fullscreen", settingsList.transform, "Полноэкранный режим");
CreateCategoryHeader("HEADER_CONTROLS", settingsList.transform, "— УПРАВЛЕНИЕ —");
var sensRow = CreateSliderRow("Row_Sensitivity", settingsList.transform, "Чувствительность мыши", 0.2f, 3.0f, 1.0f, "x");
GameObject botRow = CreateEmptyRect("Settings_BottomButtons", settingsCard.transform,
new Vector2(0.06f, 0.03f), new Vector2(0.94f, 0.12f), Vector2.zero, Vector2.zero);
HorizontalLayoutGroup bLayout = botRow.AddComponent<HorizontalLayoutGroup>();
bLayout.spacing = 30f;
bLayout.childAlignment = TextAnchor.MiddleCenter;
bLayout.childControlWidth = true;
bLayout.childControlHeight = true;
Button backBtn = CreateStyledButton("Button_Back", botRow.transform,
"✔ НАЗАД В ПАУЗУ",
new Color(0.08f, 0.22f, 0.30f, 0.95f),
new Color(0.00f, 0.65f, 0.85f, 1.0f),
new Color(0.05f, 0.14f, 0.20f, 1.0f),
new Color(0.90f, 0.98f, 1.0f, 1.0f),
48f, 18);
// Привязываем ссылки
pauseMenu.pauseMenuPanel = pausePanel;
pauseMenu.settingsPanel = settingsPanel;
pauseMenu.volumeSlider = volumeRow.slider;
pauseMenu.volumeValueText = volumeRow.valueText;
pauseMenu.muteToggle = muteToggle;
pauseMenu.qualityDropdown = qualityDropdown;
pauseMenu.fullscreenToggle = fullscreenToggle;
pauseMenu.sensitivitySlider = sensRow.slider;
pauseMenu.sensitivityValueText = sensRow.valueText;
UnityEditor.Events.UnityEventTools.AddPersistentListener(resumeBtn.onClick, pauseMenu.ResumeGame);
UnityEditor.Events.UnityEventTools.AddPersistentListener(settingsBtn.onClick, pauseMenu.OpenSettings);
UnityEditor.Events.UnityEventTools.AddPersistentListener(menuBtn.onClick, pauseMenu.ReturnToMainMenu);
UnityEditor.Events.UnityEventTools.AddPersistentListener(quitBtn.onClick, pauseMenu.QuitGame);
UnityEditor.Events.UnityEventTools.AddPersistentListener(backBtn.onClick, pauseMenu.CloseSettings);
pausePanel.SetActive(false);
settingsPanel.SetActive(false);
// Сохраняем сцену геймплея
EditorSceneManager.SaveScene(gameplayScene);
Debug.Log("[PauseMenuBuilder] PauseMenu успешно добавлен в SampleScene.unity");
// Открываем обратно сцену MainMenu
EditorSceneManager.OpenScene("Assets/Scenes/MainMenu.unity", OpenSceneMode.Single);
return "SUCCESS: PauseMenu added to SampleScene and MainMenu restored!";
}
#region Хелперы UI
private static GameObject CreateEmptyRect(string name, Transform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 sizeDelta, Vector2 anchoredPosition)
{
GameObject go = new GameObject(name, typeof(RectTransform));
go.transform.SetParent(parent, false);
RectTransform rt = go.GetComponent<RectTransform>();
rt.anchorMin = anchorMin;
rt.anchorMax = anchorMax;
rt.sizeDelta = sizeDelta;
rt.anchoredPosition = anchoredPosition;
return go;
}
private static GameObject CreateImage(string name, Transform parent, Color color, Vector2 anchorMin, Vector2 anchorMax, Vector2 sizeDelta, Vector2 anchoredPosition)
{
GameObject go = CreateEmptyRect(name, parent, anchorMin, anchorMax, sizeDelta, anchoredPosition);
Image img = go.AddComponent<Image>();
img.color = color;
img.sprite = uiResources.background;
img.type = Image.Type.Sliced;
return go;
}
private static GameObject CreateText(string name, Transform parent, string text, int fontSize, FontStyle style, TextAnchor alignment, Color color, Vector2 anchorMin, Vector2 anchorMax, Vector2 sizeDelta, Vector2 anchoredPosition)
{
GameObject go = CreateEmptyRect(name, parent, anchorMin, anchorMax, sizeDelta, anchoredPosition);
Text t = go.AddComponent<Text>();
t.font = standardFont;
t.text = text;
t.fontSize = fontSize;
t.fontStyle = style;
t.alignment = alignment;
t.color = color;
t.horizontalOverflow = HorizontalWrapMode.Wrap;
t.verticalOverflow = VerticalWrapMode.Overflow;
return go;
}
private static Button CreateStyledButton(string name, Transform parent, string label, Color normalColor, Color highlightedColor, Color pressedColor, Color textColor, float height, int fontSize)
{
GameObject btnObj = DefaultControls.CreateButton(uiResources);
btnObj.name = name;
btnObj.transform.SetParent(parent, false);
LayoutElement layout = btnObj.AddComponent<LayoutElement>();
layout.minHeight = height;
layout.preferredHeight = height;
Image img = btnObj.GetComponent<Image>();
img.color = normalColor;
img.type = Image.Type.Sliced;
Button btn = btnObj.GetComponent<Button>();
ColorBlock colors = btn.colors;
colors.normalColor = normalColor;
colors.highlightedColor = highlightedColor;
colors.pressedColor = pressedColor;
colors.selectedColor = highlightedColor;
colors.colorMultiplier = 1f;
colors.fadeDuration = 0.12f;
btn.colors = colors;
Text text = btnObj.GetComponentInChildren<Text>();
if (text != null)
{
text.font = standardFont;
text.text = label;
text.fontSize = fontSize;
text.fontStyle = FontStyle.Bold;
text.color = textColor;
text.alignment = TextAnchor.MiddleCenter;
}
return btn;
}
private static void CreateCategoryHeader(string name, Transform parent, string text)
{
GameObject go = CreateEmptyRect(name, parent, Vector2.zero, Vector2.one, new Vector2(0f, 30f), Vector2.zero);
LayoutElement layout = go.AddComponent<LayoutElement>();
layout.minHeight = 30f;
layout.preferredHeight = 30f;
Text t = go.AddComponent<Text>();
t.font = standardFont;
t.text = text;
t.fontSize = 16;
t.fontStyle = FontStyle.Bold;
t.alignment = TextAnchor.MiddleLeft;
t.color = new Color(0.00f, 0.85f, 0.95f, 0.95f);
}
private struct SliderRow
{
public Slider slider;
public Text valueText;
}
private static SliderRow CreateSliderRow(string name, Transform parent, string label, float min, float max, float def, string unit)
{
GameObject row = CreateEmptyRect(name, parent, Vector2.zero, Vector2.one, new Vector2(0f, 40f), Vector2.zero);
LayoutElement layout = row.AddComponent<LayoutElement>();
layout.minHeight = 40f;
layout.preferredHeight = 40f;
HorizontalLayoutGroup hLayout = row.AddComponent<HorizontalLayoutGroup>();
hLayout.spacing = 18f;
hLayout.childAlignment = TextAnchor.MiddleLeft;
hLayout.childControlWidth = false;
hLayout.childControlHeight = true;
hLayout.childForceExpandWidth = false;
hLayout.childForceExpandHeight = true;
GameObject lblGo = CreateEmptyRect("Label", row.transform, Vector2.zero, Vector2.one, new Vector2(260f, 40f), Vector2.zero);
LayoutElement lblLayout = lblGo.AddComponent<LayoutElement>();
lblLayout.minWidth = 260f;
lblLayout.preferredWidth = 260f;
Text lbl = lblGo.AddComponent<Text>();
lbl.font = standardFont;
lbl.text = label;
lbl.fontSize = 17;
lbl.alignment = TextAnchor.MiddleLeft;
lbl.color = new Color(0.85f, 0.92f, 0.98f, 1f);
GameObject sliderObj = DefaultControls.CreateSlider(uiResources);
sliderObj.name = "Slider";
sliderObj.transform.SetParent(row.transform, false);
LayoutElement sliderLayout = sliderObj.AddComponent<LayoutElement>();
sliderLayout.minWidth = 360f;
sliderLayout.preferredWidth = 360f;
Slider slider = sliderObj.GetComponent<Slider>();
slider.minValue = min;
slider.maxValue = max;
slider.value = def;
GameObject valGo = CreateEmptyRect("ValueText", row.transform, Vector2.zero, Vector2.one, new Vector2(80f, 40f), Vector2.zero);
LayoutElement valLayout = valGo.AddComponent<LayoutElement>();
valLayout.minWidth = 80f;
valLayout.preferredWidth = 80f;
Text valText = valGo.AddComponent<Text>();
valText.font = standardFont;
valText.text = unit == "%" ? $"{Mathf.RoundToInt(def * 100)}%" : $"{def:F1}{unit}";
valText.fontSize = 17;
valText.fontStyle = FontStyle.Bold;
valText.alignment = TextAnchor.MiddleCenter;
valText.color = new Color(0.00f, 0.85f, 0.95f, 1f);
return new SliderRow { slider = slider, valueText = valText };
}
private static Toggle CreateToggleRow(string name, Transform parent, string label)
{
GameObject row = CreateEmptyRect(name, parent, Vector2.zero, Vector2.one, new Vector2(0f, 38f), Vector2.zero);
LayoutElement layout = row.AddComponent<LayoutElement>();
layout.minHeight = 38f;
layout.preferredHeight = 38f;
HorizontalLayoutGroup hLayout = row.AddComponent<HorizontalLayoutGroup>();
hLayout.spacing = 18f;
hLayout.childAlignment = TextAnchor.MiddleLeft;
hLayout.childControlWidth = false;
hLayout.childControlHeight = true;
hLayout.childForceExpandWidth = false;
hLayout.childForceExpandHeight = true;
GameObject lblGo = CreateEmptyRect("Label", row.transform, Vector2.zero, Vector2.one, new Vector2(260f, 38f), Vector2.zero);
LayoutElement lblLayout = lblGo.AddComponent<LayoutElement>();
lblLayout.minWidth = 260f;
lblLayout.preferredWidth = 260f;
Text lbl = lblGo.AddComponent<Text>();
lbl.font = standardFont;
lbl.text = label;
lbl.fontSize = 17;
lbl.alignment = TextAnchor.MiddleLeft;
lbl.color = new Color(0.85f, 0.92f, 0.98f, 1f);
GameObject toggleObj = DefaultControls.CreateToggle(uiResources);
toggleObj.name = "Toggle";
toggleObj.transform.SetParent(row.transform, false);
LayoutElement toggleLayout = toggleObj.AddComponent<LayoutElement>();
toggleLayout.minWidth = 50f;
toggleLayout.preferredWidth = 50f;
Text toggleLabel = toggleObj.GetComponentInChildren<Text>();
if (toggleLabel != null) toggleLabel.text = "";
return toggleObj.GetComponent<Toggle>();
}
private static Dropdown CreateDropdownRow(string name, Transform parent, string label)
{
GameObject row = CreateEmptyRect(name, parent, Vector2.zero, Vector2.one, new Vector2(0f, 42f), Vector2.zero);
LayoutElement layout = row.AddComponent<LayoutElement>();
layout.minHeight = 42f;
layout.preferredHeight = 42f;
HorizontalLayoutGroup hLayout = row.AddComponent<HorizontalLayoutGroup>();
hLayout.spacing = 18f;
hLayout.childAlignment = TextAnchor.MiddleLeft;
hLayout.childControlWidth = false;
hLayout.childControlHeight = true;
hLayout.childForceExpandWidth = false;
hLayout.childForceExpandHeight = true;
GameObject lblGo = CreateEmptyRect("Label", row.transform, Vector2.zero, Vector2.one, new Vector2(260f, 42f), Vector2.zero);
LayoutElement lblLayout = lblGo.AddComponent<LayoutElement>();
lblLayout.minWidth = 260f;
lblLayout.preferredWidth = 260f;
Text lbl = lblGo.AddComponent<Text>();
lbl.font = standardFont;
lbl.text = label;
lbl.fontSize = 17;
lbl.alignment = TextAnchor.MiddleLeft;
lbl.color = new Color(0.85f, 0.92f, 0.98f, 1f);
GameObject dropdownObj = DefaultControls.CreateDropdown(uiResources);
dropdownObj.name = "Dropdown";
dropdownObj.transform.SetParent(row.transform, false);
LayoutElement ddLayout = dropdownObj.AddComponent<LayoutElement>();
ddLayout.minWidth = 380f;
ddLayout.preferredWidth = 380f;
Dropdown dropdown = dropdownObj.GetComponent<Dropdown>();
Text caption = dropdown.captionText;
if (caption != null) caption.font = standardFont;
Text item = dropdown.itemText;
if (item != null) item.font = standardFont;
return dropdown;
}
#endregion
}