@@ -1504,6 +1504,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
1504
1504
result .append (f"\t GDEXTENSION_CLASS({ class_name } , { inherits } )" )
1505
1505
result .append ("" )
1506
1506
1507
+ if is_singleton :
1508
+ result .append (f"\t static { class_name } *singleton;" )
1509
+ result .append ("" )
1510
+
1507
1511
result .append ("public:" )
1508
1512
result .append ("" )
1509
1513
@@ -1584,6 +1588,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
1584
1588
1585
1589
result .append ("\t }" )
1586
1590
result .append ("" )
1591
+
1592
+ if is_singleton :
1593
+ result .append (f"\t ~{ class_name } ();" )
1594
+ result .append ("" )
1595
+
1587
1596
result .append ("public:" )
1588
1597
1589
1598
# Special cases.
@@ -1733,6 +1742,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
1733
1742
1734
1743
result .append (f"#include <godot_cpp/classes/{ snake_class_name } .hpp>" )
1735
1744
result .append ("" )
1745
+ result .append ("#include <godot_cpp/core/class_db.hpp>" )
1736
1746
result .append ("#include <godot_cpp/core/engine_ptrcall.hpp>" )
1737
1747
result .append ("#include <godot_cpp/core/error_macros.hpp>" )
1738
1748
result .append ("" )
@@ -1747,9 +1757,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
1747
1757
result .append ("" )
1748
1758
1749
1759
if is_singleton :
1760
+ result .append (f"{ class_name } *{ class_name } ::singleton = nullptr;" )
1761
+ result .append ("" )
1750
1762
result .append (f"{ class_name } *{ class_name } ::get_singleton() {{" )
1751
1763
# We assume multi-threaded access is OK because each assignment will assign the same value every time
1752
- result .append (f"\t static { class_name } *singleton = nullptr;" )
1753
1764
result .append ("\t if (unlikely(singleton == nullptr)) {" )
1754
1765
result .append (
1755
1766
f"\t \t GDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({ class_name } ::get_class_static()._native_ptr());"
@@ -1763,11 +1774,22 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
1763
1774
result .append ("#ifdef DEBUG_ENABLED" )
1764
1775
result .append ("\t \t ERR_FAIL_NULL_V(singleton, nullptr);" )
1765
1776
result .append ("#endif // DEBUG_ENABLED" )
1777
+ result .append ("\t \t if (likely(singleton)) {" )
1778
+ result .append (f"\t \t \t ClassDB::_register_engine_singleton({ class_name } ::get_class_static(), singleton);" )
1779
+ result .append ("\t \t }" )
1766
1780
result .append ("\t }" )
1767
1781
result .append ("\t return singleton;" )
1768
1782
result .append ("}" )
1769
1783
result .append ("" )
1770
1784
1785
+ result .append (f"{ class_name } ::~{ class_name } () {{" )
1786
+ result .append ("\t if (singleton == this) {" )
1787
+ result .append (f"\t \t ClassDB::_unregister_engine_singleton({ class_name } ::get_class_static());" )
1788
+ result .append ("\t \t singleton = nullptr;" )
1789
+ result .append ("\t }" )
1790
+ result .append ("}" )
1791
+ result .append ("" )
1792
+
1771
1793
if "methods" in class_api :
1772
1794
for method in class_api ["methods" ]:
1773
1795
if method ["is_virtual" ]:
0 commit comments