@@ -915,14 +915,43 @@ GDScript::GDScript() :
915
915
#endif
916
916
}
917
917
918
+ void GDScript::_save_orphaned_subclasses () {
919
+ struct ClassRefWithName {
920
+ ObjectID id;
921
+ String fully_qualified_name;
922
+ };
923
+ Vector<ClassRefWithName> weak_subclasses;
924
+ // collect subclasses ObjectID and name
925
+ for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front (); E; E = E->next ()) {
926
+ E->get ()->_owner = NULL ; // bye, you are no longer owned cause I died
927
+ ClassRefWithName subclass;
928
+ subclass.id = E->get ()->get_instance_id ();
929
+ subclass.fully_qualified_name = E->get ()->fully_qualified_name ;
930
+ weak_subclasses.push_back (subclass);
931
+ }
932
+
933
+ // clear subclasses to allow unused subclasses to be deleted
934
+ subclasses.clear ();
935
+ // subclasses are also held by constants, clear those as well
936
+ constants.clear ();
937
+
938
+ // keep orphan subclass only for subclasses that are still in use
939
+ for (int i = 0 ; i < weak_subclasses.size (); i++) {
940
+ ClassRefWithName subclass = weak_subclasses[i];
941
+ Object *obj = ObjectDB::get_instance (subclass.id );
942
+ if (!obj)
943
+ continue ;
944
+ // subclass is not released
945
+ GDScriptLanguage::get_singleton ()->add_orphan_subclass (subclass.fully_qualified_name , subclass.id );
946
+ }
947
+ }
948
+
918
949
GDScript::~GDScript () {
919
950
for (Map<StringName, GDScriptFunction *>::Element *E = member_functions.front (); E; E = E->next ()) {
920
951
memdelete (E->get ());
921
952
}
922
953
923
- for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front (); E; E = E->next ()) {
924
- E->get ()->_owner = NULL ; // bye, you are no longer owned cause I died
925
- }
954
+ _save_orphaned_subclasses ();
926
955
927
956
#ifdef DEBUG_ENABLED
928
957
if (GDScriptLanguage::get_singleton ()->lock ) {
@@ -2176,6 +2205,22 @@ GDScriptLanguage::~GDScriptLanguage() {
2176
2205
singleton = NULL ;
2177
2206
}
2178
2207
2208
+ void GDScriptLanguage::add_orphan_subclass (const String &p_qualified_name, const ObjectID &p_subclass) {
2209
+ orphan_subclasses[p_qualified_name] = p_subclass;
2210
+ }
2211
+
2212
+ Ref<GDScript> GDScriptLanguage::get_orphan_subclass (const String &p_qualified_name) {
2213
+ Map<String, ObjectID>::Element *orphan_subclass_element = orphan_subclasses.find (p_qualified_name);
2214
+ if (!orphan_subclass_element)
2215
+ return Ref<GDScript>();
2216
+ ObjectID orphan_subclass = orphan_subclass_element->get ();
2217
+ Object *obj = ObjectDB::get_instance (orphan_subclass);
2218
+ orphan_subclasses.erase (orphan_subclass_element);
2219
+ if (!obj)
2220
+ return Ref<GDScript>();
2221
+ return Ref<GDScript>(Object::cast_to<GDScript>(obj));
2222
+ }
2223
+
2179
2224
/* ************** RESOURCE ***************/
2180
2225
2181
2226
RES ResourceFormatLoaderGDScript::load (const String &p_path, const String &p_original_path, Error *r_error) {
0 commit comments