fix(world-map): 🐛 Fix camera texture refresh to prevent stale rendering in offscreen matches by updating occlusion handling
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
921a68a7d9
commit
28e9994e39
1 changed files with 30 additions and 10 deletions
|
|
@ -110,7 +110,10 @@ func _disable_blocking_overlays() -> void:
|
|||
func _apply_arena_camera_fit() -> void:
|
||||
## Find the background camera and zoom out so the whole map fits the
|
||||
## arena cell viewport. Called deferred so it runs after world_map's
|
||||
## own _start_game completes its camera setup.
|
||||
## own _start_game completes its camera setup. Also forces the map
|
||||
## SubViewport's update_mode to UPDATE_ALWAYS so Godot doesn't skip
|
||||
## its draw pass when the arena window is occluded by another arena
|
||||
## window — without this the offscreen matches show stale textures.
|
||||
var game_map: RefCounted = GameState.get_game_map()
|
||||
if game_map == null:
|
||||
return
|
||||
|
|
@ -120,6 +123,13 @@ func _apply_arena_camera_fit() -> void:
|
|||
var cam: Camera2D = vwm.get_background_camera()
|
||||
if cam == null or not cam.has_method("fit_map_to_viewport"):
|
||||
return
|
||||
|
||||
var bg_vp: SubViewport = null
|
||||
if vwm.has_method("get_background_viewport"):
|
||||
bg_vp = vwm.call("get_background_viewport") as SubViewport
|
||||
if bg_vp != null:
|
||||
bg_vp.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
||||
|
||||
var viewport: Viewport = _world_map.get_viewport()
|
||||
if viewport == null:
|
||||
return
|
||||
|
|
@ -222,20 +232,25 @@ func _on_turn_ended(_turn_number: int, _player_index: int) -> void:
|
|||
|
||||
|
||||
func _capture_viewport_screenshot_async() -> void:
|
||||
## Godot on Wayland skips rendering occluded/unfocused windows, so a
|
||||
## raw `get_viewport().get_texture().get_image()` here grabs whatever
|
||||
## stale frame was last drawn — which for windows stacked behind
|
||||
## other arena instances is the loading-screen splash. Wait a few
|
||||
## idle frames AND force an explicit draw pass before grabbing, so
|
||||
## every window renders at least one real gameplay frame to its
|
||||
## texture before we read it back.
|
||||
## Capture the root viewport's texture after forcing a draw pass.
|
||||
## Godot on Wayland skips rendering occluded windows, so we set
|
||||
## update_mode = UPDATE_ALWAYS on the map SubViewport (once, when the
|
||||
## arena helper comes up) and, at capture time, yield a few frames
|
||||
## and call RenderingServer.force_draw() to flush the pipeline. The
|
||||
## world map renders into a SubViewport owned by ViewportWindowManager;
|
||||
## SubViewportContainer composites it into the root viewport each frame,
|
||||
## so grabbing the root viewport gives us HUD + map in one image.
|
||||
## (Grabbing the SubViewport directly returned 2x2 because its size is
|
||||
## tied to the Control's layout state, which isn't deterministic at
|
||||
## capture time.)
|
||||
if _result_dir.is_empty():
|
||||
return
|
||||
var tree: SceneTree = _world_map.get_tree()
|
||||
for _i: int in range(3):
|
||||
for _i: int in range(4):
|
||||
await tree.process_frame
|
||||
RenderingServer.force_draw()
|
||||
await tree.process_frame
|
||||
await tree.process_frame
|
||||
|
||||
var viewport: Viewport = _world_map.get_viewport()
|
||||
if viewport == null:
|
||||
|
|
@ -252,7 +267,12 @@ func _capture_viewport_screenshot_async() -> void:
|
|||
if err != OK:
|
||||
push_warning("[AI ARENA] screenshot save failed: %s" % error_string(err))
|
||||
return
|
||||
print("[AI ARENA] screenshot saved: %s" % path)
|
||||
print(
|
||||
(
|
||||
"[AI ARENA] screenshot saved: %s (%dx%d)"
|
||||
% [path, image.get_width(), image.get_height()]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
func _on_victory(player_index: int, victory_type: String) -> void:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue