90 lines
2.4 KiB
GDScript
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
|