summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub4
-rw-r--r--core/core_bind.cpp20
-rw-r--r--core/core_bind.h4
-rw-r--r--core/debugger/local_debugger.cpp7
-rw-r--r--core/debugger/remote_debugger.cpp10
-rw-r--r--core/debugger/remote_debugger.h3
-rw-r--r--core/error/error_macros.cpp8
-rw-r--r--core/extension/native_extension.cpp28
-rw-r--r--core/input/input.cpp1
-rw-r--r--core/object/object.cpp2
-rw-r--r--core/object/object.h8
-rw-r--r--core/object/script_language_extension.h6
-rw-r--r--core/os/os.cpp15
-rw-r--r--core/os/os.h1
-rw-r--r--core/string/print_string.cpp95
-rw-r--r--core/string/print_string.h12
-rw-r--r--core/variant/variant_internal.h7
-rw-r--r--core/variant/variant_utility.cpp17
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);