class_name PresentationNavRequestBudget extends RefCounted const MAX_NEW_REQUESTS_PER_FRAME := 2 var _pending_by_id: Dictionary = {} var _in_flight_ids: Dictionary = {} var _last_drained_frame := -1 func enqueue(stable_id: StringName, priority: int = 0, reason_trace: Array[String] = []) -> bool: if stable_id.is_empty() or _pending_by_id.has(stable_id) or _in_flight_ids.has(stable_id): return false var normalized_trace := reason_trace.duplicate() normalized_trace.sort() _pending_by_id[stable_id] = { "stable_id": stable_id, "priority": priority, "reason_trace": normalized_trace, } return true func take_new_requests(frame_index: int) -> Array[Dictionary]: var result: Array[Dictionary] = [] if frame_index < 0 or frame_index <= _last_drained_frame: return result _last_drained_frame = frame_index var pending: Array[Dictionary] = [] for request in _pending_by_id.values(): pending.append((request as Dictionary).duplicate(true)) pending.sort_custom(_request_before) for index in mini(MAX_NEW_REQUESTS_PER_FRAME, pending.size()): var request: Dictionary = pending[index] var stable_id: StringName = request["stable_id"] _pending_by_id.erase(stable_id) _in_flight_ids[stable_id] = true request["reason_trace"].append("granted_frame_%d" % frame_index) result.append(request) return result func complete(stable_id: StringName) -> bool: return _in_flight_ids.erase(stable_id) func cancel(stable_id: StringName) -> bool: var changed := _pending_by_id.erase(stable_id) return _in_flight_ids.erase(stable_id) or changed func get_pending_ids() -> Array[StringName]: var result: Array[StringName] = [] for stable_id in _pending_by_id: result.append(StringName(stable_id)) result.sort() return result func get_in_flight_ids() -> Array[StringName]: var result: Array[StringName] = [] for stable_id in _in_flight_ids: result.append(StringName(stable_id)) result.sort() return result func clear() -> void: _pending_by_id.clear() _in_flight_ids.clear() _last_drained_frame = -1 func _request_before(first: Dictionary, second: Dictionary) -> bool: if int(first["priority"]) != int(second["priority"]): return int(first["priority"]) > int(second["priority"]) return String(first["stable_id"]) < String(second["stable_id"])