refactor(M03): extract M2 prototype cache state
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
class_name M2PrototypeCacheState
|
||||
extends RefCounted
|
||||
|
||||
## Owns detached static/animated M2 prototypes and their negative lookup
|
||||
## outcomes until final renderer shutdown.
|
||||
|
||||
var _static_prototypes_by_path: Dictionary = {}
|
||||
var _animated_prototypes_by_path: Dictionary = {}
|
||||
var _missing_model_paths: Dictionary = {}
|
||||
var _static_animation_paths: Dictionary = {}
|
||||
|
||||
|
||||
## Returns whether a valid static prototype is retained for the normalized path.
|
||||
func has_static_prototype(normalized_relative_path: String) -> bool:
|
||||
return find_static_prototype(normalized_relative_path) != null
|
||||
|
||||
|
||||
## Returns the exact retained static prototype or null.
|
||||
func find_static_prototype(normalized_relative_path: String) -> Node3D:
|
||||
return _find_valid_prototype(_static_prototypes_by_path, normalized_relative_path)
|
||||
|
||||
|
||||
## Adopts a static prototype and returns the canonical retained reference. The
|
||||
## first valid prototype wins; a later detached candidate is released.
|
||||
func adopt_static_prototype(
|
||||
normalized_relative_path: String,
|
||||
prototype: Node3D) -> Node3D:
|
||||
return _adopt_prototype(
|
||||
_static_prototypes_by_path,
|
||||
normalized_relative_path,
|
||||
prototype
|
||||
)
|
||||
|
||||
|
||||
## Returns whether a valid animated prototype is retained for the normalized path.
|
||||
func has_animated_prototype(normalized_relative_path: String) -> bool:
|
||||
return find_animated_prototype(normalized_relative_path) != null
|
||||
|
||||
|
||||
## Returns the exact retained animated prototype or null.
|
||||
func find_animated_prototype(normalized_relative_path: String) -> Node3D:
|
||||
return _find_valid_prototype(_animated_prototypes_by_path, normalized_relative_path)
|
||||
|
||||
|
||||
## Adopts an animated prototype and returns the canonical retained reference.
|
||||
func adopt_animated_prototype(
|
||||
normalized_relative_path: String,
|
||||
prototype: Node3D) -> Node3D:
|
||||
return _adopt_prototype(
|
||||
_animated_prototypes_by_path,
|
||||
normalized_relative_path,
|
||||
prototype
|
||||
)
|
||||
|
||||
|
||||
## Records that no model prototype can currently be loaded for this path.
|
||||
func mark_model_missing(normalized_relative_path: String) -> bool:
|
||||
return _mark_path(_missing_model_paths, normalized_relative_path)
|
||||
|
||||
|
||||
## Returns whether the model path has a retained missing outcome.
|
||||
func is_model_missing(normalized_relative_path: String) -> bool:
|
||||
return not normalized_relative_path.is_empty() and _missing_model_paths.has(
|
||||
normalized_relative_path
|
||||
)
|
||||
|
||||
|
||||
## Records that the path must use static presentation instead of animation.
|
||||
func mark_animation_static(normalized_relative_path: String) -> bool:
|
||||
return _mark_path(_static_animation_paths, normalized_relative_path)
|
||||
|
||||
|
||||
## Returns whether the path has a retained static-animation outcome.
|
||||
func is_animation_static(normalized_relative_path: String) -> bool:
|
||||
return not normalized_relative_path.is_empty() and _static_animation_paths.has(
|
||||
normalized_relative_path
|
||||
)
|
||||
|
||||
|
||||
## Returns detached path-only cache state for diagnostics and verification.
|
||||
func diagnostic_snapshot() -> Dictionary:
|
||||
return {
|
||||
"static_prototype_paths": _sorted_paths(_static_prototypes_by_path),
|
||||
"animated_prototype_paths": _sorted_paths(_animated_prototypes_by_path),
|
||||
"missing_model_paths": _sorted_paths(_missing_model_paths),
|
||||
"static_animation_paths": _sorted_paths(_static_animation_paths),
|
||||
}
|
||||
|
||||
|
||||
## Releases every retained prototype and clears positive and negative state.
|
||||
## Detached Nodes are freed synchronously; in-tree Nodes are queued for deletion.
|
||||
func clear_and_release() -> void:
|
||||
_release_prototypes(_static_prototypes_by_path)
|
||||
_release_prototypes(_animated_prototypes_by_path)
|
||||
_missing_model_paths.clear()
|
||||
_static_animation_paths.clear()
|
||||
|
||||
|
||||
func _find_valid_prototype(
|
||||
prototypes_by_path: Dictionary,
|
||||
normalized_relative_path: String) -> Node3D:
|
||||
if normalized_relative_path.is_empty():
|
||||
return null
|
||||
var prototype_variant: Variant = prototypes_by_path.get(normalized_relative_path)
|
||||
if not (prototype_variant is Node3D):
|
||||
return null
|
||||
var prototype := prototype_variant as Node3D
|
||||
return prototype if is_instance_valid(prototype) else null
|
||||
|
||||
|
||||
func _adopt_prototype(
|
||||
prototypes_by_path: Dictionary,
|
||||
normalized_relative_path: String,
|
||||
prototype: Node3D) -> Node3D:
|
||||
if normalized_relative_path.is_empty() or prototype == null or not is_instance_valid(prototype):
|
||||
return null
|
||||
var retained_prototype := _find_valid_prototype(
|
||||
prototypes_by_path,
|
||||
normalized_relative_path
|
||||
)
|
||||
if retained_prototype != null:
|
||||
if not is_same(retained_prototype, prototype):
|
||||
_release_prototype(prototype)
|
||||
return retained_prototype
|
||||
prototypes_by_path[normalized_relative_path] = prototype
|
||||
return prototype
|
||||
|
||||
|
||||
func _mark_path(paths: Dictionary, normalized_relative_path: String) -> bool:
|
||||
if normalized_relative_path.is_empty():
|
||||
return false
|
||||
paths[normalized_relative_path] = true
|
||||
return true
|
||||
|
||||
|
||||
func _release_prototypes(prototypes_by_path: Dictionary) -> void:
|
||||
for prototype_variant in prototypes_by_path.values():
|
||||
if prototype_variant is Node3D:
|
||||
_release_prototype(prototype_variant as Node3D)
|
||||
prototypes_by_path.clear()
|
||||
|
||||
|
||||
func _release_prototype(prototype: Node3D) -> void:
|
||||
if prototype == null or not is_instance_valid(prototype):
|
||||
return
|
||||
if prototype.is_inside_tree():
|
||||
prototype.queue_free()
|
||||
else:
|
||||
prototype.free()
|
||||
|
||||
|
||||
func _sorted_paths(paths: Dictionary) -> Array[String]:
|
||||
var result: Array[String] = []
|
||||
for path_variant in paths.keys():
|
||||
result.append(String(path_variant))
|
||||
result.sort()
|
||||
return result
|
||||
@@ -0,0 +1 @@
|
||||
uid://srnqsus8pddp
|
||||
Reference in New Issue
Block a user