Files
FreewayGamesTest/Assets/Runtime/Presentation/Factories/MinesweeperScreenBootstrapper.cs
T

127 lines
4.9 KiB
C#

using Minesweeper.Config;
using Minesweeper.Presentation.Views;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Minesweeper.Presentation.Factories
{
public sealed class MinesweeperScreenBootstrapper
{
private const string MainMenuPanelName = "MainMenuPanel";
private const string BoardGridName = "BoardGrid";
private const string PausePanelName = "PausePanel";
private const string ResultPanelName = "ResultPanel";
private const string RestartButtonPath = "RestartButton";
private const string ContinueButtonPath = "ContinueButton";
private const string MainMenuButtonPath = "MainMenuButton";
private const string ResultTextPath = "ResultText";
public MinesweeperScreenRefs Spawn(Transform contentRoot, MinesweeperScreenCatalog catalog)
{
if (contentRoot == null)
{
Debug.LogError("Minesweeper screen bootstrap failed: Content root is not assigned.");
return default;
}
if (catalog == null || !catalog.IsValid)
{
Debug.LogError("Minesweeper screen bootstrap failed: screen catalog prefab references are incomplete.");
return default;
}
ClearContent(contentRoot);
var mainMenu = SpawnScreen(catalog.MainMenuPanelPrefab, contentRoot, MainMenuPanelName, 0);
var board = SpawnScreen(catalog.BoardGridPrefab, contentRoot, BoardGridName, 1);
var pause = SpawnScreen(catalog.PausePanelPrefab, contentRoot, PausePanelName, 2);
var result = SpawnScreen(catalog.ResultPanelPrefab, contentRoot, ResultPanelName, 3);
var mainMenuView = RequireComponent<MainMenuView>(mainMenu.transform, MainMenuPanelName);
mainMenuView.BindRoot(mainMenu);
var refs = new MinesweeperScreenRefs(
mainMenuView,
RequireComponent<RectTransform>(board.transform, BoardGridName),
RequireComponent<GridLayoutGroup>(board.transform, BoardGridName),
pause,
RequireChildComponent<Button>(pause.transform, RestartButtonPath),
RequireChildComponent<Button>(pause.transform, ContinueButtonPath),
RequireChildComponent<Button>(pause.transform, MainMenuButtonPath),
result,
RequireChildComponent<Button>(result.transform, RestartButtonPath),
RequireChildComponent<Button>(result.transform, MainMenuButtonPath),
RequireChildComponent<TMP_Text>(result.transform, ResultTextPath));
mainMenu.SetActive(false);
board.SetActive(false);
pause.SetActive(false);
result.SetActive(false);
return refs;
}
private static GameObject SpawnScreen(GameObject prefab, Transform parent, string expectedName, int siblingIndex)
{
var instance = Object.Instantiate(prefab, parent, false);
instance.name = expectedName;
instance.transform.SetSiblingIndex(siblingIndex);
Stretch(instance.GetComponent<RectTransform>());
return instance;
}
private static void ClearContent(Transform contentRoot)
{
for (var i = contentRoot.childCount - 1; i >= 0; i--)
{
var child = contentRoot.GetChild(i);
child.SetParent(null, false);
Object.Destroy(child.gameObject);
}
}
private static T RequireComponent<T>(Transform root, string ownerName) where T : Component
{
var component = root.GetComponent<T>();
if (component == null)
{
Debug.LogError($"Minesweeper screen bootstrap failed: '{ownerName}' is missing {typeof(T).Name}.");
}
return component;
}
private static T RequireChildComponent<T>(Transform root, string path) where T : Component
{
var child = root.Find(path);
if (child == null)
{
Debug.LogError($"Minesweeper screen bootstrap failed: '{root.name}/{path}' was not found.");
return null;
}
var component = child.GetComponent<T>();
if (component == null)
{
Debug.LogError($"Minesweeper screen bootstrap failed: '{root.name}/{path}' is missing {typeof(T).Name}.");
}
return component;
}
private static void Stretch(RectTransform rectTransform)
{
if (rectTransform == null)
{
return;
}
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.offsetMin = Vector2.zero;
rectTransform.offsetMax = Vector2.zero;
}
}
}