Skip to content

Commit

Permalink
Ensure texture loading happens on the main thread
Browse files Browse the repository at this point in the history
Co-authored-by: Will Jordan <[email protected]>
  • Loading branch information
rsubtil and plink-plonk-will committed Aug 27, 2024
1 parent a102147 commit 1358688
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
18 changes: 17 additions & 1 deletion addons/controller_icons/ControllerIcons.gd
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ enum PathType {
var _cached_icons := {}
var _custom_input_actions := {}

var _cached_callables_lock := Mutex.new()
var _cached_callables : Array[Callable] = []

var _last_input_type : InputType
var _last_controller : int
var _settings : ControllerSettings
Expand Down Expand Up @@ -158,14 +161,23 @@ func _test_mouse_velocity(relative_vec: Vector2):
# We do a component sum instead of a length, to save on a
# sqrt operation, and because length_squared is negatively
# affected by low value vectors (<10).
# It is also it's good enough for this system, so reliability
# It is also good enough for this system, so reliability
# is sacrificed in favor of speed.
_mouse_velocity += abs(relative_vec.x) + abs(relative_vec.y)
return _mouse_velocity / _MOUSE_VELOCITY_DELTA > _settings.mouse_min_movement

func _process(delta: float) -> void:
_t += delta

if not _cached_callables.is_empty() and _cached_callables_lock.try_lock():
# UPGRADE: In Godot 4.2, for-loop variables can be
# statically typed:
# for f: Callable in _cached_callables:
for f in _cached_callables:
if f.is_valid(): f.call()
_cached_callables.clear()
_cached_callables_lock.unlock()

func _add_custom_input_action(input_action: String, data: Dictionary):
_custom_input_actions[input_action] = data["events"]

Expand Down Expand Up @@ -656,3 +668,7 @@ func _load_icon(path: String) -> int:
_cached_icons[path] = tex
return OK

func _defer_texture_load(f: Callable) -> void:
_cached_callables_lock.lock()
_cached_callables.push_back(f)
_cached_callables_lock.unlock()
9 changes: 6 additions & 3 deletions addons/controller_icons/objects/ControllerIconTexture.gd
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func _reload_resource():
_dirty = true
emit_changed()

func _load_texture_path_main_thread():
func _load_texture_path_impl():
var textures : Array[Texture2D] = []
if ControllerIcons.is_node_ready() and _can_be_shown():
var input_type = ControllerIcons._last_input_type if force_type == ForceType.NONE else force_type - 1
Expand All @@ -174,9 +174,12 @@ func _load_texture_path_main_thread():
func _load_texture_path():
# Ensure loading only occurs on the main thread
if OS.get_thread_caller_id() != OS.get_main_thread_id():
_load_texture_path_main_thread.call_deferred()
# In Godot 4.3, call_deferred no longer makes this function
# execute on the main thread due to changes in resource loading.
# To ensure this, we instead rely on ControllerIcons for this
ControllerIcons._defer_texture_load(_load_texture_path_impl)
else:
_load_texture_path_main_thread()
_load_texture_path_impl()

func _init():
ControllerIcons.input_type_changed.connect(_on_input_type_changed)
Expand Down

0 comments on commit 1358688

Please sign in to comment.