using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ProjectI.Builds; using ProjectI.Combat; using ProjectI.Runs; using ProjectI.Sessions; using ProjectI.Settings; using ProjectI.UI; using UnityEngine; using UnityEngine.UIElements; using Cursor = UnityEngine.Cursor; namespace ProjectI.Menu { [DefaultExecutionOrder(-1000)] [RequireComponent(typeof(UIDocument))] public sealed class MainMenuController : MonoBehaviour { [SerializeField] private AbilityDefinition[] abilityDefinitions; [SerializeField] private int[] unlockedAbilityIds; private readonly MainMenuNavigation navigation = new MainMenuNavigation(); private readonly Dictionary definitions = new Dictionary(); private AbilityLibraryState libraryState; private AbilityLibraryPresenter library; private readonly List weaponIds = new List(); private PrototypeSessionController session; private VisualElement screen; private SettingsPanel settings; private DamageVignetteElement vignette; private DropdownField firstWeapon, secondWeapon; private PlayerBuildState preview; private AbilityUnlockState unlocks; private IVisualElementScheduledItem refreshTask; private bool initialized, operation, wasConnected, localReady; private int lifetime; private string feedback = ""; private readonly List<(Button Button, Action Callback)> buttonCallbacks = new List<(Button,Action)>(); private readonly List<(VisualElement Control,EventCallback Callback)> focusCallbacks=new List<(VisualElement,EventCallback)>(); private void OnEnable() { } private void Start() { Initialize(); } private void Initialize() { if (initialized) return; session = PrototypeSessionController.Instance; if (session == null) session = FindAnyObjectByType(); var documentRoot=GetComponent().rootVisualElement; documentRoot.AddToClassList("prototype-ui-root"); screen = documentRoot.Q("menuScreen"); if (screen == null || session == null) return; initialized = true; lifetime++; operation=false; navigation.Reset(); screen.RegisterCallback(OnKeyDown); vignette = new DamageVignetteElement(); screen.Insert(0, vignette); settings = new SettingsPanel(screen, () => { navigation.Back(); ShowPage(); }); ConfigureChoices(); Bind("openWeapons", () => Open("weapons")); Bind("openAbilities", () => Open("abilities")); Bind("lobbyWeapons", () => Open("weapons")); Bind("lobbyAbilities", () => Open("abilities")); Bind("openSettings", () => Open("settings")); Bind("openJoin", () => Open("join")); Bind("openLobby", () => Open("lobby")); Bind("menuBack", Back); Bind("hostGame", () => RunOperation(session.HostAsync, true)); Bind("cancelConnection", CancelConnection); Bind("joinGame", () => RunOperation(() => session.JoinAsync(screen.Q("menuJoinCode").value), true)); Bind("leaveGame", () => RunOperation(session.LeaveAsync, false)); Bind("startGame", () => RunOperation(session.StartRunAsync, true)); Bind("copyJoinCode", () => { GUIUtility.systemCopyBuffer = session.JoinCode; feedback = "Join code copied."; Refresh(); }); Bind("saveWeapons", ApplyLoadout); Bind("saveAbilities", ApplyLoadout); Bind("discardWeapons", DiscardLoadout); Bind("discardAbilities", DiscardLoadout); Bind("readyGame", () => { if (operation || session.Busy) return; session.SetReady(!localReady); Refresh(); }); Bind("quitGame", () => { if (!operation && !session.Busy) Application.Quit(); }); Bind("acknowledgeResults",()=>{var result=PrototypeRunDirector.CachedResult;RunResultsVisibility.Dismiss(result);if(result!=null)PrototypeRunDirector.AcknowledgeCachedResult(result.RunId);navigation.Reset();ShowPage();}); session.Changed += Refresh; refreshTask = screen.schedule.Execute(Refresh).Every(100); LocalPlayerSettings.SetInputBlocked(this, true); Cursor.lockState = CursorLockMode.None; Cursor.visible = true; if(RunResultsVisibility.ShouldShow(PrototypeRunDirector.CachedResult)) {navigation.Open("results");screen.Q