Hidden menu panels stop catching pointers and rendering #19
Loading…
Reference in a new issue
No description provided.
Delete branch "hiccup444/da-game-hiccup:menu-panels-inactive-when-hidden"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
A
MenuPanelis hidden withvisible = false, which neither takes its collider out of physics nor stops its viewport. Both panels keep aStaticBody3Don layer 21 (the layer the XR Tools pointers raycast against) and a 1024x768 SubViewport set toUPDATE_ALWAYS. So two viewports render every frame for the whole session, including gameplay, where neither is visible.handle_pointer_event()doesn't check visibility either.Where it bites: the pause panel lives under
Game, so pausing never disables it. After closing pause, its invisible collider stays 1.3 m in front of where you paused. Back in the main menu, if you paused between the menu anchor and the menu panel, it sits in the laser's path:user://settings.cfg.Level.apply_mode()has the same pattern: hidden content groups keep processing and colliding. That is harmless today (they hold only meshes and labels). Once sandbox items or story props get physics, they would be invisible obstacles in the wrong mode.Changes
src/ui/menu_panel.gd: the panel follows its visibility in the tree.NOTIFICATION_VISIBILITY_CHANGED, it switches itsBody/CollisionShape3Doff or on (deferred, see below) and its SubViewport betweenUPDATE_ALWAYSandUPDATE_DISABLED. It also does this once in_ready, because entering the tree sends no visibility change, so a panel created under a hidden parent has to check for itself.MenuContent.handle_pointer_event()ignores events.src/core/game.gd:_on_menu_action()acts only in MENU and not paused;_on_pause_action()acts only while paused.src/levels/level.gd:apply_mode()goes through a small_set_group()that sets each group'sprocess_modealong with its visibility (hiddenPROCESS_MODE_DISABLED, shownPROCESS_MODE_INHERIT).disable_mode, this also takes a hidden group's collision objects out of the physics space.open_pause()and_unpause_world()still freeze and unfreeze it.Verified by experiment on 4.6.3:
NOTIFICATION_VISIBILITY_CHANGEDreaches a child Node3D when its parent or grandparent Node3D is hidden or shown. It is not sent on entering the tree, hence the call in_ready.CollisionShape3D.disabledinside a physics callback fails with "Can't change this state while flushing queries" (Godot Physics, the project's default engine). Changingprocess_modethere works, so_set_group()stays immediate.button_upbut nopressed, the slider grab ends at its current value, and the next click lands. An OptionButton popup opened by the held press closes too.Tests
tests/pause_check.gdgains a staged run, one stage per frame because the collider switch is deferred. Each stage clears_startedwhen it finishes, so an aborted stage is still reported.UPDATE_DISABLED).UPDATE_ALWAYS). Afterclose_pause()it is inactive again.XRToolsPointerEvents throughhandle_pointer_event().tests/smoke_menu.gd:MenuContentprocesses. A panel created under an already hidden parent starts inactive.MenuContentisPROCESS_MODE_DISABLED,StoryContentprocesses, the menu panel is inactive, and a menu action changes nothing.MenuContentprocesses and the panel is live again. Hiding onlyMenuContent(the panel's ownvisiblestays true) makes the panel inactive, and showing it again makes it live.SandboxContentprocesses and the menu panel is inactive.The full suite list from the CI workflow passes: smoke_menu, arms_check, addon_check, save_check, rig_motion_check, pause_check, input_check. The local run was on Windows with
--xr-mode off(no headset attached); CI covers Linux.pause_check prints a few more of the known first-pass harness lines:
menu_panel.gdnow shows up in the "Failed to compile depended scripts" chain, because the test calls MenuPanel methods;set_anchored()call in the new stages prints the known Nilenabledline.Corrections to the review
handle_pointer_event()guard on its own leaves a press stuck. XR Tools reports the release to the target it locked on press, even after its ray stops hitting it. If the panel hides while the trigger is held (pause toggled off by the pause input), that release is now dropped. The panel still counts the press as held, and the first click after reopening is swallowed. Reproduced headless. Letting go of the press on hide, as described above, fixes it.action_selected(&"options")while not paused, can't fail. PauseMenu handles Options itself and never emitsoptions, and Game has no branch for it. The tests use Save and Return to Menu instead.game.gdguards don't cover the Options controls, sincesettings_changedis a separate signal. The hidden Options page is protected by the panel-side changes: the collider is off, input is ignored, and a held press is dropped without moving a slider.Left for in-headset checking
Overlap with open PRs
Trial merges with #7, #11 and #14 have no conflicts. #11 edits
open_pause(),_unpause_world()and the Load branch of_on_pause_action(), and appends tolevel.gd. This PR's hunks sit next to those but don't overlap.Two interactions with #11:
traversal_checkcalls_on_pause_action(&"save")without pausing, to show that the region blocks saving. With this PR that check still passes, but because the game isn't paused rather than because ofsave_blocked. It should callopen_pause()first to keep testing the gate.apply_mode()from the traversal exit. The deferred collider switch keeps that safe if it runs inside a physics callback.Sibling PRs from the same review: #15, #16, #17 and #18. Their source changes merge cleanly with each other. Several of them add checks at the same spot in
tests/pause_check.gd(and two intests/save_check.gd), so whichever merges second may need a small rebase that keeps both blocks.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.