diff --git a/SConstruct b/SConstruct index c7e1f8e5..61c1ff6c 100644 --- a/SConstruct +++ b/SConstruct @@ -158,6 +158,14 @@ setup_options(env, args) setup_defines_and_flags(env, additional_src) generate_sources_for_resources(env, additional_src) +scons_cache_path = os.environ.get("SCONS_CACHE") +if scons_cache_path is None: + # store all obj's in a dedicated folder + env["SHOBJPREFIX"] = "#obj/" +else: + env.CacheDir(scons_cache_path) + env.Decider("MD5") + extra_tags = "" if "release" in env["target"] and env["force_enabled_dd3d"]: extra_tags += ".enabled" diff --git a/dev_build_godot_cpp.bat b/dev_build_godot_cpp.bat index 90f886ff..a618cef7 100644 --- a/dev_build_godot_cpp.bat +++ b/dev_build_godot_cpp.bat @@ -1,11 +1,6 @@ -cd godot-cpp -::set api=custom_api_file="../api.json" -set api= +scons apply_patches -git apply --ignore-space-change --ignore-whitespace ../patches/godot_cpp_exclude_unused_classes.patch -git apply --ignore-space-change --ignore-whitespace ../patches/unity_build.patch -git apply --ignore-space-change --ignore-whitespace ../patches/web_threads.patch -::git apply --ignore-space-change --ignore-whitespace ../patches/debug_string.patch +cd godot-cpp title win x64 debug dev scons platform=windows target=editor arch=x86_64 dev_build=yes %api% generate_bindings=yes @@ -18,11 +13,3 @@ if errorlevel 1 ( echo Failed to generate and compile debug godot-cpp source cod title win x64 scons platform=windows target=template_release arch=x86_64 debug_symbols=no %api% if errorlevel 1 ( echo Failed to compile Windows godot-cpp for x64. Code: %errorlevel% && exit /b %errorlevel% ) - -title android arm64v8 debug -scons platform=android target=template_debug arch=arm64v8 ANDROID_HOME="" %api% -if errorlevel 1 ( echo Failed to compile debug Android godot-cpp for arm64v8. Code: %errorlevel% && exit /b %errorlevel% ) - -title android arm64v8 -scons platform=android target=template_release arch=arm64v8 ANDROID_HOME="" %api% -if errorlevel 1 ( echo Failed to compile Android godot-cpp for arm64v8. Code: %errorlevel% && exit /b %errorlevel% ) diff --git a/lib_utils.py b/lib_utils.py index 7b65e537..8b42a9a6 100644 --- a/lib_utils.py +++ b/lib_utils.py @@ -7,34 +7,41 @@ import os, json, re -def get_sources(src: list, src_folder: str, lib_name: str = "unity_"): - res = [os.path.join(src_folder, file) for file in src] +def get_sources(src: list, src_folder: str = "", lib_name: str = "unity_"): + if len(src_folder): + res = [os.path.join(src_folder, file) for file in src] + else: + res = src.copy() res = unity_tools.generate_unity_build(res, lib_name + "_") return res -def get_library_object(env: SConsEnvironment, project_name: str, lib_name: str, extra_tags: str, output_path: str, src_folder: str, additional_src: list) -> str: +def get_library_object( + other_env: SConsEnvironment, + project_name: str, + lib_name: str, + extra_tags: str, + output_path: str, + src_folder: str, + additional_src: list, +) -> str: + env = other_env.Clone() env.Append(CPPPATH=src_folder) src = [] with open(src_folder + "/default_sources.json") as f: src = json.load(f) - scons_cache_path = os.environ.get("SCONS_CACHE") - if scons_cache_path is None: - # store all obj's in a dedicated folder - env["SHOBJPREFIX"] = "#obj/" - else: - env.CacheDir(scons_cache_path) - env.Decider("MD5") - # some additional tags if needed additional_tags = "" if env["platform"] == "web" and env.get("threads", True): additional_tags = ".threads" - lib_filename = "lib{}.{}.{}.{}{}".format(lib_name, env["platform"], env["target"], env["arch"], additional_tags + extra_tags) + env["SHLIBSUFFIX"] + lib_filename = ( + "lib{}.{}.{}.{}{}".format(lib_name, env["platform"], env["target"], env["arch"], additional_tags + extra_tags) + + env["SHLIBSUFFIX"] + ) if env["platform"] == "macos": generate_framework_folder(env, project_name, lib_name, lib_filename, output_path) @@ -43,10 +50,7 @@ def get_library_object(env: SConsEnvironment, project_name: str, lib_name: str, lib_filename = os.path.join(output_path, lib_filename) env.Default( - env.SharedLibrary( - target=env.File(lib_filename), - source=get_sources(additional_src + src, src_folder, lib_name) - ) + env.SharedLibrary(target=env.File(lib_filename), source=get_sources(additional_src + src, src_folder, lib_name)) ) return lib_filename @@ -67,7 +71,35 @@ def get_library_version(): return f"{major_value}.{minor_value}.{patch_value}" -def generate_framework_folder(env: SConsEnvironment, project_name: str, lib_name: str, lib_filename: str, output_path: str): +def read_all_text(file_path: str) -> str | None: + try: + with open(file_path, "r") as file: + text_data = file.read() + except UnicodeDecodeError: + try: + with open(file_path, "r", encoding="utf-8") as file: + text_data = file.read() + except UnicodeDecodeError as e: + print( + "Couldn't open file due to 'UnicodeDecodeError' exception: " + + (file_path).resolve().as_posix() + + "\nException: " + + str(e) + ) + return None + return text_data + + +def write_all_text(file_path: str, text: str) -> bool: + with open(file_path, "w+", encoding="utf-8") as file: + file.write(text) + return True + return False + + +def generate_framework_folder( + env: SConsEnvironment, project_name: str, lib_name: str, lib_filename: str, output_path: str +): min_version = env.get("macos_deployment_target", "10.15") lib_version = get_library_version() lib_filename_noext = os.path.splitext(lib_filename)[0] @@ -113,10 +145,12 @@ def generate_framework_folder(env: SConsEnvironment, project_name: str, lib_name info_plist_file.write(info_plist) -def generate_resources_cpp_h_files(input_files: list, namespace: str, src_folder: str, output_no_ext: str, src_out: list): +def generate_resources_cpp_h_files( + input_files: list, namespace: str, src_folder: str, output_no_ext: str, src_out: list +): """ input_files : list of tuples - (path: str, is_text: bool) + (path: str, is_text: bool, content: list) namespace : str source code namespace src_folder : str @@ -151,31 +185,26 @@ def generate_resources_cpp_h_files(input_files: list, namespace: str, src_folder for input_file_touple in input_files: is_text = input_file_touple[1] input_file_path = input_file_touple[0] + file_content = None + if len(input_file_touple) >= 3: + file_content = input_file_touple[2] file_name_escaped = input_file_path.replace(".", "_").replace("/", "_").replace("\\", "_").replace(":", "_") if is_text: - try: - with open(input_file_path, "r") as file: - text_data = file.read() - except UnicodeDecodeError: - try: - with open(input_file_path, "r", encoding="utf-8") as file: - text_data = file.read() - except UnicodeDecodeError as e: - print( - "Skipping file due to 'UnicodeDecodeError' exception: " - + (input_file_path).resolve().as_posix() - + "\nException: " - + str(e) - ) - continue + if file_content == None: + text_data = read_all_text(input_file_path) + else: + text_data = file_content cpp_file.write(f'\tconst char *{file_name_escaped} = R"({text_data})";\n\n') h_file.write(f"\textern const char *{file_name_escaped};\n") else: - with open(input_file_touple[0], "rb") as input_file: - binary_data = input_file.read() + if file_content == None: + with open(input_file_touple[0], "rb") as input_file: + binary_data = input_file.read() + else: + binary_data = file_content cpp_array = ", ".join([f"{byte}" for byte in binary_data]) cpp_file.write( diff --git a/src/2d/debug_draw_2d.cpp b/src/2d/debug_draw_2d.cpp index 15ced9b0..b122699f 100644 --- a/src/2d/debug_draw_2d.cpp +++ b/src/2d/debug_draw_2d.cpp @@ -13,7 +13,6 @@ GODOT_WARNING_RESTORE() #define NEED_LEAVE (!_is_enabled_override()) DebugDraw2D *DebugDraw2D::singleton = nullptr; -const char *DebugDraw2D::s_marked_dirty = "marked_dirty"; void DebugDraw2D::_bind_methods() { #define REG_CLASS_NAME DebugDraw2D diff --git a/src/2d/debug_draw_2d.h b/src/2d/debug_draw_2d.h index bab49486..74211eba 100644 --- a/src/2d/debug_draw_2d.h +++ b/src/2d/debug_draw_2d.h @@ -34,7 +34,7 @@ class DebugDraw2D : public Object { DebugDrawManager *root_node = nullptr; // 2d - const static char *s_marked_dirty; + static constexpr const char *s_marked_dirty = "marked_dirty"; bool _is_drawing_frame = true; bool _canvas_need_update = true; diff --git a/src/2d/grouped_text.cpp b/src/2d/grouped_text.cpp index e4a570cf..fe1793e5 100644 --- a/src/2d/grouped_text.cpp +++ b/src/2d/grouped_text.cpp @@ -7,7 +7,7 @@ using namespace godot; #ifndef DISABLE_DEBUG_RENDERING TextGroupItem::TextGroupItem(const double &p_expiration_time, const String &p_key, const String &p_text, const int &p_priority, const Color &p_color) { - DEV_PRINT_STD("New " NAMEOF(TextGroupItem) " created: %s : %s\n", p_key.utf8().get_data(), p_text.utf8().get_data()); + DEV_PRINT_STD("New %s created: %s : %s\n", NAMEOF(TextGroupItem), p_key.utf8().get_data(), p_text.utf8().get_data()); expiration_time = p_expiration_time; key = p_key; @@ -85,7 +85,7 @@ int TextGroup::get_text_size() { } TextGroup::TextGroup(DebugDraw2D *p_owner, const String &p_title, const int &p_priority, const bool &p_show_title, const Color &p_group_color, const int &p_title_size, const int &p_text_size) { - DEV_PRINT_STD("New " NAMEOF(TextGroup) " created: %s\n", p_title.utf8().get_data()); + DEV_PRINT_STD("New %s created: %s\n", NAMEOF(TextGroup), p_title.utf8().get_data()); owner = p_owner; title = p_title; diff --git a/src/3d/debug_draw_3d.cpp b/src/3d/debug_draw_3d.cpp index 8d78267b..06460bc0 100644 --- a/src/3d/debug_draw_3d.cpp +++ b/src/3d/debug_draw_3d.cpp @@ -45,19 +45,6 @@ _DD3D_WorldWatcher::_DD3D_WorldWatcher(DebugDraw3D *p_root, uint64_t p_world_id) #endif DebugDraw3D *DebugDraw3D::singleton = nullptr; -const char *DebugDraw3D::s_use_icosphere = "use_icosphere"; -const char *DebugDraw3D::s_use_icosphere_hd = "use_icosphere_for_hd"; -const char *DebugDraw3D::s_add_bevel_to_volumetric = "add_bevel_to_volumetric_geometry"; -const char *DebugDraw3D::s_default_frustum_scale = "defaults/frustum_length_scale"; - -const char *DebugDraw3D::s_default_thickness = "volumetric_defaults/thickness"; -const char *DebugDraw3D::s_default_center_brightness = "volumetric_defaults/center_brightness"; -const char *DebugDraw3D::s_default_hd_spheres = "volumetric_defaults/hd_spheres"; -const char *DebugDraw3D::s_default_plane_size = "volumetric_defaults/plane_size"; - -const char *DebugDraw3D::s_render_priority = "rendering/render_priority"; -const char *DebugDraw3D::s_render_mode = "rendering/render_mode"; -const char *DebugDraw3D::s_render_fog_disabled = "rendering/disable_fog"; void DebugDraw3D::_bind_methods() { #define REG_CLASS_NAME DebugDraw3D diff --git a/src/3d/debug_draw_3d.h b/src/3d/debug_draw_3d.h index 0a6bd7b9..c22af4f9 100644 --- a/src/3d/debug_draw_3d.h +++ b/src/3d/debug_draw_3d.h @@ -53,7 +53,7 @@ class _DD3D_WorldWatcher : public Node3D { protected: DebugDraw3D *m_owner = nullptr; uint64_t m_world_id; - static void _bind_methods(){}; + static void _bind_methods() {}; public: virtual void _process(double p_delta) override; @@ -136,19 +136,19 @@ class DebugDraw3D : public Object, public IScopeStorage custom_editor_viewports; DebugDrawManager *root_node = nullptr; @@ -273,7 +273,7 @@ class DebugDraw3D : public Object, public IScopeStorageget_instance_id() : 0); + DEV_PRINT_STD("%s destroyed: %s, World3D (%d)\n", NAMEOF(DebugGeometryContainer), no_depth_test ? "NoDepth" : "Normal", base_world_viewport.is_valid() ? base_world_viewport->get_instance_id() : 0); LOCK_GUARD(owner->datalock); geometry_pool.clear_pool(); diff --git a/src/3d/render_instances.cpp b/src/3d/render_instances.cpp index 5df2517c..9b6a97a5 100644 --- a/src/3d/render_instances.cpp +++ b/src/3d/render_instances.cpp @@ -32,13 +32,13 @@ bool DelayedRenderer::update_visibility(const std::shared_ptr *> &p_meshes, Ref p_ig, std::unordered_map > &p_culling_data) { diff --git a/src/debug_draw_manager.cpp b/src/debug_draw_manager.cpp index e6b2ab0f..1909eb87 100644 --- a/src/debug_draw_manager.cpp +++ b/src/debug_draw_manager.cpp @@ -32,13 +32,6 @@ void _DD3D_PhysicsWatcher::_physics_process(double p_delta) { DebugDrawManager *DebugDrawManager::singleton = nullptr; -const char *DebugDrawManager::s_initial_state = "initial_debug_state"; -const char *DebugDrawManager::s_manager_aliases = NAMEOF(DebugDrawManager) "_singleton_aliases "; -const char *DebugDrawManager::s_dd2d_aliases = NAMEOF(DebugDraw2D) "_singleton_aliases"; -const char *DebugDrawManager::s_dd3d_aliases = NAMEOF(DebugDraw3D) "_singleton_aliases"; - -const char *DebugDrawManager::s_extension_unloading = "extension_unloading"; - void DebugDrawManager::_bind_methods() { #ifdef DEV_ENABLED ClassDB::bind_method(D_METHOD(NAMEOF(api_test1)), &DebugDrawManager::api_test1); diff --git a/src/debug_draw_manager.h b/src/debug_draw_manager.h index e981d66e..6e679a5f 100644 --- a/src/debug_draw_manager.h +++ b/src/debug_draw_manager.h @@ -17,7 +17,7 @@ class _DD3D_PhysicsWatcher : public Node { GDCLASS(_DD3D_PhysicsWatcher, Node) protected: DebugDrawManager *root_node; - static void _bind_methods(){}; + static void _bind_methods() {}; public: void init(DebugDrawManager *p_root); @@ -64,10 +64,10 @@ class DebugDrawManager : public CanvasLayer { static DebugDrawManager *singleton; String root_settings_section; - const static char *s_initial_state; - const static char *s_manager_aliases; - const static char *s_dd2d_aliases; - const static char *s_dd3d_aliases; + static constexpr const char *s_initial_state = "initial_debug_state"; + static constexpr const char *s_manager_aliases = NAMEOF(DebugDrawManager) "_singleton_aliases "; + static constexpr const char *s_dd2d_aliases = NAMEOF(DebugDraw2D) "_singleton_aliases"; + static constexpr const char *s_dd3d_aliases = NAMEOF(DebugDraw3D) "_singleton_aliases"; double log_flush_time = 0; bool debug_enabled = true; @@ -106,7 +106,7 @@ class DebugDrawManager : public CanvasLayer { static Object *default_arg_obj; // Test regular arguments - void api_test1(Variant, Object *, bool, int, float, String, StringName, NodePath){}; + void api_test1(Variant, Object *, bool, int, float, String, StringName, NodePath) {}; void api_test2(Color, Vector2, Vector2i, Vector3, Vector3i, Vector4, Vector4i, Rect2, Rect2i){}; void api_test3(Transform2D, Transform3D, Plane, Quaternion, AABB, Basis, Projection){}; void api_test4(RID, Callable, Signal, Dictionary, Array){}; @@ -123,7 +123,7 @@ class DebugDrawManager : public CanvasLayer { public: /// @private - static const char *s_extension_unloading; + static constexpr const char *s_extension_unloading = "extension_unloading"; DebugDrawManager(); ~DebugDrawManager(); diff --git a/src/editor/asset_library_update_checker.cpp b/src/editor/asset_library_update_checker.cpp index 717e9109..63536724 100644 --- a/src/editor/asset_library_update_checker.cpp +++ b/src/editor/asset_library_update_checker.cpp @@ -34,7 +34,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::request_completed(String body) { Variant p = json->get_data(); if (err != Error::OK || p.get_type() != Variant::Type::DICTIONARY) { - DEV_PRINT_STD_ERR(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Failed to parse the response body.\n"); + DEV_PRINT_STD_ERR("%s: Failed to parse the response body.\n", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker)); return; } @@ -118,7 +118,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::init() { err = http->poll(); if (err != Error::OK) { - PRINT_ERROR(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Failed to initialize connection. Error: {0}", UtilityFunctions::error_string(err)); + PRINT_ERROR("{0}: Failed to initialize connection. Error: {1}", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker), UtilityFunctions::error_string(err)); return; } } else { @@ -129,7 +129,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::init() { while (http.is_valid() && !is_thread_closing) { err = http->poll(); if (err != Error::OK) { - PRINT_ERROR(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Failed to connect. Error: {0}", UtilityFunctions::error_string(err)); + PRINT_ERROR("{0}: Failed to connect. Error: {1}", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker), UtilityFunctions::error_string(err)); return; } @@ -140,7 +140,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::init() { case godot::HTTPClient::STATUS_CANT_RESOLVE: case godot::HTTPClient::STATUS_CANT_CONNECT: case godot::HTTPClient::STATUS_TLS_HANDSHAKE_ERROR: - PRINT_ERROR(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Connection error: {0}", status); + PRINT_ERROR("{0}: Connection error: {1}", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker), status); return; case godot::HTTPClient::STATUS_RESOLVING: case godot::HTTPClient::STATUS_CONNECTING: @@ -148,7 +148,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::init() { case godot::HTTPClient::STATUS_BODY: default: if (status != prev_status) { - DEV_PRINT_STD(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Connecting status: %d\n", status); + DEV_PRINT_STD("%s: Connecting status: %d\n", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker), status); } break; case godot::HTTPClient::STATUS_CONNECTED: @@ -167,7 +167,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::init() { String request_url = "/asset-library/api/asset/" + String::num_int64(addon_id); err = http->request(HTTPClient::METHOD_GET, request_url, PackedStringArray()); if (err != Error::OK) { - PRINT_ERROR(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Failed to create a request. Error: {0}", UtilityFunctions::error_string(err)); + PRINT_ERROR("{0}: Failed to create a request. Error: {1}", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker), UtilityFunctions::error_string(err)); return; } @@ -175,7 +175,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::init() { err = http->poll(); if (err != Error::OK) { - PRINT_ERROR(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Failed to get a response from \"{0}\". Error: {1}", godot_domain + request_url, UtilityFunctions::error_string(err)); + PRINT_ERROR("{0}: Failed to get a response from \"{1}\". Error: {2}", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker), godot_domain + request_url, UtilityFunctions::error_string(err)); return; } @@ -195,7 +195,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::init() { return; } else { if (code != 0) { - PRINT_ERROR(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Failed to get a response from \"{0}\". Code: {1}", godot_domain + request_url, code); + PRINT_ERROR("{0}: Failed to get a response from \"{1}\". Code: {2}", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker), godot_domain + request_url, code); return; } } @@ -203,7 +203,7 @@ void _DebugDraw3DAssetLibraryUpdateChecker::init() { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } - DEV_PRINT_STD(NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker) ": Thread finished\n"); + DEV_PRINT_STD("%s: Thread finished\n", NAMEOF(_DebugDraw3DAssetLibraryUpdateChecker)); }); } diff --git a/src/editor/editor_menu_extensions.cpp b/src/editor/editor_menu_extensions.cpp index f02c5e38..5f0d74ca 100644 --- a/src/editor/editor_menu_extensions.cpp +++ b/src/editor/editor_menu_extensions.cpp @@ -25,7 +25,7 @@ inline String DebugDrawMenuExtensionPlugin::_get_plugin_name() const { void DebugDrawMenuExtensionPlugin::_enter_tree() { ZoneScoped; - DEV_PRINT_STD(NAMEOF(DebugDrawMenuExtensionPlugin) " _enter_tree\n"); + DEV_PRINT_STD("%s _enter_tree\n", NAMEOF(DebugDrawMenuExtensionPlugin)); PopupMenu *menu = memnew(PopupMenu); menu->connect("id_pressed", Callable(this, NAMEOF(_on_id_pressed))); @@ -75,7 +75,7 @@ void DebugDrawMenuExtensionPlugin::_on_id_pressed(MenuItemId p_id) { } DebugDrawMenuExtensionPlugin::DebugDrawMenuExtensionPlugin() { - DEV_PRINT_STD(NAMEOF(DebugDrawMenuExtensionPlugin) " constructor\n"); + DEV_PRINT_STD("%s constructor\n", NAMEOF(DebugDrawMenuExtensionPlugin)); menu_item_name = "Debug Draw"; } diff --git a/src/utils/compiler.h b/src/utils/compiler.h index 13a732dd..66e402e2 100644 --- a/src/utils/compiler.h +++ b/src/utils/compiler.h @@ -1,6 +1,6 @@ #pragma once -#define NAMEOF(s) #s +#define NAMEOF(_name) #_name // Expands to macro #if DEBUG_ENABLED && _MSC_VER diff --git a/src/utils/utils.h b/src/utils/utils.h index 0feaec51..5b99c8be 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -160,20 +160,20 @@ constexpr size_t INSTANCE_DATA_FLOAT_COUNT = ((sizeof(godot::Transform3D) + size PS()->set_initial_value(path, def); \ } -#define ASSIGN_SINGLETON(class_name) \ - if (!singleton) { \ - singleton = this; \ - } else { \ - PRINT_ERROR("Only 1 instance of " NAMEOF(class_name) " is allowed"); \ +#define ASSIGN_SINGLETON(class_name) \ + if (!singleton) { \ + singleton = this; \ + } else { \ + PRINT_ERROR("Only 1 instance of {0} is allowed", NAMEOF(class_name)); \ } -#define UNASSIGN_SINGLETON(class_name) \ - if (singleton) { \ - if (singleton == this) { \ - singleton = nullptr; \ - } else { \ - PRINT_ERROR("More than 1 " NAMEOF(class_name) " instance was created"); \ - } \ +#define UNASSIGN_SINGLETON(class_name) \ + if (singleton) { \ + if (singleton == this) { \ + singleton = nullptr; \ + } else { \ + PRINT_ERROR("More than 1 {0} instance was created", NAMEOF(class_name)); \ + } \ } // HACK temp constants.