Skip to content

Commit

Permalink
Preload scripts for registering system and component names
Browse files Browse the repository at this point in the history
  • Loading branch information
Beliar83 committed Feb 22, 2023
1 parent e0c8e08 commit eac4c95
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 13 deletions.
71 changes: 58 additions & 13 deletions ecs.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@

#include "ecs.h"
#include <core/config/project_settings.h>
#include <core/io/dir_access.h>
#include <modules/gdscript/gdscript_parser.h>

#include "components/dynamic_component.h"
#include "core/object/message_queue.h"
Expand Down Expand Up @@ -159,6 +162,43 @@ ECS::ECS() :
}
}

void get_script_files(const String &p_path, Vector<String> &scripts) {
for (const auto &directory : DirAccess::get_directories_at(p_path)) {
get_script_files(p_path.path_join(directory), scripts);
}
for (const auto &file : DirAccess::get_files_at(p_path)) {
auto file_path = p_path.path_join(file);
if (ResourceLoader::get_resource_type(file_path) == "GDScript") {
scripts.push_back(file_path);
}
}
}

void ECS::preload_scripts() {
if (Engine::get_singleton()->is_project_manager_hint()) {
return;
}

Vector<String> scripts;

get_script_files("res://", scripts);

for (const auto &script : scripts) {
auto code = FileAccess::get_file_as_string(script);
GDScriptParser parser;
if (parser.parse(code, script, false) == OK) {
auto tree = parser.get_tree();
if (tree->extends.has("System")) {
register_dynamic_system(script.get_file());
}

if (tree->extends.has("Component")) {
register_or_get_id_for_component_name(script.get_file());
}
}
}
}

ECS::~ECS() {
}

Expand Down Expand Up @@ -1041,11 +1081,7 @@ const LocalVector<godex::component_id> &ECS::get_spawnable_components(godex::spa
return spawners_info[p_spawner].components;
}

uint32_t ECS::register_or_update_script_component(
const StringName &p_name,
const LocalVector<ScriptProperty> &p_properties,
StorageType p_storage_type,
Vector<StringName> p_spawners) {
uint32_t ECS::register_or_get_id_for_component_name(const StringName &p_name) {
godex::component_id id = get_component_id(p_name);
DynamicComponentInfo *info;

Expand All @@ -1058,12 +1094,25 @@ uint32_t ECS::register_or_update_script_component(
components.push_back(p_name);
components_info.push_back(ComponentInfo());
components_info[id].dynamic_component_info = info;
} else {
// This is an old component, verify is a script component.
ERR_FAIL_COND_V_MSG(components_info[id].dynamic_component_info == nullptr, godex::COMPONENT_NONE, "This component " + p_name + " is not a script component and can't be updated. Your component must be an unique name.");
info = components_info[id].dynamic_component_info;

// Add a new scripting constant, for fast and easy `component` access.
ClassDB::bind_integer_constant(get_class_static(), StringName(), String(p_name).replace(".", "_"), id);
print_line("ComponentScript: " + p_name + " registered with ID: " + itos(id));
}

return id;
}

uint32_t ECS::register_or_update_script_component(
const StringName &p_name,
const LocalVector<ScriptProperty> &p_properties,
StorageType p_storage_type,
Vector<StringName> p_spawners) {
godex::component_id id = register_or_get_id_for_component_name(p_name);
DynamicComponentInfo *info;
ERR_FAIL_COND_V_MSG(components_info[id].dynamic_component_info == nullptr, godex::COMPONENT_NONE, "This component " + p_name + " is not a script component and can't be updated. Your component must be an unique name.");
info = components_info[id].dynamic_component_info;

info->property_map.resize(p_properties.size());
info->properties.resize(p_properties.size());
info->defaults.resize(p_properties.size());
Expand Down Expand Up @@ -1115,10 +1164,6 @@ uint32_t ECS::register_or_update_script_component(
spawners_info[spawner].components.push_back(info->component_id);
}

// Add a new scripting constant, for fast and easy `component` access.
ClassDB::bind_integer_constant(get_class_static(), StringName(), String(p_name).replace(".", "_"), id);
print_line("ComponentScript: " + p_name + " registered with ID: " + itos(id));

return id;
}

Expand Down
3 changes: 3 additions & 0 deletions ecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ class ECS : public Object {
template <class C>
static void register_component(StorageBase *(*create_storage)());

static uint32_t register_or_get_id_for_component_name(const StringName &p_name);
static uint32_t register_or_update_script_component(const StringName &p_name, const LocalVector<ScriptProperty> &p_properties, StorageType p_storage_type, Vector<StringName> p_spawners);

static uint32_t get_components_count();
Expand Down Expand Up @@ -488,6 +489,8 @@ class ECS : public Object {
/// time, making the pipeline switch immediate.
static void system_set_active_system(godex::system_id p_id, uint8_t *p_mem, bool p_active);

static void preload_scripts();

private:
static void clear_emitters_for_system(godex::system_id p_id);

Expand Down
1 change: 1 addition & 0 deletions modules/godot/nodes/script_ecs.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "script_ecs.h"
#include <modules/gdscript/gdscript_parser.h>

#include "../../../ecs.h"
#include "../../../systems/dynamic_system.h"
Expand Down
2 changes: 2 additions & 0 deletions modules/godot/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ void initialize_godot_module(ModuleInitializationLevel p_level) {

ClassDB::register_class<SharedComponentResource>();

ECS::preload_scripts();

memnew(ScriptEcs());

} else if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
Expand Down

0 comments on commit eac4c95

Please sign in to comment.