render: extract M2 build queue
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
class_name M2BuildJob
|
||||
extends RefCounted
|
||||
|
||||
## Holds one M2 build cursor, grouped transforms and a strong root reference.
|
||||
## Releasing this record never frees the referenced Node.
|
||||
|
||||
var _tile_key: String
|
||||
var _root: Node3D
|
||||
var _groups: Dictionary
|
||||
var _group_keys: Array
|
||||
var _group_index: int = 0
|
||||
var _transform_offset: int = 0
|
||||
var _batch_serial: int = 0
|
||||
|
||||
|
||||
func _init(tile_key: String, root: Node3D, groups: Dictionary) -> void:
|
||||
_tile_key = tile_key
|
||||
_root = root
|
||||
_groups = groups
|
||||
_group_keys = groups.keys()
|
||||
|
||||
|
||||
## Returns the immutable tile identity used by the queue.
|
||||
func tile_key() -> String:
|
||||
return _tile_key
|
||||
|
||||
|
||||
## Returns the strongly referenced M2 scene root without transferring ownership.
|
||||
func root() -> Node3D:
|
||||
return _root
|
||||
|
||||
|
||||
## Returns the exact grouped-transform Dictionary supplied at enqueue time.
|
||||
func groups() -> Dictionary:
|
||||
return _groups
|
||||
|
||||
|
||||
## Returns the insertion-order group-key snapshot created at enqueue time.
|
||||
func group_keys() -> Array:
|
||||
return _group_keys
|
||||
|
||||
|
||||
## Returns the current model-path group cursor.
|
||||
func group_index() -> int:
|
||||
return _group_index
|
||||
|
||||
|
||||
## Returns the current transform offset within the selected model-path group.
|
||||
func transform_offset() -> int:
|
||||
return _transform_offset
|
||||
|
||||
|
||||
## Returns the next static/animated batch serial used for node naming.
|
||||
func batch_serial() -> int:
|
||||
return _batch_serial
|
||||
|
||||
|
||||
## Atomically adopts all progress values after one planned build operation.
|
||||
func adopt_progress(
|
||||
next_group_index: int,
|
||||
next_transform_offset: int,
|
||||
next_batch_serial: int
|
||||
) -> void:
|
||||
_group_index = next_group_index
|
||||
_transform_offset = next_transform_offset
|
||||
_batch_serial = next_batch_serial
|
||||
|
||||
|
||||
## Returns detached scalar/count diagnostics without engine-object references.
|
||||
func diagnostic_snapshot() -> Dictionary:
|
||||
return {
|
||||
"tile_key": _tile_key,
|
||||
"group_index": _group_index,
|
||||
"transform_offset": _transform_offset,
|
||||
"batch_serial": _batch_serial,
|
||||
"group_count": _group_keys.size(),
|
||||
"has_root": _root != null,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://drawyd5qmel7j
|
||||
@@ -0,0 +1,169 @@
|
||||
class_name M2BuildQueue
|
||||
extends RefCounted
|
||||
|
||||
## Owns pending M2 build-job records and FIFO tile keys. Stale FIFO keys are
|
||||
## intentional: erasing a job never removes its queued key.
|
||||
|
||||
const JOB_SCRIPT := preload("res://src/render/m2/m2_build_job.gd")
|
||||
|
||||
var _jobs_by_tile_key: Dictionary = {}
|
||||
var _queued_tile_keys: Array[String] = []
|
||||
|
||||
|
||||
## Enqueues a typed job. Duplicate tile keys replace the keyed job and append
|
||||
## another FIFO entry, matching raw Dictionary assignment plus Array append.
|
||||
func enqueue(tile_key: String, root: Node3D, groups: Dictionary) -> bool:
|
||||
if tile_key.is_empty() or root == null or groups.is_empty():
|
||||
return false
|
||||
_jobs_by_tile_key[tile_key] = JOB_SCRIPT.new(tile_key, root, groups)
|
||||
_queued_tile_keys.append(tile_key)
|
||||
return true
|
||||
|
||||
|
||||
## Returns whether at least one FIFO key, including a stale key, is pending.
|
||||
func has_pending() -> bool:
|
||||
return not _queued_tile_keys.is_empty()
|
||||
|
||||
|
||||
## Returns the front FIFO tile key, or an empty String when the queue is empty.
|
||||
func front_key() -> String:
|
||||
if _queued_tile_keys.is_empty():
|
||||
return ""
|
||||
return _queued_tile_keys.front()
|
||||
|
||||
|
||||
## Pops and returns the front FIFO key, or an empty String when already empty.
|
||||
func pop_front() -> String:
|
||||
if _queued_tile_keys.is_empty():
|
||||
return ""
|
||||
return _queued_tile_keys.pop_front()
|
||||
|
||||
|
||||
## Moves the front FIFO key to the tail and reports whether a key existed.
|
||||
func rotate_front() -> bool:
|
||||
if _queued_tile_keys.is_empty():
|
||||
return false
|
||||
_queued_tile_keys.append(_queued_tile_keys.pop_front())
|
||||
return true
|
||||
|
||||
|
||||
## Returns whether a tile key still has a current job record.
|
||||
func has_job(tile_key: String) -> bool:
|
||||
return _jobs_by_tile_key.has(tile_key)
|
||||
|
||||
|
||||
## Returns the current job as its engine base type, or null for a stale key.
|
||||
func job_for(tile_key: String) -> RefCounted:
|
||||
return _jobs_by_tile_key.get(tile_key, null) as RefCounted
|
||||
|
||||
|
||||
## Returns the borrowed root for a current job, or null for a stale key.
|
||||
func root_for(tile_key: String) -> Node3D:
|
||||
var job := job_for(tile_key)
|
||||
if job == null:
|
||||
return null
|
||||
return job.call("root") as Node3D
|
||||
|
||||
|
||||
## Returns the exact grouped-transform Dictionary, or an empty Dictionary.
|
||||
func groups_for(tile_key: String) -> Dictionary:
|
||||
var job := job_for(tile_key)
|
||||
if job == null:
|
||||
return {}
|
||||
return job.call("groups") as Dictionary
|
||||
|
||||
|
||||
## Returns the borrowed group-key snapshot, or an empty Array for a stale key.
|
||||
func group_keys_for(tile_key: String) -> Array:
|
||||
var job := job_for(tile_key)
|
||||
if job == null:
|
||||
return []
|
||||
return job.call("group_keys") as Array
|
||||
|
||||
|
||||
## Returns the current model-path group cursor, or zero for a stale key.
|
||||
func group_index_for(tile_key: String) -> int:
|
||||
var job := job_for(tile_key)
|
||||
if job == null:
|
||||
return 0
|
||||
return int(job.call("group_index"))
|
||||
|
||||
|
||||
## Returns the current in-group transform offset, or zero for a stale key.
|
||||
func transform_offset_for(tile_key: String) -> int:
|
||||
var job := job_for(tile_key)
|
||||
if job == null:
|
||||
return 0
|
||||
return int(job.call("transform_offset"))
|
||||
|
||||
|
||||
## Returns the current batch serial, or zero for a stale key.
|
||||
func batch_serial_for(tile_key: String) -> int:
|
||||
var job := job_for(tile_key)
|
||||
if job == null:
|
||||
return 0
|
||||
return int(job.call("batch_serial"))
|
||||
|
||||
|
||||
## Atomically adopts all progress values for a current job.
|
||||
func adopt_progress(
|
||||
tile_key: String,
|
||||
next_group_index: int,
|
||||
next_transform_offset: int,
|
||||
next_batch_serial: int
|
||||
) -> bool:
|
||||
var job := job_for(tile_key)
|
||||
if job == null:
|
||||
return false
|
||||
job.call(
|
||||
"adopt_progress",
|
||||
next_group_index,
|
||||
next_transform_offset,
|
||||
next_batch_serial
|
||||
)
|
||||
return true
|
||||
|
||||
|
||||
## Erases only the keyed job and intentionally leaves every FIFO entry stale.
|
||||
## Returns whether an active record existed. Engine objects are never freed.
|
||||
func erase_job(tile_key: String) -> bool:
|
||||
var had_job := _jobs_by_tile_key.has(tile_key)
|
||||
_jobs_by_tile_key.erase(tile_key)
|
||||
return had_job
|
||||
|
||||
|
||||
## Returns a detached snapshot of active job keys for loader-owned cleanup.
|
||||
func job_keys() -> Array:
|
||||
return _jobs_by_tile_key.keys()
|
||||
|
||||
|
||||
## Releases all job/key references without freeing referenced engine objects.
|
||||
func clear() -> void:
|
||||
_jobs_by_tile_key.clear()
|
||||
_queued_tile_keys.clear()
|
||||
|
||||
|
||||
## Returns FIFO entry count, including duplicate and stale keys.
|
||||
func pending_count() -> int:
|
||||
return _queued_tile_keys.size()
|
||||
|
||||
|
||||
## Returns active keyed job count, excluding stale FIFO keys.
|
||||
func active_job_count() -> int:
|
||||
return _jobs_by_tile_key.size()
|
||||
|
||||
|
||||
## Returns detached FIFO order and tile-key-sorted scalar job diagnostics.
|
||||
func diagnostic_snapshot() -> Dictionary:
|
||||
var tile_keys: Array = _jobs_by_tile_key.keys()
|
||||
tile_keys.sort()
|
||||
var jobs: Array[Dictionary] = []
|
||||
for tile_key_variant in tile_keys:
|
||||
var tile_key := String(tile_key_variant)
|
||||
var job := job_for(tile_key)
|
||||
if job != null:
|
||||
jobs.append(job.call("diagnostic_snapshot") as Dictionary)
|
||||
return {
|
||||
"queued_tile_keys": _queued_tile_keys.duplicate(),
|
||||
"jobs": jobs,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://57qrpiqqgpr4
|
||||
Reference in New Issue
Block a user