884 lines
33 KiB
C#
884 lines
33 KiB
C#
using System.Collections.Generic;
|
|
using BumpCombat.Audio;
|
|
using BumpCombat.Core;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.UI;
|
|
|
|
namespace BumpCombat.UI
|
|
{
|
|
/// <summary>
|
|
/// Runtime title, pause, and settings panels. The RunManager owns state;
|
|
/// this component only presents and requests those transitions.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public sealed class RunMenuController : MonoBehaviour
|
|
{
|
|
private enum Screen
|
|
{
|
|
None,
|
|
Title,
|
|
TitleModes,
|
|
Pause,
|
|
Settings,
|
|
}
|
|
|
|
private Screen currentScreen;
|
|
private Screen settingsCaller;
|
|
private RunManager runManager;
|
|
private BumpCombatAudioService audioService;
|
|
private GameObject panel;
|
|
private GameObject modalDim;
|
|
private Text titleText;
|
|
private Text subtitleText;
|
|
private Text inputHelpText;
|
|
private readonly List<Button> buttons = new();
|
|
private readonly List<GameObject> buttonFocusMarkers = new();
|
|
private readonly GameObject[] settingsFocusRows = new GameObject[4];
|
|
private Slider masterSlider;
|
|
private Slider musicSlider;
|
|
private Slider sfxSlider;
|
|
private Text masterValueText;
|
|
private Text musicValueText;
|
|
private Text sfxValueText;
|
|
private int selectedButton;
|
|
private int selectedSettingsControl;
|
|
|
|
public bool IsVisible => panel != null && panel.activeSelf;
|
|
|
|
private void Start()
|
|
{
|
|
runManager = RunManager.Instance;
|
|
audioService = BumpCombatAudioService.Instance;
|
|
PresentationUiStyle.EnsureEventSystem(
|
|
clearMenuNavigationActions: true);
|
|
CreatePanel();
|
|
if (runManager != null)
|
|
{
|
|
runManager.OnTitleChanged += HandleTitleChanged;
|
|
runManager.OnPauseChanged += HandlePauseChanged;
|
|
runManager.OnGameOver += HandleGameOver;
|
|
}
|
|
|
|
if (runManager != null && runManager.IsTitleScreen)
|
|
{
|
|
SetScreen(Screen.Title);
|
|
}
|
|
else
|
|
{
|
|
SetScreen(Screen.None);
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (runManager != null)
|
|
{
|
|
runManager.OnTitleChanged -= HandleTitleChanged;
|
|
runManager.OnPauseChanged -= HandlePauseChanged;
|
|
runManager.OnGameOver -= HandleGameOver;
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (runManager == null || Keyboard.current == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Keyboard keyboard = Keyboard.current;
|
|
if (keyboard.escapeKey.wasPressedThisFrame)
|
|
{
|
|
if (currentScreen == Screen.Settings)
|
|
{
|
|
SetScreen(settingsCaller);
|
|
}
|
|
else if (currentScreen == Screen.TitleModes)
|
|
{
|
|
SetScreen(Screen.Title);
|
|
}
|
|
else if (currentScreen == Screen.Pause)
|
|
{
|
|
runManager.ClosePause();
|
|
}
|
|
else if (currentScreen == Screen.None
|
|
&& !runManager.IsSelectionOpen
|
|
&& !runManager.IsGameOver
|
|
&& !runManager.IsTitleScreen)
|
|
{
|
|
if (runManager.TryOpenPause())
|
|
{
|
|
SetScreen(Screen.Pause);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!IsVisible)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (currentScreen == Screen.Settings)
|
|
{
|
|
HandleSettingsKeyboard(keyboard);
|
|
return;
|
|
}
|
|
|
|
bool moved = false;
|
|
if (keyboard.upArrowKey.wasPressedThisFrame)
|
|
{
|
|
selectedButton = FindNextActiveButton(-1);
|
|
moved = true;
|
|
}
|
|
else if (keyboard.downArrowKey.wasPressedThisFrame)
|
|
{
|
|
selectedButton = FindNextActiveButton(1);
|
|
moved = true;
|
|
}
|
|
if (moved)
|
|
{
|
|
SelectButton(selectedButton, true);
|
|
}
|
|
if (keyboard.enterKey.wasPressedThisFrame
|
|
|| keyboard.numpadEnterKey.wasPressedThisFrame
|
|
|| keyboard.spaceKey.wasPressedThisFrame)
|
|
{
|
|
if (selectedButton >= 0 && selectedButton < buttons.Count)
|
|
{
|
|
Button selected = buttons[selectedButton];
|
|
if (selected != null && selected.interactable)
|
|
{
|
|
audioService?.PlayUi("ui_confirm");
|
|
selected.onClick.Invoke();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (!IsVisible || modalDim == null || panel == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Transform panelParent = panel.transform.parent;
|
|
if (panelParent == null || modalDim.transform.parent != panelParent)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int lastIndex = panelParent.childCount - 1;
|
|
int modalIndex = modalDim.transform.GetSiblingIndex();
|
|
int panelIndex = panel.transform.GetSiblingIndex();
|
|
if (panelIndex == lastIndex && modalIndex == lastIndex - 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
modalDim.transform.SetAsLastSibling();
|
|
panel.transform.SetAsLastSibling();
|
|
}
|
|
|
|
private void HandleTitleChanged(bool isOpen)
|
|
{
|
|
if (isOpen)
|
|
{
|
|
SetScreen(Screen.Title);
|
|
}
|
|
else if (currentScreen == Screen.Title)
|
|
{
|
|
SetScreen(Screen.None);
|
|
}
|
|
}
|
|
|
|
private void HandlePauseChanged(bool isOpen)
|
|
{
|
|
if (isOpen)
|
|
{
|
|
SetScreen(Screen.Pause);
|
|
}
|
|
else if (currentScreen == Screen.Pause)
|
|
{
|
|
SetScreen(Screen.None);
|
|
}
|
|
}
|
|
|
|
private void HandleGameOver()
|
|
{
|
|
SetScreen(Screen.None);
|
|
}
|
|
|
|
private void SetScreen(Screen screen)
|
|
{
|
|
currentScreen = screen;
|
|
if (panel == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
panel.SetActive(screen != Screen.None);
|
|
if (modalDim != null)
|
|
{
|
|
modalDim.SetActive(screen != Screen.None);
|
|
}
|
|
if (screen == Screen.None)
|
|
{
|
|
return;
|
|
}
|
|
|
|
panel.transform.SetAsLastSibling();
|
|
HideAllControls();
|
|
switch (screen)
|
|
{
|
|
case Screen.Title:
|
|
titleText.text = "Tiny Tackle Heroes";
|
|
subtitleText.text = "DIRECTIONAL ACTION SURVIVAL";
|
|
inputHelpText.text = "항목 이동: 위/아래 선택: Enter/Space";
|
|
ShowButton(0, "게임시작", OpenTitleModes);
|
|
ShowButton(1, "설정", OpenTitleSettings);
|
|
ShowButton(2, "업적", OpenTitleAchievements);
|
|
ShowButton(3, "나가기", QuitGame);
|
|
break;
|
|
|
|
case Screen.TitleModes:
|
|
titleText.text = "게임 시작";
|
|
subtitleText.text = "모드를 선택하세요";
|
|
inputHelpText.text = "항목 이동: 위/아래 선택: Enter/Space 뒤로: Esc";
|
|
ShowTitleModeButtons();
|
|
break;
|
|
|
|
case Screen.Pause:
|
|
titleText.text = "PAUSED";
|
|
subtitleText.text = "THE RUN IS WAITING";
|
|
inputHelpText.text = "항목 이동: 위/아래 선택: Enter/Space 계속: Esc";
|
|
ShowButton(0, "계속", ContinueRun);
|
|
ShowButton(1, "설정", OpenPauseSettings);
|
|
ShowButton(2, "다시 시작", RestartRun);
|
|
ShowButton(3, "타이틀", ReturnToTitle);
|
|
break;
|
|
|
|
case Screen.Settings:
|
|
titleText.text = "설정";
|
|
subtitleText.text = "음량";
|
|
inputHelpText.text = "항목 이동: 위/아래 음량 조절: 왼쪽/오른쪽\n뒤로 선택: Enter/Space 즉시 뒤로: Esc";
|
|
ShowSlider(masterSlider, masterValueText, "전체", audioService?.MasterVolume ?? 0.8f);
|
|
ShowSlider(musicSlider, musicValueText, "음악", audioService?.MusicVolume ?? 0.55f);
|
|
ShowSlider(sfxSlider, sfxValueText, "효과음", audioService?.SfxVolume ?? 0.8f);
|
|
ShowButton(3, "뒤로", BackFromSettings);
|
|
break;
|
|
}
|
|
|
|
if (screen == Screen.Settings)
|
|
{
|
|
selectedSettingsControl = 0;
|
|
SelectSettingsControl(false);
|
|
}
|
|
else
|
|
{
|
|
selectedButton = FindFirstActiveButton();
|
|
SelectButton(selectedButton, false);
|
|
}
|
|
}
|
|
|
|
private void HideAllControls()
|
|
{
|
|
for (int i = 0; i < buttons.Count; i++)
|
|
{
|
|
buttons[i].gameObject.SetActive(false);
|
|
}
|
|
SetControlVisible(masterSlider, false);
|
|
SetControlVisible(musicSlider, false);
|
|
SetControlVisible(sfxSlider, false);
|
|
masterValueText.gameObject.SetActive(false);
|
|
musicValueText.gameObject.SetActive(false);
|
|
sfxValueText.gameObject.SetActive(false);
|
|
for (int i = 0; i < settingsFocusRows.Length; i++)
|
|
{
|
|
settingsFocusRows[i]?.SetActive(false);
|
|
}
|
|
}
|
|
|
|
private void ShowButton(int index, string label, UnityEngine.Events.UnityAction action)
|
|
{
|
|
Button button = GetButton(index);
|
|
button.gameObject.SetActive(true);
|
|
button.interactable = true;
|
|
PositionButton(button, 95f - index * 88f);
|
|
Text labelText = button.GetComponentInChildren<Text>();
|
|
labelText.text = label;
|
|
labelText.color = Color.white;
|
|
button.onClick.RemoveAllListeners();
|
|
button.onClick.AddListener(action);
|
|
}
|
|
|
|
private Button GetButton(int index)
|
|
{
|
|
Transform child = panel.transform.Find($"Button {index + 1}");
|
|
Button button = child.GetComponent<Button>();
|
|
buttons[index] = button;
|
|
return button;
|
|
}
|
|
|
|
private void SelectButton(int index, bool playSound)
|
|
{
|
|
if (buttons.Count == 0 || index < 0 || index >= buttons.Count)
|
|
{
|
|
return;
|
|
}
|
|
Button button = buttons[index];
|
|
if (!IsButtonSelectable(button))
|
|
{
|
|
return;
|
|
}
|
|
for (int i = 0; i < buttonFocusMarkers.Count; i++)
|
|
{
|
|
buttonFocusMarkers[i].SetActive(currentScreen != Screen.Settings && i == index);
|
|
}
|
|
EventSystem.current?.SetSelectedGameObject(button.gameObject);
|
|
if (playSound)
|
|
{
|
|
audioService?.PlayUi("ui_move");
|
|
}
|
|
}
|
|
|
|
private int FindFirstActiveButton()
|
|
{
|
|
for (int i = 0; i < buttons.Count; i++)
|
|
{
|
|
if (IsButtonSelectable(buttons[i]))
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
private int FindNextActiveButton(int direction)
|
|
{
|
|
if (buttons.Count == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
int candidate = selectedButton;
|
|
for (int i = 0; i < buttons.Count; i++)
|
|
{
|
|
candidate = (candidate + direction + buttons.Count) % buttons.Count;
|
|
if (IsButtonSelectable(buttons[candidate]))
|
|
{
|
|
return candidate;
|
|
}
|
|
}
|
|
return selectedButton;
|
|
}
|
|
|
|
private static bool IsButtonSelectable(Button button)
|
|
{
|
|
return button != null
|
|
&& button.gameObject.activeSelf
|
|
&& button.interactable;
|
|
}
|
|
|
|
private void HandleSettingsKeyboard(Keyboard keyboard)
|
|
{
|
|
if (keyboard.upArrowKey.wasPressedThisFrame)
|
|
{
|
|
selectedSettingsControl = (selectedSettingsControl + 3) % 4;
|
|
SelectSettingsControl(true);
|
|
}
|
|
else if (keyboard.downArrowKey.wasPressedThisFrame)
|
|
{
|
|
selectedSettingsControl = (selectedSettingsControl + 1) % 4;
|
|
SelectSettingsControl(true);
|
|
}
|
|
|
|
if (selectedSettingsControl < 3
|
|
&& (keyboard.leftArrowKey.wasPressedThisFrame
|
|
|| keyboard.rightArrowKey.wasPressedThisFrame))
|
|
{
|
|
Slider slider = GetSettingsSlider(selectedSettingsControl);
|
|
float delta = keyboard.rightArrowKey.wasPressedThisFrame ? 0.05f : -0.05f;
|
|
slider.value = Mathf.Clamp01(slider.value + delta);
|
|
}
|
|
else if (selectedSettingsControl == 3
|
|
&& (keyboard.enterKey.wasPressedThisFrame
|
|
|| keyboard.numpadEnterKey.wasPressedThisFrame
|
|
|| keyboard.spaceKey.wasPressedThisFrame))
|
|
{
|
|
audioService?.PlayUi("ui_confirm");
|
|
buttons[3].onClick.Invoke();
|
|
}
|
|
}
|
|
|
|
private Slider GetSettingsSlider(int index)
|
|
{
|
|
return index switch
|
|
{
|
|
0 => masterSlider,
|
|
1 => musicSlider,
|
|
_ => sfxSlider,
|
|
};
|
|
}
|
|
|
|
private void SelectSettingsControl(bool playSound)
|
|
{
|
|
for (int i = 0; i < settingsFocusRows.Length; i++)
|
|
{
|
|
if (settingsFocusRows[i] != null)
|
|
{
|
|
settingsFocusRows[i].SetActive(i == selectedSettingsControl);
|
|
}
|
|
}
|
|
|
|
if (selectedSettingsControl == 3)
|
|
{
|
|
SelectButton(3, playSound);
|
|
return;
|
|
}
|
|
Slider slider = GetSettingsSlider(selectedSettingsControl);
|
|
EventSystem.current?.SetSelectedGameObject(slider.gameObject);
|
|
if (playSound)
|
|
{
|
|
audioService?.PlayUi("ui_move");
|
|
}
|
|
}
|
|
|
|
private void BeginDevelopmentRun()
|
|
{
|
|
BeginRun(RunMode.Development);
|
|
}
|
|
|
|
private void BeginProductionRun()
|
|
{
|
|
BeginRun(RunMode.Production);
|
|
}
|
|
|
|
private void OpenTitleModes()
|
|
{
|
|
SetScreen(Screen.TitleModes);
|
|
}
|
|
|
|
private void ShowTitleModeButtons()
|
|
{
|
|
int index = 0;
|
|
if (IsDevelopmentStartVisible(Application.isEditor, Debug.isDebugBuild))
|
|
{
|
|
ShowButton(index++, "개발용 시작", BeginDevelopmentRun);
|
|
}
|
|
ShowButton(index++, "기본 모드", BeginProductionRun);
|
|
ShowDisabledButton(index++, "챌린지 모드(준비 중)");
|
|
ShowDisabledButton(index++, "하드코어 모드(준비 중)");
|
|
ShowButton(index, "뒤로", ReturnToTitleMenu);
|
|
|
|
int visibleButtonCount = index + 1;
|
|
float top = (visibleButtonCount - 1) * 36f;
|
|
for (int buttonIndex = 0; buttonIndex < visibleButtonCount; buttonIndex++)
|
|
{
|
|
RectTransform rect = buttons[buttonIndex].GetComponent<RectTransform>();
|
|
rect.anchoredPosition = new Vector2(
|
|
rect.anchoredPosition.x,
|
|
top - buttonIndex * 72f);
|
|
}
|
|
}
|
|
|
|
private void ShowDisabledButton(int index, string label)
|
|
{
|
|
Button button = GetButton(index);
|
|
button.gameObject.SetActive(true);
|
|
button.interactable = false;
|
|
PositionButton(button, 95f - index * 88f);
|
|
Text labelText = button.GetComponentInChildren<Text>();
|
|
labelText.text = label;
|
|
labelText.color = new Color32(166, 171, 181, 255);
|
|
button.onClick.RemoveAllListeners();
|
|
}
|
|
|
|
private static bool IsDevelopmentStartVisible(
|
|
bool isEditor,
|
|
bool isDevelopmentBuild)
|
|
{
|
|
return isEditor || isDevelopmentBuild;
|
|
}
|
|
|
|
private static void PositionButton(Button button, float y)
|
|
{
|
|
RectTransform rect = button.GetComponent<RectTransform>();
|
|
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, y);
|
|
}
|
|
|
|
private void OpenTitleAchievements()
|
|
{
|
|
MissionAchievementPanel achievements = GetComponent<MissionAchievementPanel>();
|
|
SetScreen(Screen.None);
|
|
if (achievements == null
|
|
|| !achievements.OpenTitleAchievements(ReturnToTitleMenu))
|
|
{
|
|
SetScreen(Screen.Title);
|
|
return;
|
|
}
|
|
audioService?.PlayUi("ui_confirm");
|
|
}
|
|
|
|
private void ReturnToTitleMenu()
|
|
{
|
|
if (runManager != null && runManager.IsTitleScreen)
|
|
{
|
|
SetScreen(Screen.Title);
|
|
}
|
|
}
|
|
|
|
private void BeginRun(RunMode mode)
|
|
{
|
|
if (runManager == null || !runManager.BeginRun(mode))
|
|
{
|
|
return;
|
|
}
|
|
audioService?.PlayUi("ui_confirm");
|
|
SetScreen(Screen.None);
|
|
}
|
|
|
|
private void ContinueRun()
|
|
{
|
|
audioService?.PlayUi("ui_confirm");
|
|
runManager?.ClosePause();
|
|
}
|
|
|
|
private void OpenTitleSettings()
|
|
{
|
|
settingsCaller = Screen.Title;
|
|
SetScreen(Screen.Settings);
|
|
}
|
|
|
|
private void OpenPauseSettings()
|
|
{
|
|
settingsCaller = Screen.Pause;
|
|
SetScreen(Screen.Settings);
|
|
}
|
|
|
|
private void BackFromSettings()
|
|
{
|
|
SetScreen(settingsCaller);
|
|
}
|
|
|
|
private void RestartRun()
|
|
{
|
|
audioService?.PlayUi("ui_confirm");
|
|
runManager?.RestartRun();
|
|
}
|
|
|
|
private void ReturnToTitle()
|
|
{
|
|
audioService?.PlayUi("ui_confirm");
|
|
runManager?.RestartToTitle();
|
|
}
|
|
|
|
private static void QuitGame()
|
|
{
|
|
Application.Quit();
|
|
}
|
|
|
|
private void ShowSlider(
|
|
Slider slider,
|
|
Text valueText,
|
|
string label,
|
|
float value)
|
|
{
|
|
slider.gameObject.SetActive(true);
|
|
valueText.gameObject.SetActive(true);
|
|
slider.value = Mathf.Clamp01(value);
|
|
valueText.text = $"{label} {Mathf.RoundToInt(slider.value * 100f)}%";
|
|
}
|
|
|
|
private void HandleMasterSlider(float value)
|
|
{
|
|
audioService?.SetMasterVolume(value);
|
|
masterValueText.text = $"MASTER {Mathf.RoundToInt(value * 100f)}%";
|
|
}
|
|
|
|
private void HandleMusicSlider(float value)
|
|
{
|
|
audioService?.SetMusicVolume(value);
|
|
musicValueText.text = $"MUSIC {Mathf.RoundToInt(value * 100f)}%";
|
|
}
|
|
|
|
private void HandleSfxSlider(float value)
|
|
{
|
|
audioService?.SetSfxVolume(value);
|
|
sfxValueText.text = $"SFX {Mathf.RoundToInt(value * 100f)}%";
|
|
}
|
|
|
|
private void CreatePanel()
|
|
{
|
|
Font font = PresentationUiStyle.GetGalmuriFont();
|
|
panel = PresentationUiStyle.CreatePanel(
|
|
transform,
|
|
"Run Menu",
|
|
new Vector2(0.5f, 0.5f),
|
|
Vector2.zero,
|
|
new Vector2(1180f, 720f),
|
|
Color.white);
|
|
PresentationUiStyle.ApplyPanel(panel.GetComponent<Image>());
|
|
|
|
modalDim = new GameObject(
|
|
"Run Menu Modal Dim",
|
|
typeof(RectTransform),
|
|
typeof(CanvasRenderer),
|
|
typeof(Image));
|
|
modalDim.transform.SetParent(transform, false);
|
|
RectTransform modalRect = modalDim.GetComponent<RectTransform>();
|
|
modalRect.anchorMin = Vector2.zero;
|
|
modalRect.anchorMax = Vector2.one;
|
|
modalRect.offsetMin = Vector2.zero;
|
|
modalRect.offsetMax = Vector2.zero;
|
|
Image modalImage = modalDim.GetComponent<Image>();
|
|
modalImage.color = new Color(0f, 0f, 0f, 0.72f);
|
|
modalImage.raycastTarget = true;
|
|
modalDim.transform.SetSiblingIndex(panel.transform.GetSiblingIndex());
|
|
|
|
titleText = CreateText(panel.transform, "Title", font, 46, new Vector2(0f, 260f), new Vector2(1000f, 70f));
|
|
subtitleText = CreateText(panel.transform, "Subtitle", font, 18, new Vector2(0f, 205f), new Vector2(1000f, 40f));
|
|
inputHelpText = CreateText(panel.transform, "Menu Input Help", font, 18, Vector2.zero, new Vector2(1100f, 40f));
|
|
RectTransform inputHelpRect = inputHelpText.rectTransform;
|
|
inputHelpRect.anchorMin = Vector2.zero;
|
|
inputHelpRect.anchorMax = Vector2.zero;
|
|
inputHelpRect.pivot = Vector2.zero;
|
|
inputHelpRect.anchoredPosition = new Vector2(32f, 24f);
|
|
inputHelpRect.sizeDelta = new Vector2(1100f, 60f);
|
|
inputHelpText.alignment = TextAnchor.MiddleLeft;
|
|
inputHelpText.color = new Color32(200, 208, 218, 255);
|
|
CreateSettingsFocusRows(panel.transform);
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
Button button = CreateButton(panel.transform, $"Button {i + 1}", font, new Vector2(0f, 95f - i * 88f));
|
|
button.gameObject.SetActive(false);
|
|
buttons.Add(button);
|
|
buttonFocusMarkers.Add(CreateButtonFocusMarker(button.transform));
|
|
AddButtonPointerSelection(button, i);
|
|
}
|
|
|
|
masterSlider = CreateSlider(panel.transform, "Master Slider", new Vector2(0f, 90f));
|
|
musicSlider = CreateSlider(panel.transform, "Music Slider", new Vector2(0f, 0f));
|
|
sfxSlider = CreateSlider(panel.transform, "Sfx Slider", new Vector2(0f, -90f));
|
|
masterValueText = CreateText(panel.transform, "Master Value", font, 22, new Vector2(-230f, 90f), new Vector2(280f, 50f));
|
|
musicValueText = CreateText(panel.transform, "Music Value", font, 22, new Vector2(-230f, 0f), new Vector2(280f, 50f));
|
|
sfxValueText = CreateText(panel.transform, "Sfx Value", font, 22, new Vector2(-230f, -90f), new Vector2(280f, 50f));
|
|
masterSlider.onValueChanged.AddListener(HandleMasterSlider);
|
|
musicSlider.onValueChanged.AddListener(HandleMusicSlider);
|
|
sfxSlider.onValueChanged.AddListener(HandleSfxSlider);
|
|
AddSliderPointerSelection(masterSlider, 0);
|
|
AddSliderPointerSelection(musicSlider, 1);
|
|
AddSliderPointerSelection(sfxSlider, 2);
|
|
panel.SetActive(false);
|
|
}
|
|
|
|
private void CreateSettingsFocusRows(Transform parent)
|
|
{
|
|
for (int i = 0; i < settingsFocusRows.Length; i++)
|
|
{
|
|
bool isBackButton = i == 3;
|
|
float y = isBackButton ? -169f : 90f - i * 90f;
|
|
Vector2 size = isBackButton
|
|
? new Vector2(520f, 76f)
|
|
: new Vector2(820f, 52f);
|
|
GameObject row = new($"Settings Focus {i}", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
|
row.transform.SetParent(parent, false);
|
|
RectTransform rowRect = row.GetComponent<RectTransform>();
|
|
rowRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
rowRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
rowRect.pivot = new Vector2(0.5f, 0.5f);
|
|
rowRect.anchoredPosition = new Vector2(isBackButton ? 0f : 5f, y);
|
|
rowRect.sizeDelta = size;
|
|
Image rowImage = row.GetComponent<Image>();
|
|
rowImage.color = new Color32(75, 128, 148, 72);
|
|
rowImage.raycastTarget = false;
|
|
|
|
GameObject marker = new($"Marker {i}", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
|
marker.transform.SetParent(row.transform, false);
|
|
RectTransform markerRect = marker.GetComponent<RectTransform>();
|
|
markerRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
markerRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
markerRect.pivot = new Vector2(0.5f, 0.5f);
|
|
markerRect.anchoredPosition = new Vector2(-size.x * 0.5f + 12f, 0f);
|
|
markerRect.sizeDelta = new Vector2(6f, 34f);
|
|
Image markerImage = marker.GetComponent<Image>();
|
|
markerImage.color = new Color32(240, 196, 92, 255);
|
|
markerImage.raycastTarget = false;
|
|
row.SetActive(false);
|
|
settingsFocusRows[i] = row;
|
|
}
|
|
}
|
|
|
|
private static GameObject CreateButtonFocusMarker(Transform parent)
|
|
{
|
|
GameObject marker = new("Focus Marker", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
|
marker.transform.SetParent(parent, false);
|
|
RectTransform rect = marker.GetComponent<RectTransform>();
|
|
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
rect.pivot = new Vector2(0.5f, 0.5f);
|
|
rect.anchoredPosition = new Vector2(-210f, 0f);
|
|
rect.sizeDelta = new Vector2(6f, 38f);
|
|
Image image = marker.GetComponent<Image>();
|
|
image.color = new Color32(240, 196, 92, 255);
|
|
image.raycastTarget = false;
|
|
marker.SetActive(false);
|
|
return marker;
|
|
}
|
|
|
|
private static Text CreateText(
|
|
Transform parent,
|
|
string name,
|
|
Font font,
|
|
int fontSize,
|
|
Vector2 position,
|
|
Vector2 size)
|
|
{
|
|
return PresentationUiStyle.CreateText(
|
|
parent,
|
|
name,
|
|
font,
|
|
fontSize,
|
|
TextAnchor.MiddleCenter,
|
|
position,
|
|
size);
|
|
}
|
|
|
|
private static Button CreateButton(
|
|
Transform parent,
|
|
string name,
|
|
Font font,
|
|
Vector2 position)
|
|
{
|
|
GameObject buttonObject = new(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button));
|
|
buttonObject.transform.SetParent(parent, false);
|
|
RectTransform rect = buttonObject.GetComponent<RectTransform>();
|
|
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
rect.pivot = new Vector2(0.5f, 0.5f);
|
|
rect.anchoredPosition = position;
|
|
rect.sizeDelta = new Vector2(460f, 68f);
|
|
Button button = buttonObject.GetComponent<Button>();
|
|
Image image = buttonObject.GetComponent<Image>();
|
|
button.targetGraphic = image;
|
|
Navigation navigation = button.navigation;
|
|
navigation.mode = Navigation.Mode.None;
|
|
button.navigation = navigation;
|
|
PresentationUiStyle.ApplyButton(button);
|
|
Text text = CreateText(buttonObject.transform, "Label", font, 24, Vector2.zero, new Vector2(430f, 58f));
|
|
text.raycastTarget = false;
|
|
return button;
|
|
}
|
|
|
|
private static Slider CreateSlider(Transform parent, string name, Vector2 position)
|
|
{
|
|
GameObject sliderObject = new(name, typeof(RectTransform), typeof(Slider));
|
|
sliderObject.transform.SetParent(parent, false);
|
|
RectTransform rect = sliderObject.GetComponent<RectTransform>();
|
|
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
rect.pivot = new Vector2(0.5f, 0.5f);
|
|
rect.anchoredPosition = position + Vector2.right * 130f;
|
|
rect.sizeDelta = new Vector2(500f, 42f);
|
|
Slider slider = sliderObject.GetComponent<Slider>();
|
|
slider.minValue = 0f;
|
|
slider.maxValue = 1f;
|
|
slider.wholeNumbers = false;
|
|
GameObject backgroundObject = new("Background", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
|
backgroundObject.transform.SetParent(sliderObject.transform, false);
|
|
RectTransform backgroundRect = backgroundObject.GetComponent<RectTransform>();
|
|
backgroundRect.anchorMin = new Vector2(0f, 0.5f);
|
|
backgroundRect.anchorMax = new Vector2(1f, 0.5f);
|
|
backgroundRect.sizeDelta = new Vector2(0f, 18f);
|
|
Image background = backgroundObject.GetComponent<Image>();
|
|
background.color = new Color(0.16f, 0.19f, 0.24f, 1f);
|
|
|
|
GameObject fillAreaObject = new("Fill Area", typeof(RectTransform));
|
|
fillAreaObject.transform.SetParent(sliderObject.transform, false);
|
|
RectTransform fillAreaRect = fillAreaObject.GetComponent<RectTransform>();
|
|
fillAreaRect.anchorMin = new Vector2(0f, 0.5f);
|
|
fillAreaRect.anchorMax = new Vector2(1f, 0.5f);
|
|
fillAreaRect.sizeDelta = new Vector2(0f, 18f);
|
|
GameObject fillObject = new("Fill", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
|
fillObject.transform.SetParent(fillAreaObject.transform, false);
|
|
RectTransform fillRect = fillObject.GetComponent<RectTransform>();
|
|
fillRect.anchorMin = Vector2.zero;
|
|
fillRect.anchorMax = Vector2.one;
|
|
fillRect.offsetMin = Vector2.zero;
|
|
fillRect.offsetMax = Vector2.zero;
|
|
Image fillImage = fillObject.GetComponent<Image>();
|
|
fillImage.color = new Color32(222, 183, 112, 255);
|
|
|
|
GameObject handleAreaObject = new("Handle Area", typeof(RectTransform));
|
|
handleAreaObject.transform.SetParent(sliderObject.transform, false);
|
|
RectTransform handleAreaRect = handleAreaObject.GetComponent<RectTransform>();
|
|
handleAreaRect.anchorMin = new Vector2(0f, 0.5f);
|
|
handleAreaRect.anchorMax = new Vector2(1f, 0.5f);
|
|
handleAreaRect.sizeDelta = Vector2.zero;
|
|
GameObject handleObject = new("Handle", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
|
handleObject.transform.SetParent(handleAreaObject.transform, false);
|
|
RectTransform handleRect = handleObject.GetComponent<RectTransform>();
|
|
handleRect.anchorMin = new Vector2(0f, 0.5f);
|
|
handleRect.anchorMax = new Vector2(0f, 0.5f);
|
|
handleRect.sizeDelta = new Vector2(24f, 36f);
|
|
Image handleImage = handleObject.GetComponent<Image>();
|
|
handleImage.color = new Color32(240, 216, 153, 255);
|
|
slider.fillRect = fillRect;
|
|
slider.handleRect = handleRect;
|
|
slider.targetGraphic = handleImage;
|
|
Navigation navigation = slider.navigation;
|
|
navigation.mode = Navigation.Mode.None;
|
|
slider.navigation = navigation;
|
|
slider.direction = Slider.Direction.LeftToRight;
|
|
return slider;
|
|
}
|
|
|
|
private void AddButtonPointerSelection(Button button, int index)
|
|
{
|
|
EventTrigger trigger = button.gameObject.AddComponent<EventTrigger>();
|
|
EventTrigger.Entry entry = new() { eventID = EventTriggerType.PointerEnter };
|
|
entry.callback.AddListener(_ =>
|
|
{
|
|
if (!button.interactable)
|
|
{
|
|
return;
|
|
}
|
|
selectedButton = index;
|
|
if (currentScreen == Screen.Settings && index == 3)
|
|
{
|
|
selectedSettingsControl = 3;
|
|
SelectSettingsControl(false);
|
|
}
|
|
else
|
|
{
|
|
SelectButton(index, false);
|
|
}
|
|
});
|
|
trigger.triggers.Add(entry);
|
|
}
|
|
|
|
private void AddSliderPointerSelection(Slider slider, int index)
|
|
{
|
|
EventTrigger trigger = slider.gameObject.AddComponent<EventTrigger>();
|
|
EventTrigger.Entry entry = new() { eventID = EventTriggerType.PointerEnter };
|
|
entry.callback.AddListener(_ =>
|
|
{
|
|
selectedSettingsControl = index;
|
|
SelectSettingsControl(false);
|
|
});
|
|
trigger.triggers.Add(entry);
|
|
}
|
|
|
|
private static void SetControlVisible(Component control, bool visible)
|
|
{
|
|
if (control != null)
|
|
{
|
|
control.gameObject.SetActive(visible);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|