Path: blob/master/editor/file_system/editor_file_system.h
20786 views
/**************************************************************************/1/* editor_file_system.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "core/io/dir_access.h"33#include "core/io/resource_importer.h"34#include "core/io/resource_loader.h"35#include "core/os/thread.h"36#include "core/os/thread_safe.h"37#include "core/templates/hash_set.h"38#include "core/templates/safe_refcount.h"39#include "scene/main/node.h"4041class FileAccess;4243struct EditorProgressBG;44class EditorFileSystemDirectory : public Object {45GDCLASS(EditorFileSystemDirectory, Object);4647String name;48uint64_t modified_time;49bool verified = false; //used for checking changes5051EditorFileSystemDirectory *parent = nullptr;52Vector<EditorFileSystemDirectory *> subdirs;5354struct FileInfo {55String file;56StringName type;57StringName resource_script_class; // If any resource has script with a global class name, its found here.58ResourceUID::ID uid = ResourceUID::INVALID_ID;59uint64_t modified_time = 0;60uint64_t import_modified_time = 0;61String import_md5;62Vector<String> import_dest_paths;63bool import_valid = false;64String import_group_file;65Vector<String> deps;66bool verified = false; //used for checking changes67// This is for script resources only.68struct ScriptClassInfo {69String name;70String extends;71String icon_path;72bool is_abstract = false;73bool is_tool = false;74};75ScriptClassInfo class_info;76};7778Vector<FileInfo *> files;7980static void _bind_methods();8182friend class EditorFileSystem;8384public:85String get_name();86String get_path() const;8788int get_subdir_count() const;89EditorFileSystemDirectory *get_subdir(int p_idx);90int get_file_count() const;91String get_file(int p_idx) const;92String get_file_path(int p_idx) const;93ResourceUID::ID get_file_uid(int p_idx) const;94StringName get_file_type(int p_idx) const;95StringName get_file_resource_script_class(int p_idx) const;96Vector<String> get_file_deps(int p_idx) const;97bool get_file_import_is_valid(int p_idx) const;98uint64_t get_file_modified_time(int p_idx) const;99uint64_t get_file_import_modified_time(int p_idx) const;100String get_file_script_class_name(int p_idx) const; //used for scripts101String get_file_script_class_extends(int p_idx) const; //used for scripts102String get_file_script_class_icon_path(int p_idx) const; //used for scripts103String get_file_icon_path(int p_idx) const; //used for FileSystemDock104105EditorFileSystemDirectory *get_parent();106107int find_file_index(const String &p_file) const;108int find_dir_index(const String &p_dir) const;109110void force_update();111112EditorFileSystemDirectory();113~EditorFileSystemDirectory();114};115116class EditorFileSystemImportFormatSupportQuery : public RefCounted {117GDCLASS(EditorFileSystemImportFormatSupportQuery, RefCounted);118119protected:120GDVIRTUAL0RC_REQUIRED(bool, _is_active)121GDVIRTUAL0RC_REQUIRED(Vector<String>, _get_file_extensions)122GDVIRTUAL0RC_REQUIRED(bool, _query)123static void _bind_methods() {124GDVIRTUAL_BIND(_is_active);125GDVIRTUAL_BIND(_get_file_extensions);126GDVIRTUAL_BIND(_query);127}128129public:130virtual bool is_active() const {131bool ret = false;132GDVIRTUAL_CALL(_is_active, ret);133return ret;134}135virtual Vector<String> get_file_extensions() const {136Vector<String> ret;137GDVIRTUAL_CALL(_get_file_extensions, ret);138return ret;139}140virtual bool query() {141bool ret = false;142GDVIRTUAL_CALL(_query, ret);143return ret;144}145};146147class EditorFileSystem : public Node {148GDCLASS(EditorFileSystem, Node);149150_THREAD_SAFE_CLASS_151152struct ItemAction {153enum Action {154ACTION_NONE,155ACTION_DIR_ADD,156ACTION_DIR_REMOVE,157ACTION_FILE_ADD,158ACTION_FILE_REMOVE,159ACTION_FILE_TEST_REIMPORT,160ACTION_FILE_RELOAD161};162163Action action = ACTION_NONE;164EditorFileSystemDirectory *dir = nullptr;165String file;166EditorFileSystemDirectory *new_dir = nullptr;167EditorFileSystemDirectory::FileInfo *new_file = nullptr;168};169170struct ScannedDirectory {171String name;172String full_path;173Vector<ScannedDirectory *> subdirs;174List<String> files;175176~ScannedDirectory();177};178179bool use_threads = false;180Thread thread;181static void _thread_func(void *_userdata);182183EditorFileSystemDirectory *new_filesystem = nullptr;184static ScannedDirectory *first_scan_root_dir;185186bool filesystem_changed_queued = false;187bool scanning = false;188bool importing = false;189bool first_scan = true;190bool scan_changes_pending = false;191float scan_total;192String filesystem_settings_version_for_import;193bool revalidate_import_files = false;194static int nb_files_total;195196void _notify_filesystem_changed();197void _scan_filesystem();198void _first_scan_filesystem();199void _first_scan_process_scripts(const ScannedDirectory *p_scan_dir, List<String> &p_gdextension_extensions, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions);200201static void _scan_for_uid_directory(const ScannedDirectory *p_scan_dir, const HashSet<String> &p_import_extensions);202203static void _load_first_scan_root_dir();204205HashSet<String> late_update_files;206207void _save_late_updated_files();208209EditorFileSystemDirectory *filesystem = nullptr;210211static EditorFileSystem *singleton;212213using ScriptClassInfo = EditorFileSystemDirectory::FileInfo::ScriptClassInfo;214215/* Used for reading the filesystem cache file */216struct FileCache {217StringName type;218String resource_script_class;219ResourceUID::ID uid = ResourceUID::INVALID_ID;220uint64_t modification_time = 0;221uint64_t import_modification_time = 0;222String import_md5;223Vector<String> import_dest_paths;224Vector<String> deps;225bool import_valid = false;226String import_group_file;227ScriptClassInfo class_info;228};229230HashMap<String, FileCache> file_cache;231HashSet<String> dep_update_list;232233struct ScanProgress {234float hi = 0;235int current = 0;236EditorProgressBG *progress = nullptr;237void increment();238};239240struct DirectoryComparator {241bool operator()(const EditorFileSystemDirectory *p_a, const EditorFileSystemDirectory *p_b) const {242return p_a->name.filenocasecmp_to(p_b->name) < 0;243}244};245246void _save_filesystem_cache();247void _save_filesystem_cache(EditorFileSystemDirectory *p_dir, Ref<FileAccess> p_file);248249bool _find_file(const String &p_file, EditorFileSystemDirectory **r_d, int &r_file_pos) const;250251void _scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanProgress &p_progress, bool p_recursive = true);252253void _delete_internal_files(const String &p_file);254int _insert_actions_delete_files_directory(EditorFileSystemDirectory *p_dir);255256HashSet<String> textfile_extensions;257HashSet<String> other_file_extensions;258HashSet<String> valid_extensions;259HashSet<String> import_extensions;260261static int _scan_new_dir(ScannedDirectory *p_dir, Ref<DirAccess> &da);262void _process_file_system(const ScannedDirectory *p_scan_dir, EditorFileSystemDirectory *p_dir, ScanProgress &p_progress, HashSet<String> *p_processed_files);263264Thread thread_sources;265bool scanning_changes = false;266SafeFlag scanning_changes_done;267268static void _thread_func_sources(void *_userdata);269270List<String> sources_changed;271List<ItemAction> scan_actions;272273bool _update_scan_actions();274275void _update_extensions();276277Error _reimport_file(const String &p_file, const HashMap<StringName, Variant> &p_custom_options = HashMap<StringName, Variant>(), const String &p_custom_importer = String(), Variant *generator_parameters = nullptr, bool p_update_file_system = true);278Error _reimport_group(const String &p_group_file, const Vector<String> &p_files);279280bool _test_for_reimport(const String &p_path, const String &p_expected_import_md5);281bool _is_test_for_reimport_needed(const String &p_path, uint64_t p_last_modification_time, uint64_t p_modification_time, uint64_t p_last_import_modification_time, uint64_t p_import_modification_time, const Vector<String> &p_import_dest_paths);282bool _can_import_file(const String &p_path);283Vector<String> _get_import_dest_paths(const String &p_path);284285bool reimport_on_missing_imported_files;286287Vector<String> _get_dependencies(const String &p_path);288289struct ImportFile {290String path;291String importer;292bool threaded = false;293int order = 0;294bool operator<(const ImportFile &p_if) const {295return order == p_if.order ? (importer < p_if.importer) : (order < p_if.order);296}297};298299struct ScriptClassInfoUpdate : public ScriptClassInfo {300StringName type;301ScriptClassInfoUpdate() = default;302explicit ScriptClassInfoUpdate(const ScriptClassInfo &p_info) :303ScriptClassInfo(p_info) {}304static ScriptClassInfoUpdate from_file_info(const EditorFileSystemDirectory::FileInfo *p_fi) {305ScriptClassInfoUpdate update;306update.type = p_fi->type;307update.name = p_fi->class_info.name;308update.extends = p_fi->class_info.extends;309update.icon_path = p_fi->class_info.icon_path;310update.is_abstract = p_fi->class_info.is_abstract;311update.is_tool = p_fi->class_info.is_tool;312return update;313}314};315316Mutex update_script_mutex;317HashMap<String, ScriptClassInfoUpdate> update_script_paths;318HashSet<String> update_script_paths_documentation;319void _queue_update_script_class(const String &p_path, const ScriptClassInfoUpdate &p_script_update);320void _update_script_classes();321void _update_script_documentation();322void _process_update_pending();323void _process_removed_files(const HashSet<String> &p_processed_files);324bool _should_reload_script(const String &p_path);325326Mutex update_scene_mutex;327HashSet<String> update_scene_paths;328void _queue_update_scene_groups(const String &p_path);329void _update_scene_groups();330void _update_pending_scene_groups();331void _get_all_scenes(EditorFileSystemDirectory *p_dir, HashSet<String> &r_list);332333ScriptClassInfo _get_global_script_class(const String &p_type, const String &p_path) const;334335static Error _resource_import(const String &p_path);336static Ref<Resource> _load_resource_on_startup(ResourceFormatImporter *p_importer, const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, ResourceFormatLoader::CacheMode p_cache_mode);337338bool using_fat32_or_exfat; // Workaround for projects in FAT32 or exFAT filesystem (pendrives, most of the time)339340void _find_group_files(EditorFileSystemDirectory *efd, HashMap<String, Vector<String>> &group_files, HashSet<String> &groups_to_reimport);341342void _move_group_files(EditorFileSystemDirectory *efd, const String &p_group_file, const String &p_new_location);343344HashSet<String> group_file_cache;345HashMap<String, String> file_icon_cache;346347bool refresh_queued = false;348HashSet<ObjectID> folders_to_sort;349350Error _copy_file(const String &p_from, const String &p_to);351bool _copy_directory(const String &p_from, const String &p_to, HashMap<String, String> *p_files);352void _queue_refresh_filesystem();353void _refresh_filesystem();354355struct ImportThreadData {356const ImportFile *reimport_files;357int reimport_from;358Semaphore *imported_sem = nullptr;359};360361void _reimport_thread(uint32_t p_index, ImportThreadData *p_import_data);362363static ResourceUID::ID _resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate);364365bool _scan_extensions();366bool _scan_import_support(const Vector<String> &reimports);367368Vector<Ref<EditorFileSystemImportFormatSupportQuery>> import_support_queries;369370void _update_file_icon_path(EditorFileSystemDirectory::FileInfo *file_info);371void _update_files_icon_path(EditorFileSystemDirectory *edp = nullptr);372bool _remove_invalid_global_class_names(const HashSet<String> &p_existing_class_names);373String _get_file_by_class_name(EditorFileSystemDirectory *p_dir, const String &p_class_name, EditorFileSystemDirectory::FileInfo *&r_file_info);374375void _register_global_class_script(const String &p_search_path, const String &p_target_path, const ScriptClassInfoUpdate &p_script_update);376377protected:378void _notification(int p_what);379static void _bind_methods();380381public:382static EditorFileSystem *get_singleton() { return singleton; }383384EditorFileSystemDirectory *get_filesystem();385bool is_scanning() const;386bool is_importing() const { return importing; }387bool doing_first_scan() const { return first_scan; }388float get_scanning_progress() const;389void scan();390void scan_changes();391void update_file(const String &p_file);392void update_files(const Vector<String> &p_script_paths);393HashSet<String> get_valid_extensions() const;394void register_global_class_script(const String &p_search_path, const String &p_target_path);395396EditorFileSystemDirectory *get_filesystem_path(const String &p_path);397String get_file_type(const String &p_file) const;398EditorFileSystemDirectory *find_file(const String &p_file, int *r_index) const;399ResourceUID::ID get_file_uid(const String &p_path) const;400401void reimport_files(const Vector<String> &p_files);402Error reimport_append(const String &p_file, const HashMap<StringName, Variant> &p_custom_options, const String &p_custom_importer, Variant p_generator_parameters);403404void reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const HashMap<StringName, Variant> &p_custom_params);405406bool is_group_file(const String &p_path) const;407void move_group_file(const String &p_path, const String &p_new_path);408409Error make_dir_recursive(const String &p_path, const String &p_base_path = String());410Error copy_file(const String &p_from, const String &p_to);411Error copy_directory(const String &p_from, const String &p_to);412413static bool _should_skip_directory(const String &p_path);414415static void scan_for_uid();416417void add_import_format_support_query(Ref<EditorFileSystemImportFormatSupportQuery> p_query);418void remove_import_format_support_query(Ref<EditorFileSystemImportFormatSupportQuery> p_query);419EditorFileSystem();420~EditorFileSystem();421};422423424