diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/SCsub | 4 | ||||
-rw-r--r-- | core/core_bind.cpp | 20 | ||||
-rw-r--r-- | core/core_bind.h | 4 | ||||
-rw-r--r-- | core/debugger/local_debugger.cpp | 7 | ||||
-rw-r--r-- | core/debugger/remote_debugger.cpp | 10 | ||||
-rw-r--r-- | core/debugger/remote_debugger.h | 3 | ||||
-rw-r--r-- | core/error/error_macros.cpp | 8 | ||||
-rw-r--r-- | core/extension/native_extension.cpp | 28 | ||||
-rw-r--r-- | core/input/input.cpp | 1 | ||||
-rw-r--r-- | core/object/object.cpp | 2 | ||||
-rw-r--r-- | core/object/object.h | 8 | ||||
-rw-r--r-- | core/object/script_language_extension.h | 6 | ||||
-rw-r--r-- | core/os/os.cpp | 15 | ||||
-rw-r--r-- | core/os/os.h | 1 | ||||
-rw-r--r-- | core/string/print_string.cpp | 95 | ||||
-rw-r--r-- | core/string/print_string.h | 12 | ||||
-rw-r--r-- | core/variant/variant_internal.h | 7 | ||||
-rw-r--r-- | core/variant/variant_utility.cpp | 17 |
18 files changed, 212 insertions, 36 deletions
diff --git a/core/SCsub b/core/SCsub index 1379e9df9b..3814c72877 100644 --- a/core/SCsub +++ b/core/SCsub @@ -129,6 +129,10 @@ if env["builtin_zstd"]: "decompress/zstd_decompress_block.c", "decompress/zstd_decompress.c", ] + if env["platform"] in ["android", "linuxbsd", "osx"]: + # Match platforms with ZSTD_ASM_SUPPORTED in common/portability_macros.h + # iOS x86_64 should be supported in theory, but it fails arm64 build, seems to use host S_compiler. + thirdparty_zstd_sources.append("decompress/huf_decompress_amd64.S") thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources] env_thirdparty.Prepend(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"]) diff --git a/core/core_bind.cpp b/core/core_bind.cpp index fc91f83462..b5f4a1c0f6 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -83,6 +83,14 @@ Vector<String> ResourceLoader::get_recognized_extensions_for_type(const String & return ret; } +void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front) { + ::ResourceLoader::add_resource_format_loader(p_format_loader, p_at_front); +} + +void ResourceLoader::remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader) { + ::ResourceLoader::remove_resource_format_loader(p_format_loader); +} + void ResourceLoader::set_abort_on_missing_resources(bool p_abort) { ::ResourceLoader::set_abort_on_missing_resources(p_abort); } @@ -119,6 +127,8 @@ void ResourceLoader::_bind_methods() { ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "cache_mode"), &ResourceLoader::load, DEFVAL(""), DEFVAL(CACHE_MODE_REUSE)); ClassDB::bind_method(D_METHOD("get_recognized_extensions_for_type", "type"), &ResourceLoader::get_recognized_extensions_for_type); + ClassDB::bind_method(D_METHOD("add_resource_format_loader", "format_loader", "at_front"), &ResourceLoader::add_resource_format_loader, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("remove_resource_format_loader", "format_loader"), &ResourceLoader::remove_resource_format_loader); ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources", "abort"), &ResourceLoader::set_abort_on_missing_resources); ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &ResourceLoader::get_dependencies); ClassDB::bind_method(D_METHOD("has_cached", "path"), &ResourceLoader::has_cached); @@ -153,11 +163,21 @@ Vector<String> ResourceSaver::get_recognized_extensions(const Ref<Resource> &p_r return ret; } +void ResourceSaver::add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front) { + ::ResourceSaver::add_resource_format_saver(p_format_saver, p_at_front); +} + +void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver) { + ::ResourceSaver::remove_resource_format_saver(p_format_saver); +} + ResourceSaver *ResourceSaver::singleton = nullptr; void ResourceSaver::_bind_methods() { ClassDB::bind_method(D_METHOD("save", "path", "resource", "flags"), &ResourceSaver::save, DEFVAL((uint32_t)FLAG_NONE)); ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &ResourceSaver::get_recognized_extensions); + ClassDB::bind_method(D_METHOD("add_resource_format_saver", "format_saver", "at_front"), &ResourceSaver::add_resource_format_saver, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("remove_resource_format_saver", "format_saver"), &ResourceSaver::remove_resource_format_saver); BIND_ENUM_CONSTANT(FLAG_NONE); BIND_ENUM_CONSTANT(FLAG_RELATIVE_PATHS); diff --git a/core/core_bind.h b/core/core_bind.h index ec9bcdbc02..99e14a75f5 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -77,6 +77,8 @@ public: Ref<Resource> load(const String &p_path, const String &p_type_hint = "", CacheMode p_cache_mode = CACHE_MODE_REUSE); Vector<String> get_recognized_extensions_for_type(const String &p_type); + void add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front); + void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader); void set_abort_on_missing_resources(bool p_abort); PackedStringArray get_dependencies(const String &p_path); bool has_cached(const String &p_path); @@ -109,6 +111,8 @@ public: Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags); Vector<String> get_recognized_extensions(const Ref<Resource> &p_resource); + void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front); + void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver); ResourceSaver() { singleton = this; } }; diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index 06e08081e9..58d239ccb9 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -31,7 +31,7 @@ #include "local_debugger.h" #include "core/debugger/script_debugger.h" -#include "scene/main/scene_tree.h" +#include "core/os/os.h" struct LocalDebugger::ScriptsProfiler { struct ProfileInfoSort { @@ -273,7 +273,10 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { script_debugger->set_depth(-1); script_debugger->set_lines_left(-1); - SceneTree::get_singleton()->quit(); + MainLoop *main_loop = OS::get_singleton()->get_main_loop(); + if (main_loop->get_class() == "SceneTree") { + main_loop->call("quit"); + } break; } else if (line.begins_with("delete")) { if (line.get_slice_count(" ") <= 1) { diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 5ee4e2c368..508a71ece9 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -208,7 +208,7 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char * rd->script_debugger->send_error(String::utf8(p_func), String::utf8(p_file), p_line, String::utf8(p_err), String::utf8(p_descr), p_editor_notify, p_type, si); } -void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error) { +void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error, bool p_rich) { RemoteDebugger *rd = static_cast<RemoteDebugger *>(p_this); if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive prints during flush. @@ -237,7 +237,13 @@ void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p OutputString output_string; output_string.message = s; - output_string.type = p_error ? MESSAGE_TYPE_ERROR : MESSAGE_TYPE_LOG; + if (p_error) { + output_string.type = MESSAGE_TYPE_ERROR; + } else if (p_rich) { + output_string.type = MESSAGE_TYPE_LOG_RICH; + } else { + output_string.type = MESSAGE_TYPE_LOG; + } rd->output_strings.push_back(output_string); if (overflowed) { diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index fdb312ae68..fe4bbe86ea 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -44,6 +44,7 @@ public: enum MessageType { MESSAGE_TYPE_LOG, MESSAGE_TYPE_ERROR, + MESSAGE_TYPE_LOG_RICH, }; private: @@ -82,7 +83,7 @@ private: Thread::ID flush_thread = 0; PrintHandlerList phl; - static void _print_handler(void *p_this, const String &p_string, bool p_error); + static void _print_handler(void *p_this, const String &p_string, bool p_error, bool p_rich); ErrorHandlerList eh; static void _err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type); diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp index 8add4b9a3a..f71a642b23 100644 --- a/core/error/error_macros.cpp +++ b/core/error/error_macros.cpp @@ -83,7 +83,13 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co // Main error printing function. void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) { - OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type); + if (OS::get_singleton()) { + OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type); + } else { + // Fallback if errors happen before OS init or after it's destroyed. + const char *err_details = (p_message && *p_message) ? p_message : p_error; + fprintf(stderr, "ERROR: %s\n at: %s (%s:%i)\n", err_details, p_function, p_file, p_line); + } _global_lock(); ErrorHandlerList *l = error_handler_list; diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp index ebdfa20725..262e28b442 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/native_extension.cpp @@ -55,14 +55,7 @@ protected: virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { GDNativePropertyInfo pinfo; get_argument_info_func(method_userdata, p_arg, &pinfo); - PropertyInfo ret; - ret.type = Variant::Type(pinfo.type); - ret.name = pinfo.name; - ret.class_name = pinfo.class_name; - ret.hint = PropertyHint(pinfo.hint); - ret.usage = pinfo.usage; - ret.class_name = pinfo.class_name; - return ret; + return PropertyInfo(pinfo); } public: @@ -204,16 +197,11 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension NativeExtension *self = static_cast<NativeExtension *>(p_library); StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'."); + String property_name = p_info->name; + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + property_name + "' for unexisting class '" + class_name + "'."); //Extension *extension = &self->extension_classes[class_name]; - PropertyInfo pinfo; - pinfo.type = Variant::Type(p_info->type); - pinfo.name = p_info->name; - pinfo.class_name = p_info->class_name; - pinfo.hint = PropertyHint(p_info->hint); - pinfo.hint_string = p_info->hint_string; - pinfo.usage = p_info->usage; + PropertyInfo pinfo(*p_info); ClassDB::add_property(class_name, pinfo, p_setter, p_getter); } @@ -245,13 +233,7 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl MethodInfo s; s.name = p_signal_name; for (int i = 0; i < p_argument_count; i++) { - PropertyInfo arg; - arg.type = Variant::Type(p_argument_info[i].type); - arg.name = p_argument_info[i].name; - arg.class_name = p_argument_info[i].class_name; - arg.hint = PropertyHint(p_argument_info[i].hint); - arg.hint_string = p_argument_info[i].hint_string; - arg.usage = p_argument_info[i].usage; + PropertyInfo arg(p_argument_info[i]); s.arguments.push_back(arg); } ClassDB::add_signal(class_name, s); diff --git a/core/input/input.cpp b/core/input/input.cpp index b3a68bb98c..da0c6cb62a 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -325,6 +325,7 @@ float Input::get_action_strength(const StringName &p_action, bool p_exact) const } float Input::get_action_raw_strength(const StringName &p_action, bool p_exact) const { + ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), 0.0, InputMap::get_singleton()->suggest_actions(p_action)); HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action); if (!E) { return 0.0f; diff --git a/core/object/object.cpp b/core/object/object.cpp index 440da00c17..5f2287c9d3 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -493,7 +493,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons uint32_t pcount; const GDNativePropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount); for (uint32_t i = 0; i < pcount; i++) { - p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name)); + p_list->push_back(PropertyInfo(pinfo[i])); } if (_extension->free_property_list) { _extension->free_property_list(_extension_instance, pinfo); diff --git a/core/object/object.h b/core/object/object.h index e065634000..1f6386e6b4 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -190,6 +190,14 @@ struct PropertyInfo { type(Variant::OBJECT), class_name(p_class_name) {} + explicit PropertyInfo(const GDNativePropertyInfo &pinfo) : + type((Variant::Type)pinfo.type), + name(pinfo.name), + class_name(pinfo.class_name), // can be null + hint((PropertyHint)pinfo.hint), + hint_string(pinfo.hint_string), // can be null + usage(pinfo.usage) {} + bool operator==(const PropertyInfo &p_info) const { return ((type == p_info.type) && (name == p_info.name) && diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 406a431a11..7eea48370e 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -671,7 +671,7 @@ public: uint32_t pcount; const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount); for (uint32_t i = 0; i < pcount; i++) { - p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name)); + p_list->push_back(PropertyInfo(pinfo[i])); } if (native_info->free_property_list_func) { native_info->free_property_list_func(instance, pinfo); @@ -716,9 +716,9 @@ public: m.name = minfo[i].name; m.flags = minfo[i].flags; m.id = minfo[i].id; - m.return_val = PropertyInfo(Variant::Type(minfo[i].return_value.type), minfo[i].return_value.class_name, PropertyHint(minfo[i].return_value.hint), minfo[i].return_value.hint_string, minfo[i].return_value.usage, minfo[i].return_value.class_name); + m.return_val = PropertyInfo(minfo[i].return_value); for (uint32_t j = 0; j < minfo[i].argument_count; j++) { - m.arguments.push_back(PropertyInfo(Variant::Type(minfo[i].arguments[j].type), minfo[i].arguments[j].class_name, PropertyHint(minfo[i].arguments[j].hint), minfo[i].arguments[j].hint_string, minfo[i].arguments[j].usage, minfo[i].arguments[j].class_name)); + m.arguments.push_back(PropertyInfo(minfo[i].arguments[j])); } const Variant *def_values = (const Variant *)minfo[i].default_arguments; for (uint32_t j = 0; j < minfo[i].default_argument_count; j++) { diff --git a/core/os/os.cpp b/core/os/os.cpp index 93477f4288..b9daf6fa53 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -100,6 +100,21 @@ void OS::print(const char *p_format, ...) { va_end(argp); } +void OS::print_rich(const char *p_format, ...) { + if (!_stdout_enabled) { + return; + } + + va_list argp; + va_start(argp, p_format); + + if (_logger) { + _logger->logv(p_format, argp, false); + } + + va_end(argp); +} + void OS::printerr(const char *p_format, ...) { if (!_stderr_enabled) { return; diff --git a/core/os/os.h b/core/os/os.h index c6ea9d869a..af6c38cbe0 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -120,6 +120,7 @@ public: void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, Logger::ErrorType p_type = Logger::ERR_ERROR); void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; + void print_rich(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; virtual String get_stdin_string(bool p_block = true) = 0; diff --git a/core/string/print_string.cpp b/core/string/print_string.cpp index 919c9e08e3..f58486e0a5 100644 --- a/core/string/print_string.cpp +++ b/core/string/print_string.cpp @@ -79,7 +79,98 @@ void __print_line(String p_string) { _global_lock(); PrintHandlerList *l = print_handler_list; while (l) { - l->printfunc(l->userdata, p_string, false); + l->printfunc(l->userdata, p_string, false, false); + l = l->next; + } + + _global_unlock(); +} + +void __print_line_rich(String p_string) { + if (!_print_line_enabled) { + return; + } + + // Convert a subset of BBCode tags to ANSI escape codes for correct display in the terminal. + // Support of those ANSI escape codes varies across terminal emulators, + // especially for italic and strikethrough. + String p_string_ansi = p_string; + + p_string_ansi = p_string_ansi.replace("[b]", "\u001b[1m"); + p_string_ansi = p_string_ansi.replace("[/b]", "\u001b[22m"); + p_string_ansi = p_string_ansi.replace("[i]", "\u001b[3m"); + p_string_ansi = p_string_ansi.replace("[/i]", "\u001b[23m"); + p_string_ansi = p_string_ansi.replace("[u]", "\u001b[4m"); + p_string_ansi = p_string_ansi.replace("[/u]", "\u001b[24m"); + p_string_ansi = p_string_ansi.replace("[s]", "\u001b[9m"); + p_string_ansi = p_string_ansi.replace("[/s]", "\u001b[29m"); + + p_string_ansi = p_string_ansi.replace("[indent]", " "); + p_string_ansi = p_string_ansi.replace("[/indent]", ""); + p_string_ansi = p_string_ansi.replace("[code]", "\u001b[2m"); + p_string_ansi = p_string_ansi.replace("[/code]", "\u001b[22m"); + p_string_ansi = p_string_ansi.replace("[url]", ""); + p_string_ansi = p_string_ansi.replace("[/url]", ""); + p_string_ansi = p_string_ansi.replace("[center]", "\n\t\t\t"); + p_string_ansi = p_string_ansi.replace("[/center]", ""); + p_string_ansi = p_string_ansi.replace("[right]", "\n\t\t\t\t\t\t"); + p_string_ansi = p_string_ansi.replace("[/right]", ""); + + if (p_string_ansi.contains("[color")) { + p_string_ansi = p_string_ansi.replace("[color=black]", "\u001b[30m"); + p_string_ansi = p_string_ansi.replace("[color=red]", "\u001b[91m"); + p_string_ansi = p_string_ansi.replace("[color=green]", "\u001b[92m"); + p_string_ansi = p_string_ansi.replace("[color=lime]", "\u001b[92m"); + p_string_ansi = p_string_ansi.replace("[color=yellow]", "\u001b[93m"); + p_string_ansi = p_string_ansi.replace("[color=blue]", "\u001b[94m"); + p_string_ansi = p_string_ansi.replace("[color=magenta]", "\u001b[95m"); + p_string_ansi = p_string_ansi.replace("[color=pink]", "\u001b[38;5;218m"); + p_string_ansi = p_string_ansi.replace("[color=purple]", "\u001b[38;5;98m"); + p_string_ansi = p_string_ansi.replace("[color=cyan]", "\u001b[96m"); + p_string_ansi = p_string_ansi.replace("[color=white]", "\u001b[97m"); + p_string_ansi = p_string_ansi.replace("[color=orange]", "\u001b[38;5;208m"); + p_string_ansi = p_string_ansi.replace("[color=gray]", "\u001b[90m"); + p_string_ansi = p_string_ansi.replace("[/color]", "\u001b[39m"); + } + if (p_string_ansi.contains("[bgcolor")) { + p_string_ansi = p_string_ansi.replace("[bgcolor=black]", "\u001b[40m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=red]", "\u001b[101m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=green]", "\u001b[102m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=lime]", "\u001b[102m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=yellow]", "\u001b[103m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=blue]", "\u001b[104m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=magenta]", "\u001b[105m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=pink]", "\u001b[48;5;218m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=purple]", "\u001b[48;5;98m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=cyan]", "\u001b[106m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=white]", "\u001b[107m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=orange]", "\u001b[48;5;208m"); + p_string_ansi = p_string_ansi.replace("[bgcolor=gray]", "\u001b[100m"); + p_string_ansi = p_string_ansi.replace("[/bgcolor]", "\u001b[49m"); + } + if (p_string_ansi.contains("[fgcolor")) { + p_string_ansi = p_string_ansi.replace("[fgcolor=black]", "\u001b[30;40m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=red]", "\u001b[91;101m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=green]", "\u001b[92;102m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=lime]", "\u001b[92;102m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=yellow]", "\u001b[93;103m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=blue]", "\u001b[94;104m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=magenta]", "\u001b[95;105m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=pink]", "\u001b[38;5;218;48;5;218m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=purple]", "\u001b[38;5;98;48;5;98m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=cyan]", "\u001b[96;106m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=white]", "\u001b[97;107m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=orange]", "\u001b[38;5;208;48;5;208m"); + p_string_ansi = p_string_ansi.replace("[fgcolor=gray]", "\u001b[90;100m"); + p_string_ansi = p_string_ansi.replace("[/fgcolor]", "\u001b[39;49m"); + } + + OS::get_singleton()->print_rich("%s\n", p_string_ansi.utf8().get_data()); + + _global_lock(); + PrintHandlerList *l = print_handler_list; + while (l) { + l->printfunc(l->userdata, p_string, false, true); l = l->next; } @@ -96,7 +187,7 @@ void print_error(String p_string) { _global_lock(); PrintHandlerList *l = print_handler_list; while (l) { - l->printfunc(l->userdata, p_string, true); + l->printfunc(l->userdata, p_string, true, false); l = l->next; } diff --git a/core/string/print_string.h b/core/string/print_string.h index f7d0f25030..823e2c29e8 100644 --- a/core/string/print_string.h +++ b/core/string/print_string.h @@ -35,7 +35,7 @@ extern void (*_print_func)(String); -typedef void (*PrintHandlerFunc)(void *, const String &p_string, bool p_error); +typedef void (*PrintHandlerFunc)(void *, const String &p_string, bool p_error, bool p_rich); struct PrintHandlerList { PrintHandlerFunc printfunc = nullptr; @@ -59,6 +59,7 @@ void remove_print_handler(const PrintHandlerList *p_handler); extern bool _print_line_enabled; extern bool _print_error_enabled; extern void __print_line(String p_string); +extern void __print_line_rich(String p_string); extern void print_error(String p_string); extern void print_verbose(String p_string); @@ -66,9 +67,18 @@ inline void print_line(Variant v) { __print_line(stringify_variants(v)); } +inline void print_line_rich(Variant v) { + __print_line_rich(stringify_variants(v)); +} + template <typename... Args> void print_line(Variant p_var, Args... p_args) { __print_line(stringify_variants(p_var, p_args...)); } +template <typename... Args> +void print_line_rich(Variant p_var, Args... p_args) { + __print_line_rich(stringify_variants(p_var, p_args...)); +} + #endif // PRINT_STRING_H diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index 3696ffae60..e0cfb42e1e 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -304,6 +304,13 @@ public: v->_get_obj().id = ObjectID(); } + static void update_object_id(Variant *v) { + const Object *o = v->_get_obj().obj; + if (o) { + v->_get_obj().id = o->get_instance_id(); + } + } + _FORCE_INLINE_ static void *get_opaque_pointer(Variant *v) { switch (v->type) { case Variant::NIL: diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index d1b5e285d2..2bca5f8284 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -560,6 +560,22 @@ struct VariantUtilityFunctions { r_error.error = Callable::CallError::CALL_OK; } + static inline void print_rich(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + String s; + for (int i = 0; i < p_arg_count; i++) { + String os = p_args[i]->operator String(); + + if (i == 0) { + s = os; + } else { + s += os; + } + } + + print_line_rich(s); + r_error.error = Callable::CallError::CALL_OK; + } + static inline void print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { if (OS::get_singleton()->is_stdout_verbose()) { String s; @@ -1306,6 +1322,7 @@ void Variant::_register_variant_utility_functions() { FUNCBINDVARARGS(str, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDR(error_string, sarray("error"), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(print, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGV(print_rich, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(printerr, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(printt, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(prints, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); |