Defer initial processing of gunk clear total until both the clear frame and initial mask have been applied

This commit is contained in:
Rob Kelly 2025-03-12 16:53:24 -06:00
parent b4b133b76c
commit 53ea89d6b8
3 changed files with 22 additions and 12 deletions

View File

@ -1,8 +1,5 @@
class_name DrawController extends Control class_name DrawController extends Control
## Emitted the frame after at least one paint operation was done.
signal painted
var _draw_queue: Array[Callable] = [] var _draw_queue: Array[Callable] = []
var _dirty := false var _dirty := false
@ -33,10 +30,13 @@ func _process(_delta: float) -> void:
if _dirty: if _dirty:
queue_redraw() queue_redraw()
_dirty = false _dirty = false
painted.emit()
# show clear rect for one frame # show clear rect for one frame
mask_clear.visible = _clear mask_clear.visible = _clear
_clear = false _clear = false
mask_texture.visible = _show_texture mask_texture.visible = _show_texture
_show_texture = false _show_texture = false
func _set_dirty() -> void:
_dirty = true

View File

@ -27,7 +27,7 @@ var _multiline_buffer := PackedVector2Array()
var _multiline_width := 1.0 var _multiline_width := 1.0
var _clear_total := 0.0 var _clear_total := 0.0
var _prev_clear_total := 0.0 var _prev_clear_total := -1.0
# _clear_total is async computed in separate thread # _clear_total is async computed in separate thread
var _mask_tx: Texture2D var _mask_tx: Texture2D
@ -83,6 +83,12 @@ func _trigger_recompute_deferred() -> void:
func _async_compute_clear_total() -> void: func _async_compute_clear_total() -> void:
# Ignore first two calls (initial mask clear & texture)
# NOTE: this technically could put us in a glitched state if that mask clear & texture don't happen
# and the thread wouldn't be able to hit the exit condition.
# If the application hangs in a weird way immediately after loading a scene, maybe this is why!
_semaphore.wait()
_semaphore.wait()
while true: while true:
_semaphore.wait() _semaphore.wait()
@ -184,7 +190,6 @@ func _get_uv(point: Vector3, normal: Vector3) -> Vector2:
## Returns Vector2.INF if the given point+normal does not lie on this mesh within tolerance. ## Returns Vector2.INF if the given point+normal does not lie on this mesh within tolerance.
func _get_px(point: Vector3, normal: Vector3) -> Vector2: func _get_px(point: Vector3, normal: Vector3) -> Vector2:
debug_draw.draw_vector(normal, point) debug_draw.draw_vector(normal, point)
#print_debug("POINT: ", point, "; NORMAL: ", normal)
return _get_uv(point * global_transform, normal * global_basis) * mask_control.size return _get_uv(point * global_transform, normal * global_basis) * mask_control.size
@ -241,10 +246,13 @@ func _process(_delta: float) -> void:
_mutex.unlock() _mutex.unlock()
var delta := new_total - _prev_clear_total var delta := new_total - _prev_clear_total
if abs(delta) > CLEAR_TOTAL_EPSILON: if abs(delta) > CLEAR_TOTAL_EPSILON:
clear_total_updated.emit(new_total) # Do not fire signal on first compute after initialization
# XXX due to fp error, this will drift from the "true count" over time # This prevents the player from collecting the grunk from the initial mask.
# but it probably won't matter :shrug: if _prev_clear_total >= 0:
Game.manager.collect_grunk(delta) clear_total_updated.emit(new_total)
# XXX due to fp error, this will drift from the "true count" over time
# but it probably won't matter :shrug:
Game.manager.collect_grunk(delta)
_prev_clear_total = new_total _prev_clear_total = new_total
# If paint_continuous wasn't called last frame, stop the current polyline. # If paint_continuous wasn't called last frame, stop the current polyline.
@ -265,4 +273,4 @@ func _process(_delta: float) -> void:
func _on_mask_painted() -> void: func _on_mask_painted() -> void:
# XXX any problem with posting each frame? # XXX any problem with posting each frame?
call_deferred("_trigger_recompute_deferred") _trigger_recompute_deferred.call_deferred()

View File

@ -56,4 +56,6 @@ grow_vertical = 2
mouse_filter = 2 mouse_filter = 2
script = ExtResource("3_m8wx4") script = ExtResource("3_m8wx4")
[connection signal="painted" from="MaskViewport/MaskControl" to="." method="_on_mask_painted"] [connection signal="visibility_changed" from="MaskViewport/MaskClear" to="MaskViewport/MaskControl" method="_set_dirty"]
[connection signal="visibility_changed" from="MaskViewport/MaskTexture" to="MaskViewport/MaskControl" method="_set_dirty"]
[connection signal="draw" from="MaskViewport/MaskControl" to="." method="_on_mask_painted"]