hy-farm/godot/FarmGodot/scripts/resources/atlas_texture_cache.gd
2026-05-29 19:54:56 +08:00

90 lines
2.4 KiB
GDScript

class_name AtlasTextureCache
extends RefCounted
var _textures: Dictionary = {}
var _atlases: Dictionary = {}
var _frame_regions: Dictionary = {}
func get_region(atlas_path: String, region_name: String) -> Texture2D:
return get_atlas_texture(atlas_path, TextureRegionCatalog.region_for(atlas_path, region_name))
func get_frame(atlas_path: String, frame_name: String) -> Texture2D:
return get_atlas_texture(atlas_path, frame_region(atlas_path, frame_name))
func get_atlas_texture(atlas_path: String, region: Rect2) -> Texture2D:
var cache_key := "%s:%s:%s:%s:%s" % [
atlas_path,
region.position.x,
region.position.y,
region.size.x,
region.size.y
]
if _textures.has(cache_key):
return _textures[cache_key]
var atlas := _load_atlas(atlas_path)
var texture := AtlasTexture.new()
texture.atlas = atlas
texture.region = region
_textures[cache_key] = texture
return texture
func preload_group(atlas_path: String, region_names: Array[String]) -> void:
for region_name in region_names:
get_region(atlas_path, region_name)
func clear_unused() -> void:
_textures.clear()
func frame_region(atlas_path: String, frame_name: String) -> Rect2:
var catalog := _load_frame_catalog(atlas_path)
if catalog.is_empty():
return Rect2(0, 0, 1, 1)
var frame = catalog.get(frame_name)
if frame == null and not frame_name.ends_with("_png"):
frame = catalog.get("%s_png" % frame_name)
if not frame is Dictionary:
return Rect2(0, 0, 1, 1)
return Rect2(
float(frame.get("x", 0)),
float(frame.get("y", 0)),
float(frame.get("w", frame.get("width", 1))),
float(frame.get("h", frame.get("height", 1)))
)
func _load_atlas(atlas_path: String) -> Texture2D:
if _atlases.has(atlas_path):
return _atlases[atlas_path]
var atlas := load(atlas_path) as Texture2D
_atlases[atlas_path] = atlas
return atlas
func _load_frame_catalog(atlas_path: String) -> Dictionary:
if _frame_regions.has(atlas_path):
return _frame_regions[atlas_path]
var json_path := "%s.json" % atlas_path.get_basename()
var file := FileAccess.open(json_path, FileAccess.READ)
if file == null:
_frame_regions[atlas_path] = {}
return {}
var parsed = JSON.parse_string(file.get_as_text())
if not parsed is Dictionary:
_frame_regions[atlas_path] = {}
return {}
var frames = parsed.get("frames", {})
if not frames is Dictionary:
frames = {}
_frame_regions[atlas_path] = frames
return frames