1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

Keep a weak reference to orphan subclasses to reuse on class reload

This commit is contained in:
ChibiDenDen
2020-01-14 01:19:37 +02:00
parent 3d88a7bb22
commit 86aa12e806
3 changed files with 63 additions and 5 deletions

View File

@@ -915,14 +915,43 @@ GDScript::GDScript() :
#endif
}
void GDScript::_save_orphaned_subclasses() {
struct ClassRefWithName {
ObjectID id;
String fully_qualified_name;
};
Vector<ClassRefWithName> weak_subclasses;
// collect subclasses ObjectID and name
for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front(); E; E = E->next()) {
E->get()->_owner = NULL; //bye, you are no longer owned cause I died
ClassRefWithName subclass;
subclass.id = E->get()->get_instance_id();
subclass.fully_qualified_name = E->get()->fully_qualified_name;
weak_subclasses.push_back(subclass);
}
// clear subclasses to allow unused subclasses to be deleted
subclasses.clear();
// subclasses are also held by constants, clear those as well
constants.clear();
// keep orphan subclass only for subclasses that are still in use
for (int i = 0; i < weak_subclasses.size(); i++) {
ClassRefWithName subclass = weak_subclasses[i];
Object *obj = ObjectDB::get_instance(subclass.id);
if (!obj)
continue;
// subclass is not released
GDScriptLanguage::get_singleton()->add_orphan_subclass(subclass.fully_qualified_name, subclass.id);
}
}
GDScript::~GDScript() {
for (Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
memdelete(E->get());
}
for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front(); E; E = E->next()) {
E->get()->_owner = NULL; //bye, you are no longer owned cause I died
}
_save_orphaned_subclasses();
#ifdef DEBUG_ENABLED
if (GDScriptLanguage::get_singleton()->lock) {
@@ -2176,6 +2205,22 @@ GDScriptLanguage::~GDScriptLanguage() {
singleton = NULL;
}
void GDScriptLanguage::add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass) {
orphan_subclasses[p_qualified_name] = p_subclass;
}
Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_name) {
Map<String, ObjectID>::Element *orphan_subclass_element = orphan_subclasses.find(p_qualified_name);
if (!orphan_subclass_element)
return Ref<GDScript>();
ObjectID orphan_subclass = orphan_subclass_element->get();
Object *obj = ObjectDB::get_instance(orphan_subclass);
orphan_subclasses.erase(orphan_subclass_element);
if (!obj)
return Ref<GDScript>();
return Ref<GDScript>(Object::cast_to<GDScript>(obj));
}
/*************** RESOURCE ***************/
RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error) {