Skip to content

Commit

Permalink
Implement project-wide node groups
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkMessiah committed Dec 19, 2023
1 parent 1f5d4a6 commit 958699a
Show file tree
Hide file tree
Showing 14 changed files with 1,564 additions and 644 deletions.
77 changes: 77 additions & 0 deletions core/config/project_settings.cpp
Expand Up @@ -281,6 +281,11 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
if (autoloads.has(node_name)) {
remove_autoload(node_name);
}
} else if (p_name.operator String().begins_with("global_group/")) {
String group_name = p_name.operator String().get_slice("/", 1);
if (global_groups.has(group_name)) {
remove_global_group(group_name);
}
}
} else {
if (p_name == CoreStringNames::get_singleton()->_custom_features) {
Expand Down Expand Up @@ -327,6 +332,9 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
autoload.path = path;
}
add_autoload(autoload);
} else if (p_name.operator String().begins_with("global_group/")) {
String group_name = p_name.operator String().get_slice("/", 1);
add_global_group(group_name, p_value);
}
}

Expand Down Expand Up @@ -674,6 +682,8 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo

Compression::gzip_level = GLOBAL_GET("compression/formats/gzip/compression_level");

load_scene_groups_cache();

project_loaded = err == OK;
return err;
}
Expand Down Expand Up @@ -1241,6 +1251,73 @@ ProjectSettings::AutoloadInfo ProjectSettings::get_autoload(const StringName &p_
return autoloads[p_name];
}

const HashMap<StringName, String> &ProjectSettings::get_global_groups_list() const {
return global_groups;
}

void ProjectSettings::add_global_group(const StringName &p_name, const String &p_description) {
ERR_FAIL_COND_MSG(p_name == StringName(), "Trying to add global group with no name.");
global_groups[p_name] = p_description;
}

void ProjectSettings::remove_global_group(const StringName &p_name) {
ERR_FAIL_COND_MSG(!global_groups.has(p_name), "Trying to remove non-existent global group.");
global_groups.erase(p_name);
}

bool ProjectSettings::has_global_group(const StringName &p_name) const {
return global_groups.has(p_name);
}

void ProjectSettings::remove_scene_groups_cache(const StringName &p_path) {
scene_groups_cache.erase(p_path);
}

void ProjectSettings::add_scene_groups_cache(const StringName &p_path, const HashSet<StringName> &p_cache) {
scene_groups_cache[p_path] = p_cache;
}

void ProjectSettings::save_scene_groups_cache() {
Ref<ConfigFile> cf;
cf.instantiate();
for (const KeyValue<StringName, HashSet<StringName>> &E : scene_groups_cache) {
if (E.value.is_empty()) {
continue;
}
Array list;
for (const StringName &group : E.value) {
list.push_back(group);
}
cf->set_value(E.key, "groups", list);
}
cf->save(get_scene_groups_cache_path());
}

String ProjectSettings::get_scene_groups_cache_path() const {
return get_project_data_path().path_join("scene_groups_cache.cfg");
}

void ProjectSettings::load_scene_groups_cache() {
Ref<ConfigFile> cf;
cf.instantiate();
if (cf->load(get_scene_groups_cache_path()) == OK) {
List<String> scene_paths;
cf->get_sections(&scene_paths);
for (const String &E : scene_paths) {
Array scene_groups = cf->get_value(E, "groups", Array());
HashSet<StringName> cache;
for (int i = 0; i < scene_groups.size(); ++i) {
cache.insert(scene_groups[i]);
}
add_scene_groups_cache(E, cache);
}
}
}

const HashMap<StringName, HashSet<StringName>> &ProjectSettings::get_scene_groups_cache() const {
return scene_groups_cache;
}

void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting);
ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting);
Expand Down
14 changes: 14 additions & 0 deletions core/config/project_settings.h
Expand Up @@ -106,6 +106,8 @@ class ProjectSettings : public Object {

LocalVector<String> hidden_prefixes;
HashMap<StringName, AutoloadInfo> autoloads;
HashMap<StringName, String> global_groups;
HashMap<StringName, HashSet<StringName>> scene_groups_cache;

Array global_class_list;
bool is_global_class_list_loaded = false;
Expand Down Expand Up @@ -208,6 +210,18 @@ class ProjectSettings : public Object {
bool has_autoload(const StringName &p_autoload) const;
AutoloadInfo get_autoload(const StringName &p_name) const;

const HashMap<StringName, String> &get_global_groups_list() const;
void add_global_group(const StringName &p_name, const String &p_description);
void remove_global_group(const StringName &p_name);
bool has_global_group(const StringName &p_name) const;

const HashMap<StringName, HashSet<StringName>> &get_scene_groups_cache() const;
void add_scene_groups_cache(const StringName &p_path, const HashSet<StringName> &p_cache);
void remove_scene_groups_cache(const StringName &p_path);
void save_scene_groups_cache();
String get_scene_groups_cache_path() const;
void load_scene_groups_cache();

ProjectSettings();
~ProjectSettings();
};
Expand Down
85 changes: 85 additions & 0 deletions editor/editor_file_system.cpp
Expand Up @@ -44,6 +44,7 @@
#include "editor/editor_paths.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_settings.h"
#include "scene/resources/packed_scene.h"

EditorFileSystem *EditorFileSystem::singleton = nullptr;
//the name is the version, to keep compatibility with different versions of Godot
Expand Down Expand Up @@ -615,6 +616,9 @@ bool EditorFileSystem::_update_scan_actions() {
if (ClassDB::is_parent_class(ia.new_file->type, SNAME("Script"))) {
_queue_update_script_class(ia.dir->get_file_path(idx));
}
if (ia.new_file->type == SNAME("PackedScene")) {
_queue_update_scene_groups(ia.dir->get_file_path(idx));
}

} break;
case ItemAction::ACTION_FILE_REMOVE: {
Expand All @@ -624,6 +628,9 @@ bool EditorFileSystem::_update_scan_actions() {
if (ClassDB::is_parent_class(ia.dir->files[idx]->type, SNAME("Script"))) {
_queue_update_script_class(ia.dir->get_file_path(idx));
}
if (ia.dir->files[idx]->type == SNAME("PackedScene")) {
_queue_update_scene_groups(ia.dir->get_file_path(idx));
}

_delete_internal_files(ia.dir->files[idx]->file);
memdelete(ia.dir->files[idx]);
Expand Down Expand Up @@ -662,6 +669,9 @@ bool EditorFileSystem::_update_scan_actions() {
if (ClassDB::is_parent_class(ia.dir->files[idx]->type, SNAME("Script"))) {
_queue_update_script_class(full_path);
}
if (ia.dir->files[idx]->type == SNAME("PackedScene")) {
_queue_update_scene_groups(full_path);
}

reloads.push_back(full_path);

Expand Down Expand Up @@ -732,6 +742,7 @@ void EditorFileSystem::scan() {
_update_scan_actions();
scanning = false;
_update_pending_script_classes();
_update_pending_scene_groups();
emit_signal(SNAME("filesystem_changed"));
emit_signal(SNAME("sources_changed"), sources_changed.size() > 0);
first_scan = false;
Expand Down Expand Up @@ -942,6 +953,9 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc
if (ClassDB::is_parent_class(fi->type, SNAME("Script"))) {
_queue_update_script_class(path);
}
if (fi->type == SNAME("PackedScene")) {
_queue_update_scene_groups(path);
}
}
}

Expand Down Expand Up @@ -1196,6 +1210,7 @@ void EditorFileSystem::scan_changes() {
_scan_fs_changes(filesystem, sp);
bool changed = _update_scan_actions();
_update_pending_script_classes();
_update_pending_scene_groups();
if (changed) {
emit_signal(SNAME("filesystem_changed"));
}
Expand Down Expand Up @@ -1262,6 +1277,7 @@ void EditorFileSystem::_notification(int p_what) {
}
bool changed = _update_scan_actions();
_update_pending_script_classes();
_update_pending_scene_groups();
if (changed) {
emit_signal(SNAME("filesystem_changed"));
}
Expand All @@ -1281,6 +1297,7 @@ void EditorFileSystem::_notification(int p_what) {
thread.wait_to_finish();
_update_scan_actions();
_update_pending_script_classes();
_update_pending_scene_groups();
emit_signal(SNAME("filesystem_changed"));
emit_signal(SNAME("sources_changed"), sources_changed.size() > 0);
first_scan = false;
Expand Down Expand Up @@ -1635,6 +1652,65 @@ void EditorFileSystem::_queue_update_script_class(const String &p_path) {
update_script_mutex.unlock();
}

void EditorFileSystem::_update_scene_groups() {
update_scene_mutex.lock();

for (const String &path : update_scene_paths) {
ProjectSettings::get_singleton()->remove_scene_groups_cache(path);

int index = -1;
EditorFileSystemDirectory *efd = find_file(path, &index);

if (!efd || index < 0) {
// The file was removed.
continue;
}

const HashSet<StringName> scene_groups = _get_scene_groups(path);
if (!scene_groups.is_empty()) {
ProjectSettings::get_singleton()->add_scene_groups_cache(path, scene_groups);
}
}

update_scene_paths.clear();
update_scene_mutex.unlock();

ProjectSettings::get_singleton()->save_scene_groups_cache();
}

void EditorFileSystem::_update_pending_scene_groups() {
if (!FileAccess::exists(ProjectSettings::get_singleton()->get_scene_groups_cache_path())) {
_get_all_scenes(get_filesystem(), update_scene_paths);
_update_scene_groups();
} else if (!update_scene_paths.is_empty()) {
_update_scene_groups();
}
}

void EditorFileSystem::_queue_update_scene_groups(const String &p_path) {
update_scene_mutex.lock();
update_scene_paths.insert(p_path);
update_scene_mutex.unlock();
}

void EditorFileSystem::_get_all_scenes(EditorFileSystemDirectory *p_dir, HashSet<String> &r_list) {
for (int i = 0; i < p_dir->get_file_count(); i++) {
if (p_dir->get_file_type(i) == SNAME("PackedScene")) {
r_list.insert(p_dir->get_file_path(i));
}
}

for (int i = 0; i < p_dir->get_subdir_count(); i++) {
_get_all_scenes(p_dir->get_subdir(i), r_list);
}
}

HashSet<StringName> EditorFileSystem::_get_scene_groups(const String &p_path) {
Ref<PackedScene> packed_scene = ResourceLoader::load(p_path);
ERR_FAIL_COND_V(packed_scene.is_null(), HashSet<StringName>());
return packed_scene->get_state()->get_all_groups();
}

void EditorFileSystem::update_file(const String &p_file) {
ERR_FAIL_COND(p_file.is_empty());
EditorFileSystemDirectory *fs = nullptr;
Expand All @@ -1658,12 +1734,16 @@ void EditorFileSystem::update_file(const String &p_file) {
if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Script"))) {
_queue_update_script_class(p_file);
}
if (fs->files[cpos]->type == SNAME("PackedScene")) {
_queue_update_scene_groups(p_file);
}

memdelete(fs->files[cpos]);
fs->files.remove_at(cpos);
}

_update_pending_script_classes();
_update_pending_scene_groups();
call_deferred(SNAME("emit_signal"), "filesystem_changed"); //update later
return;
}
Expand Down Expand Up @@ -1730,8 +1810,12 @@ void EditorFileSystem::update_file(const String &p_file) {
if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Script"))) {
_queue_update_script_class(p_file);
}
if (fs->files[cpos]->type == SNAME("PackedScene")) {
_queue_update_scene_groups(p_file);
}

_update_pending_script_classes();
_update_pending_scene_groups();
call_deferred(SNAME("emit_signal"), "filesystem_changed"); //update later
}

Expand Down Expand Up @@ -2341,6 +2425,7 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {

_save_filesystem_cache();
_update_pending_script_classes();
_update_pending_scene_groups();
importing = false;
if (!is_scanning()) {
emit_signal(SNAME("filesystem_changed"));
Expand Down
8 changes: 8 additions & 0 deletions editor/editor_file_system.h
Expand Up @@ -267,6 +267,14 @@ class EditorFileSystem : public Node {
void _update_script_classes();
void _update_pending_script_classes();

Mutex update_scene_mutex;
HashSet<String> update_scene_paths;
void _queue_update_scene_groups(const String &p_path);
void _update_scene_groups();
void _update_pending_scene_groups();
HashSet<StringName> _get_scene_groups(const String &p_path);
void _get_all_scenes(EditorFileSystemDirectory *p_dir, HashSet<String> &r_list);

String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const;

static Error _resource_import(const String &p_path);
Expand Down

0 comments on commit 958699a

Please sign in to comment.