extends LoadingScreen @export_dir var _spatial_shader_material_dir : String @export_file("*.tscn") var _cache_shaders_scene : String @export var _mesh : Mesh @export_group("Advanced") @export var _matching_extensions : Array[String] = [".tres", ".material", ".res"] @export var _ignore_subfolders : Array[String] = [".", ".."] @export var _shader_delay_timer : float = 0.1 var _loading_shader_cache : bool = false var _caching_progress : float = 0.0 : set(value): if value <= _caching_progress: return _caching_progress = value update_total_loading_progress() _reset_loading_stage() func can_load_shader_cache() -> bool: return not _spatial_shader_material_dir.is_empty() and \ not _cache_shaders_scene.is_empty() and \ SceneLoader.is_loading_scene(_cache_shaders_scene) func update_total_loading_progress() -> void: var partial_total := _scene_loading_progress if can_load_shader_cache(): partial_total += _caching_progress partial_total /= 2 _total_loading_progress = partial_total func _set_scene_loading_complete() -> void: super._set_scene_loading_complete() if can_load_shader_cache() and not _loading_shader_cache: _loading_shader_cache = true _show_all_draw_passes_once() if can_load_shader_cache() and _caching_progress < 1.0: return SceneLoader._background_loading = false SceneLoader.set_process(true) func _show_all_draw_passes_once() -> void: var all_materials := _traverse_folders(_spatial_shader_material_dir) var total_material_count := all_materials.size() var cached_material_count := 0 for material_path in all_materials: _load_material(material_path) cached_material_count += 1 _caching_progress = float(cached_material_count) / total_material_count if _shader_delay_timer > 0: await(get_tree().create_timer(_shader_delay_timer).timeout) func _traverse_folders(dir_path:String) -> PackedStringArray: var material_list:PackedStringArray = [] if not dir_path.ends_with("/"): dir_path += "/" var dir := DirAccess.open(dir_path) if not dir: push_error("failed to access the path ", dir_path) return [] if dir.list_dir_begin() != OK: push_error("failed to access the path ", dir_path) return [] var file_name := dir.get_next() while file_name != "": if not dir.current_is_dir(): var matches : bool = false for extension in _matching_extensions: if file_name.ends_with(extension): matches = true break if matches: material_list.append(dir_path + file_name) else: var subfolder_name := file_name if not subfolder_name in _ignore_subfolders: material_list.append_array(_traverse_folders(dir_path + subfolder_name)) file_name = dir.get_next() return material_list func _load_material(path:String) -> void: var material_shower := MeshInstance3D.new() material_shower.mesh = _mesh var material := ResourceLoader.load(path) as Material material_shower.set_surface_override_material(0, material) %SpatialShaderTypeCaches.add_child(material_shower) func _ready() -> void: SceneLoader._background_loading = true