Add a Screen

In short

The game shows one screen per GameState. UIRoot.OnGUI switches on the state and calls that screen’s view, an IMGUI class with a Draw(GameRoot game) method. A new screen = a GameState value + a view class + a case in UIRoot + something that calls GameRoot.SetState. A popup over an existing screen does not need a state.

Steps

  1. State. Add a value at the end of enum GameState in Assets/_Project/Scripts/Core/GameState.cs, with a comment. The last three added were Intro, Outro (#40) and Index (#43):
    Index        // the master list of everything in the game (UI/IndexView), a lobby screen like Customize
  2. View. Create Assets/_Project/Scripts/UI/MyView.cs in namespace HomeRunDerby.UI, shaped like the others (RunMapView, MapSelectView): a plain class with public void Draw(GameRoot game) that draws with UIDraw and UITheme (see UI System). Unity creates the .meta file when the Editor imports it; commit it.
  3. Register it in Assets/_Project/Scripts/UI/UIRoot.cs: a field and a case in OnGUI:
    readonly IndexView _index = new IndexView();
    ...
    case GameState.Index: _index.Draw(_game); break;
    If the view needs GameEvents, subscribe in UIRoot.OnEnable and unsubscribe in OnDisable, as _hud and _customize do.
  4. Enter it. Add a method on GameRoot (like OpenMapSelect, EnterCustomize, EnterIndex) that sets up the field and camera and calls SetState(GameState.X). SetState raises GameEvents.StateChanged, which other systems listen to.
    • A lobby screen under the top bar (like CUSTOMIZE and INDEX): add a value to enum LobbyTab and a tab in LobbyNav.DrawBar that calls your GameRoot method, then call _nav.DrawBar(game, LobbyTab.X, w) from your view. Also add the state to ScreenFade.HasTopBar so the bar doesn’t fade between lobby screens.
  5. Check the other state switches and decide what your screen should do there:
    • Audio/GameAudio.OnState: the organ plays on every state except AtBat, CoopWatch, Intro and Outro.
    • Batting/AtBatController (around line 161): the preview batter is aborted on any state except MainMenu, Customize, Lobby, CoopWatch, Intro and Outro.
    • UI/ScreenFade: HasTopBar is MainMenu, Customize and Index; OnState skips the fade from Intro to AtBat / CoopWatch and from AtBat / CoopWatch to Outro (the cutscenes carry the shot over).
    • UI/UIRoot.OnGUI draws IntroOverlayView.DrawTransition and OutroOverlayView.DrawTransition after every screen, so a cutscene’s walk-up or wipe sits over whatever comes next. See Cutscenes.
    • UI/UIRoot.Update: Esc pauses and the cursor is confined only in AtBat.
    • UI/DevMenu: the RUN tools only work in RunMap, Shop and AtBat.

Check it works

No self-test covers screens. Press Play, reach the screen, and check: Esc behaviour, music on or off, the batter preview, and that leaving returns cleanly (GameRoot.GoToMainMenu). Check it at a couple of window sizes; views lay out from UITheme.Width / Height.

Gotchas

  • UIRoot draws nothing until GameRoot.IsReady.
  • Pausing only exists in AtBat; a new gameplay screen that needs pause must add it to UIRoot.Update.
  • If co-op players can be on the screen, the co-op run (Run/CoopRun) also changes states and must know when to go there. Changing what co-op peers expect is a protocol change (Protocol Versions).
  • In the top bar (UI/LobbyNav), PLAY, CUSTOMIZE and INDEX switch states (MainMenu, Customize, Index); PERKS, BATTING CAGE and the settings behind the menu icon are popups, not states.