feat(studio,stacking,animations,collections): M16 ModBison Studio, object stacking, model animations, and poly collections for MVP 2
checkpoint / checkpoint (push) Successful in 6m32s
checkpoint / checkpoint (push) Successful in 6m32s
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
class_name AssetCacheManager
|
||||
extends RefCounted
|
||||
## Manages client-side disk caching of downloaded 3D model assets and collections.
|
||||
## Caches assets locally under user://asset_cache/ to prevent duplicate network fetches.
|
||||
|
||||
const CACHE_DIR: String = "user://asset_cache"
|
||||
|
||||
static var _instance = null
|
||||
|
||||
|
||||
static func get_instance():
|
||||
if _instance == null:
|
||||
var script := load("res://scripts/studio/asset_cache_manager.gd")
|
||||
_instance = script.new()
|
||||
return _instance
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
_ensure_cache_dir()
|
||||
|
||||
|
||||
func _ensure_cache_dir() -> void:
|
||||
if not DirAccess.dir_exists_absolute(CACHE_DIR):
|
||||
DirAccess.make_dir_recursive_absolute(CACHE_DIR)
|
||||
|
||||
|
||||
func get_cache_path(asset_key: String) -> String:
|
||||
var clean_key := asset_key.replace("/", "_").replace("\\", "_").replace(":", "_")
|
||||
if not clean_key.ends_with(".glb") and not clean_key.ends_with(".gltf"):
|
||||
clean_key += ".glb"
|
||||
return "%s/%s" % [CACHE_DIR, clean_key]
|
||||
|
||||
|
||||
func has_cached(asset_key: String) -> bool:
|
||||
var p := get_cache_path(asset_key)
|
||||
return FileAccess.file_exists(p)
|
||||
|
||||
|
||||
func get_cached_path_if_exists(asset_key: String) -> String:
|
||||
var p := get_cache_path(asset_key)
|
||||
if FileAccess.file_exists(p):
|
||||
return p
|
||||
return ""
|
||||
|
||||
|
||||
func store_asset(asset_key: String, data: PackedByteArray) -> String:
|
||||
_ensure_cache_dir()
|
||||
var path := get_cache_path(asset_key)
|
||||
var fa := FileAccess.open(path, FileAccess.WRITE)
|
||||
if fa != null:
|
||||
fa.store_buffer(data)
|
||||
fa.close()
|
||||
return path
|
||||
return ""
|
||||
|
||||
|
||||
func read_asset(asset_key: String) -> PackedByteArray:
|
||||
var path := get_cache_path(asset_key)
|
||||
if not FileAccess.file_exists(path):
|
||||
return PackedByteArray()
|
||||
var fa := FileAccess.open(path, FileAccess.READ)
|
||||
if fa != null:
|
||||
var buf := fa.get_buffer(fa.get_length())
|
||||
fa.close()
|
||||
return buf
|
||||
return PackedByteArray()
|
||||
|
||||
|
||||
func load_model(asset_key: String) -> Node:
|
||||
var path := get_cached_path_if_exists(asset_key)
|
||||
if path == "":
|
||||
return null
|
||||
|
||||
if path.ends_with(".glb") or path.ends_with(".gltf"):
|
||||
var gltf := GLTFDocument.new()
|
||||
var state := GLTFState.new()
|
||||
var err := gltf.append_from_file(path, state)
|
||||
if err == OK:
|
||||
return gltf.generate_scene(state)
|
||||
elif ResourceLoader.exists(path):
|
||||
var res := load(path)
|
||||
if res is PackedScene:
|
||||
return (res as PackedScene).instantiate()
|
||||
|
||||
return null
|
||||
|
||||
|
||||
func get_cached_items() -> Array[String]:
|
||||
_ensure_cache_dir()
|
||||
var items: Array[String] = []
|
||||
var dir := DirAccess.open(CACHE_DIR)
|
||||
if dir != null:
|
||||
dir.list_dir_begin()
|
||||
var file_name := dir.get_next()
|
||||
while file_name != "":
|
||||
if not dir.current_is_dir() and not file_name.begins_with("."):
|
||||
items.append(file_name)
|
||||
file_name = dir.get_next()
|
||||
dir.list_dir_end()
|
||||
return items
|
||||
|
||||
|
||||
func clear_cache() -> int:
|
||||
_ensure_cache_dir()
|
||||
var count := 0
|
||||
var dir := DirAccess.open(CACHE_DIR)
|
||||
if dir != null:
|
||||
dir.list_dir_begin()
|
||||
var file_name := dir.get_next()
|
||||
while file_name != "":
|
||||
if not dir.current_is_dir():
|
||||
DirAccess.remove_absolute("%s/%s" % [CACHE_DIR, file_name])
|
||||
count += 1
|
||||
file_name = dir.get_next()
|
||||
dir.list_dir_end()
|
||||
return count
|
||||
Reference in New Issue
Block a user