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