Skip to content

Conversation

@JamesVanBoxtel
Copy link
Contributor

  • Language selection setup screen created, shown when language not set
  • Discord information setup screen created, new config for when it has been shown
  • New Input Overlay Scene for picking inputs
  • New controller theme graphics for representing input device type
  • Comprehensive BattleRoom methods for managing players and their input assignments
  • Restore previous assignments in 1P if they have been picked this session
  • Language now defaults to English but not confirmed until picked
  • Set Language method decoupled from saving language to support above
  • InputPromptRenderer for drawing device images and eventually button prompts
  • InputConfiguration has become a full class with device name, image, label etc fully accessible.
  • InputManager manages the input configurations and provides a touch one.
  • Added a second WASD default configuration for when new players don't have any yet and expect to navigate menus with WASD
  • Input Device Overlay is shown in character select when not all human local players are assigned.
  • Added change input device button for changing after you have already assigned
  • Input Config Menu visuals improved, added auto configure joystick
  • Added SceneCoordinator class for auto showing next scenes based on state
  • Added ability for labels to autosize
  • Added ability for menus to size to fit
  • Added a slider menu item
  • Made UIElement properly traverse touch from topmost down
  • Auto show input config on new controller
  • Add way to set TYPE variable on class constructor
  • Added debugging print functions on UIElement
  • Clear previous bindings when reusing key
  • Require all keys bound before exiting config
  • Input manager cleanup

Video showing language picker, discord info, configuring new controller, can't exit till not partially configured.

Screen.Recording.2025-10-31.at.9.20.53.AM.mp4

Repost of this commit since it was reverted.

The Debug Settings system provides runtime-configurable debug features through a UI overlay. Settings are persisted to config.debug and can be accessed anywhere via the DebugSettings singleton.

Also provide a way to generate the debug menu and surface it from a debug button.

To support this new button and future overlays, add a root element to the game so we can order overlays

Updated Bool Selector to size correctly
Updated Style Selector creation to make sure sizing and layout is right
Reload main menu when you come back to it
Make navigation stack a UIElement so it works with touch handling

Fixes panel-attack#697
Language selection setup screen created, shown when language not set
Discord information setup screen created, new config for when it has been shown
New Input Overlay Scene for picking inputs
New controller theme graphics for representing input device type
Comprehensive BattleRoom methods for managing players and their input assignments
Restore previous assignments in 1P if they have been picked this session
Language now defaults to English but not confirmed until picked
Set Language method decoupled from saving language to support above
InputPromptRenderer for drawing device images and eventually button prompts
InputConfiguration has become a full class with device name, image, label etc fully accessible.
InputManager manages the input configurations and provides a touch one.
Added a second WASD default configuration for when new players don't have any yet and expect to navigate menus with WASD
Input Device Overlay is shown in character select when not all human local players are assigned.
Added change input device button for changing after you have already assigned
Input Config Menu visuals improved, added auto configure joystick
Added SceneCoordinator class for auto showing next scenes based on state
Added ability for labels to autosize
Added ability for menus to size to fit
Added a slider menu item
Made UIElement properly traverse touch from topmost down
Auto show input config on new controller
Add way to set TYPE variable on class constructor
Added debugging print functions on UIElement
Clear previous bindings when reusing key
Require all keys bound before exiting config
Input manager cleanup
@JamesVanBoxtel JamesVanBoxtel added this to the 25.1 milestone Nov 9, 2025
@Endaris
Copy link
Collaborator

Endaris commented Nov 29, 2025

Hi, some initial feedback, I hope to make some more serious progress over the weekend but there's something I already want to discuss regarding the architecture adjustment to the scenes. I wanted to review some yesterday and then got stuck superhard on this really early which kept me from looking at the rest so I'll get this one out early

In particular this is about SceneCoordinator and the new Scene.triggerNextScene callback.

Obviously it works and it's good in the sense that the scenes themselves don't have to know about how they are used but I think the approach strays a bit too far from what a Scene ideally should be to keep things easily composable without having to add a class like SceneCoordinator to glue things together.

Semantically I understand a Scene as the composition of audio, UI and input options that serves a specific purpose. For the feature in this PR I would intuitively think that what is currently StartUp could be renamed to BootScene and that what the SceneCoordinator does is more representative of what a StartUpScene does - except that it is not a Scene right now.

I think having a SceneCoordinator besides the NavigationStack is confusing and misleading.
Partially a name thing but generally speaking, the first start up functionality could mostly also be implemented by checking in the current StartUp whether the respective config fields are set and simply pushing the desired scenes in reverse order on top of the NavigationStack and then they just pop off one after another and always set the config field on exit. And the callback for bringing up the InputConfigMenu could live on Game rather than have its own class.
I think if we feel like there are lacking options in regards to chaining scenes, then we should extend the functionality of NavigationStack rather than inventing new things that intentionally work around the center component of our Scene navigation. This is the main gripe I have with this new class.

I think we have two options here:

  1. Aim for composition of menus instead of composition of scenes.
    Menus can be ready made UIElements that provide an onExit callback so that a scene can chain multiple menus after another by setting the callback on the menu instance and replacing its own uiRoot with the new menu. We could gather standalone menus in a new directory, e.g. src/menus.
    If we have menus we want to show in different situations like the InputConfigMenu, we have the option to wrap them in a standalone scene but also present them in a composed Scene like the first start up assistant here.
    SceneCoordinator becomes an actual StartUpScene. It uses the exit callback of the new menus to call its own continueSetupFlow which replaces the menu within the scene itself instead of pushing a Scene.
    Flexible, does not collide with the NavigationStack purpose. Seems like an intuitive architecture to break up OptionsMenu down the line.

  2. Add more functions to NavigationStack that help with pushing a sequence of scenes.
    Could look something like this in place of where SceneCoordinator.handleStartupComplete(SceneCoordinator) is called in StartUp?

local startUpSequence = {}
-- Check language selection
if not config.language_code then
  table.insert(startUpSequence, require("client.src.scenes.LanguageSelectSetup"))
end

-- Check Discord community welcome
if not config.discordCommunityShown then
  table.insert(startUpSequence, require("client.src.scenes.DiscordCommunitySetup"))
end

-- Check for unconfigured joysticks
if input.hasUnsavedChanges or input:hasUnconfiguredJoysticks() then
  table.insert(startUpSequence, require("client.src.scenes.InputConfigMenu"))
end

table.insert(startUpSequence, require("client.src.scenes.MainMenu"))

GAME.navigationStack:pushSequence(startUpSequence)

The new pushSequence would respectively take care of pushing the scenes in the correct order so they pop up one after another.

I think I'm fine with either, I think you were leaning towards menus as UI elements before?
But it's mainly food for thought based on my feeling of SceneCoordinator adding complexity to the project when there's less complex or more flexible solutions.

@JamesVanBoxtel
Copy link
Contributor Author

I think I see what you mean, here is a proposal for a cleaner approach. Please let me know if its what you were thinking.

Instead of having a separate SceneCoordinator class that works alongside the navigation system, I'll rename the BootScene to StartupScene and move all the SceneCoordinator logic into it.

  1. Uses NavigationStack directly as the sole navigation mechanism—no separate coordinator layer, no Scene.triggerNextScene callback
  2. Owns the startup flow by checking what setup steps are needed and pushing the appropriate scenes (LanguageSelect, DiscordCommunity, InputConfig) via GAME.navigationStack:push()

The flow would work like this: StartUpScene enters and evaluates what's needed, pushes the first required setup scene, then when that scene pops, StartUpScene:resume() re-evaluates and either
pushes the next step or replaces itself with MainMenu when done. All navigation goes through NavigationStack—the startup scene just decides what to navigate to. This aligns with your suggestion
of working within NavigationStack rather than inventing parallel mechanisms.

I may need to add a little bit of logic to NavigationStack so we can transition to the next scene without showing the boot scene for a frame and getting a flicker. TBD

For the input config callback you mentioned should live on Game, I'll move that there or just call GAME.navigationStack:push(InputConfigMenu) directly from the startup scene.

This eliminates having a coordinator side mechanism and generic callback that were the core concerns, while still giving us a proper place to orchestrate the first-time setup flow.

Let me know if this works for you and I can implement.

@JamesVanBoxtel
Copy link
Contributor Author

After attempting to implement the solution we discussed, I encountered a fundamental issue that I believe I encountered during my initial attempt.

We require a seamless transition from Discord to InputConfig, with no flickering animation. This becomes even more challenging when we want to implement a slide transition or something similar, as both scenes are simultaneously visible. We cannot have an “in-between” scene that is not part of the actual transition. Instead, we need to replace one scene with another without briefly displaying something in between.

BattleRoom, ChallengeMode, and Game all already coordinate scenes that perform similar functions.

Additionally, we have the following requirements:

  1. Scenes must be self-contained. DiscordCommunitySetup should not be aware of InputConfig.
  2. There must be a mechanism to determine the flow of the transition. The logic for “After Discord, show InputConfig” should reside somewhere.

This is why I implemented the solution in the manner I did and added Scene.triggerNextScene to decouple the components. However, I believe triggerNextScene should not be generic, and each scene should have its own specific requirements for the name or if a function is required for returning. For instance, ChallengeMode could have a win and a lose function passed in.

Therefore, I believe the original solution is largely sound, except for the fact that triggerNextScene should not be generic. Please advise whether you believe modifying that is sufficient or if we still need to make further changes.

If so, how can we achieve these goals in an alternative manner? Alternatively, would you like to attempt refactoring while still meeting these goals?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants