Browse Source

Update error macros to match core

Mikael Hermansson 2 years ago
parent
commit
d174b47e51
3 changed files with 355 additions and 168 deletions
  1. 6 3
      gdextension/gdextension_interface.h
  2. 323 134
      include/godot_cpp/core/error_macros.hpp
  3. 26 31
      src/core/error_macros.cpp

+ 6 - 3
gdextension/gdextension_interface.h

@@ -415,9 +415,12 @@ typedef struct {
 	void *(*mem_realloc)(void *p_ptr, size_t p_bytes);
 	void *(*mem_realloc)(void *p_ptr, size_t p_bytes);
 	void (*mem_free)(void *p_ptr);
 	void (*mem_free)(void *p_ptr);
 
 
-	void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
-	void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
-	void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
+	void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, bool p_editor_notify);
+	void (*print_error_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, bool p_editor_notify);
+	void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, bool p_editor_notify);
+	void (*print_warning_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, bool p_editor_notify);
+	void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, bool p_editor_notify);
+	void (*print_script_error_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, bool p_editor_notify);
 
 
 	uint64_t (*get_native_struct_size)(GDExtensionConstStringNamePtr p_name);
 	uint64_t (*get_native_struct_size)(GDExtensionConstStringNamePtr p_name);
 
 

+ 323 - 134
include/godot_cpp/core/error_macros.hpp

@@ -32,32 +32,26 @@
 #define GODOT_ERROR_MACROS_HPP
 #define GODOT_ERROR_MACROS_HPP
 
 
 #include <godot_cpp/core/defs.hpp>
 #include <godot_cpp/core/defs.hpp>
-#include <godot_cpp/variant/string.hpp>
 
 
-#include <cstdint>
+#include <atomic>
 
 
 namespace godot {
 namespace godot {
 
 
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_is_warning = false);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_is_warning = false);
-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_is_warning = false);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_is_warning = false);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_is_warning = false);
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_is_warning = false);
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool fatal = false);
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal = false);
+class String;
 
 
-} // namespace godot
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, bool p_is_warning = false);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify = false, bool p_is_warning = false);
+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 = false, bool p_is_warning = false);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, bool p_is_warning = false);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, bool p_is_warning = false);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, bool p_is_warning = false);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool p_fatal = false);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool p_fatal = false);
+void _err_flush_stdout();
 
 
-// Used to strip debug messages in release mode
-#ifdef DEBUG_ENABLED
-#define DEBUG_STR(m_msg) m_msg
-#else
-#define DEBUG_STR(m_msg) ""
-#endif
+} // namespace godot
 
 
 #ifdef __GNUC__
 #ifdef __GNUC__
-//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
 #define FUNCTION_STR __FUNCTION__
 #define FUNCTION_STR __FUNCTION__
 #else
 #else
 #define FUNCTION_STR __FUNCTION__
 #define FUNCTION_STR __FUNCTION__
@@ -75,6 +69,34 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
 #define GENERATE_TRAP() __builtin_trap()
 #define GENERATE_TRAP() __builtin_trap()
 #endif
 #endif
 
 
+/**
+ * Error macros.
+ * WARNING: These macros work in the opposite way to assert().
+ *
+ * Unlike exceptions and asserts, these macros try to maintain consistency and stability.
+ * In most cases, bugs and/or invalid data are not fatal. They should never allow a perfectly
+ * running application to fail or crash.
+ * Always try to return processable data, so the engine can keep running well.
+ * Use the _MSG versions to print a meaningful message to help with debugging.
+ *
+ * The `((void)0)` no-op statement is used as a trick to force us to put a semicolon after
+ * those macros, making them look like proper statements.
+ * The if wrappers are used to ensure that the macro replacement does not trigger unexpected
+ * issues when expanded e.g. after an `if (cond) ERR_FAIL();` without braces.
+ */
+
+// Index out of bounds error macros.
+// These macros should be used instead of `ERR_FAIL_COND` for bounds checking.
+
+// Integer index out of bounds error macros.
+
+/**
+ * Try using `ERR_FAIL_INDEX_MSG`.
+ * Only use this macro if there is no sensible error message.
+ *
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, the current function returns.
+ */
 #define ERR_FAIL_INDEX(m_index, m_size)                                                                                  \
 #define ERR_FAIL_INDEX(m_index, m_size)                                                                                  \
 	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                              \
 	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                              \
 		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
 		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
@@ -86,11 +108,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
  * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
  * If not, prints `m_msg` and the current function returns.
  * If not, prints `m_msg` and the current function returns.
  */
  */
-#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg)                                                                                         \
-	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                                \
-		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
-		return;                                                                                                                            \
-	} else                                                                                                                                 \
+#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg)                                                                              \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                     \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
+		return;                                                                                                                 \
+	} else                                                                                                                      \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_INDEX_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg)                                                                                  \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                           \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+		return;                                                                                                                       \
+	} else                                                                                                                            \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -111,11 +143,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
  * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
  * If not, prints `m_msg` and the current function returns `m_retval`.
  * If not, prints `m_msg` and the current function returns `m_retval`.
  */
  */
-#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg)                                                                             \
-	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                                \
-		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
-		return m_retval;                                                                                                                   \
-	} else                                                                                                                                 \
+#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg)                                                                  \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                     \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
+		return m_retval;                                                                                                        \
+	} else                                                                                                                      \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_INDEX_V_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg)                                                                      \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                           \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+		return m_retval;                                                                                                              \
+	} else                                                                                                                            \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -126,11 +168,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
  * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
  * If not, the application crashes.
  * If not, the application crashes.
  */
  */
-#define CRASH_BAD_INDEX(m_index, m_size)                                                                                           \
-	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                        \
-		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \
-		GENERATE_TRAP();                                                                                                           \
-	} else                                                                                                                         \
+#define CRASH_BAD_INDEX(m_index, m_size)                                                                                                  \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                               \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", false, true); \
+		::godot::_err_flush_stdout();                                                                                                     \
+		GENERATE_TRAP();                                                                                                                  \
+	} else                                                                                                                                \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -140,11 +183,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
  * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
  * If not, prints `m_msg` and the application crashes.
  * If not, prints `m_msg` and the application crashes.
  */
  */
-#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg)                                                                                              \
-	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                                      \
-		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \
-		GENERATE_TRAP();                                                                                                                         \
-	} else                                                                                                                                       \
+#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg)                                                                                          \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                                  \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, false, true); \
+		::godot::_err_flush_stdout();                                                                                                        \
+		GENERATE_TRAP();                                                                                                                     \
+	} else                                                                                                                                   \
 		((void)0)
 		((void)0)
 
 
 // Unsigned integer index out of bounds error macros.
 // Unsigned integer index out of bounds error macros.
@@ -167,11 +211,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures an unsigned integer index `m_index` is less than `m_size`.
  * Ensures an unsigned integer index `m_index` is less than `m_size`.
  * If not, prints `m_msg` and the current function returns.
  * If not, prints `m_msg` and the current function returns.
  */
  */
-#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg)                                                                                \
-	if (unlikely((m_index) >= (m_size))) {                                                                                                 \
-		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
-		return;                                                                                                                            \
-	} else                                                                                                                                 \
+#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg)                                                                     \
+	if (unlikely((m_index) >= (m_size))) {                                                                                      \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
+		return;                                                                                                                 \
+	} else                                                                                                                      \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_UNSIGNED_INDEX_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg)                                                                         \
+	if (unlikely((m_index) >= (m_size))) {                                                                                            \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+		return;                                                                                                                       \
+	} else                                                                                                                            \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -192,11 +246,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures an unsigned integer index `m_index` is less than `m_size`.
  * Ensures an unsigned integer index `m_index` is less than `m_size`.
  * If not, prints `m_msg` and the current function returns `m_retval`.
  * If not, prints `m_msg` and the current function returns `m_retval`.
  */
  */
-#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg)                                                                    \
-	if (unlikely((m_index) >= (m_size))) {                                                                                                 \
-		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
-		return m_retval;                                                                                                                   \
-	} else                                                                                                                                 \
+#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg)                                                         \
+	if (unlikely((m_index) >= (m_size))) {                                                                                      \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
+		return m_retval;                                                                                                        \
+	} else                                                                                                                      \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_UNSIGNED_INDEX_V_EDMSG` but also notifies the editor.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg)                                                             \
+	if (unlikely((m_index) >= (m_size))) {                                                                                            \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
+		return m_retval;                                                                                                              \
+	} else                                                                                                                            \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -207,11 +271,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures an unsigned integer index `m_index` is less than `m_size`.
  * Ensures an unsigned integer index `m_index` is less than `m_size`.
  * If not, the application crashes.
  * If not, the application crashes.
  */
  */
-#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size)                                                                                  \
-	if (unlikely((m_index) >= (m_size))) {                                                                                         \
-		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \
-		GENERATE_TRAP();                                                                                                           \
-	} else                                                                                                                         \
+#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size)                                                                                         \
+	if (unlikely((m_index) >= (m_size))) {                                                                                                \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", false, true); \
+		::godot::_err_flush_stdout();                                                                                                     \
+		GENERATE_TRAP();                                                                                                                  \
+	} else                                                                                                                                \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -221,11 +286,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures an unsigned integer index `m_index` is less than `m_size`.
  * Ensures an unsigned integer index `m_index` is less than `m_size`.
  * If not, prints `m_msg` and the application crashes.
  * If not, prints `m_msg` and the application crashes.
  */
  */
-#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg)                                                                                     \
-	if (unlikely((m_index) >= (m_size))) {                                                                                                       \
-		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \
-		GENERATE_TRAP();                                                                                                                         \
-	} else                                                                                                                                       \
+#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg)                                                                                 \
+	if (unlikely((m_index) >= (m_size))) {                                                                                                   \
+		::godot::_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, false, true); \
+		::godot::_err_flush_stdout();                                                                                                        \
+		GENERATE_TRAP();                                                                                                                     \
+	} else                                                                                                                                   \
 		((void)0)
 		((void)0)
 
 
 // Null reference error macros.
 // Null reference error macros.
@@ -248,11 +314,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures a pointer `m_param` is not null.
  * Ensures a pointer `m_param` is not null.
  * If it is null, prints `m_msg` and the current function returns.
  * If it is null, prints `m_msg` and the current function returns.
  */
  */
-#define ERR_FAIL_NULL_MSG(m_param, m_msg)                                                                                          \
-	if (unlikely(m_param == nullptr)) {                                                                                            \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \
-		return;                                                                                                                    \
-	} else                                                                                                                         \
+#define ERR_FAIL_NULL_MSG(m_param, m_msg)                                                                               \
+	if (unlikely(m_param == nullptr)) {                                                                                 \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
+		return;                                                                                                         \
+	} else                                                                                                              \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_NULL_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_NULL_EDMSG(m_param, m_msg)                                                                                   \
+	if (unlikely(m_param == nullptr)) {                                                                                       \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
+		return;                                                                                                               \
+	} else                                                                                                                    \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -273,11 +349,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures a pointer `m_param` is not null.
  * Ensures a pointer `m_param` is not null.
  * If it is null, prints `m_msg` and the current function returns `m_retval`.
  * If it is null, prints `m_msg` and the current function returns `m_retval`.
  */
  */
-#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg)                                                                              \
-	if (unlikely(m_param == nullptr)) {                                                                                            \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \
-		return m_retval;                                                                                                           \
-	} else                                                                                                                         \
+#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg)                                                                   \
+	if (unlikely(m_param == nullptr)) {                                                                                 \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
+		return m_retval;                                                                                                \
+	} else                                                                                                              \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_NULL_V_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg)                                                                       \
+	if (unlikely(m_param == nullptr)) {                                                                                       \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
+		return m_retval;                                                                                                      \
+	} else                                                                                                                    \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -303,11 +389,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * If checking for null use ERR_FAIL_NULL_MSG instead.
  * If checking for null use ERR_FAIL_NULL_MSG instead.
  * If checking index bounds use ERR_FAIL_INDEX_MSG instead.
  * If checking index bounds use ERR_FAIL_INDEX_MSG instead.
  */
  */
-#define ERR_FAIL_COND_MSG(m_cond, m_msg)                                                                                          \
-	if (unlikely(m_cond)) {                                                                                                       \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \
-		return;                                                                                                                   \
-	} else                                                                                                                        \
+#define ERR_FAIL_COND_MSG(m_cond, m_msg)                                                                               \
+	if (unlikely(m_cond)) {                                                                                            \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg); \
+		return;                                                                                                        \
+	} else                                                                                                             \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_COND_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_COND_EDMSG(m_cond, m_msg)                                                                                   \
+	if (unlikely(m_cond)) {                                                                                                  \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg, true); \
+		return;                                                                                                              \
+	} else                                                                                                                   \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -333,11 +429,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * If checking for null use ERR_FAIL_NULL_V_MSG instead.
  * If checking for null use ERR_FAIL_NULL_V_MSG instead.
  * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
  * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
  */
  */
-#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg)                                                                                                         \
-	if (unlikely(m_cond)) {                                                                                                                                  \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
-		return m_retval;                                                                                                                                     \
-	} else                                                                                                                                                   \
+#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg)                                                                                              \
+	if (unlikely(m_cond)) {                                                                                                                       \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg); \
+		return m_retval;                                                                                                                          \
+	} else                                                                                                                                        \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_COND_V_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg)                                                                                                  \
+	if (unlikely(m_cond)) {                                                                                                                             \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg, true); \
+		return m_retval;                                                                                                                                \
+	} else                                                                                                                                              \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -358,11 +464,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures `m_cond` is false.
  * Ensures `m_cond` is false.
  * If `m_cond` is true, prints `m_msg` and the current loop continues.
  * If `m_cond` is true, prints `m_msg` and the current loop continues.
  */
  */
-#define ERR_CONTINUE_MSG(m_cond, m_msg)                                                                                                       \
-	if (unlikely(m_cond)) {                                                                                                                   \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", DEBUG_STR(m_msg)); \
-		continue;                                                                                                                             \
-	} else                                                                                                                                    \
+#define ERR_CONTINUE_MSG(m_cond, m_msg)                                                                                            \
+	if (unlikely(m_cond)) {                                                                                                        \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg); \
+		continue;                                                                                                                  \
+	} else                                                                                                                         \
+		((void)0)
+
+/**
+ * Same as `ERR_CONTINUE_MSG` but also notifies the editor.
+ */
+#define ERR_CONTINUE_EDMSG(m_cond, m_msg)                                                                                                \
+	if (unlikely(m_cond)) {                                                                                                              \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg, true); \
+		continue;                                                                                                                        \
+	} else                                                                                                                               \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -383,11 +499,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures `m_cond` is false.
  * Ensures `m_cond` is false.
  * If `m_cond` is true, prints `m_msg` and the current loop breaks.
  * If `m_cond` is true, prints `m_msg` and the current loop breaks.
  */
  */
-#define ERR_BREAK_MSG(m_cond, m_msg)                                                                                                        \
-	if (unlikely(m_cond)) {                                                                                                                 \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", DEBUG_STR(m_msg)); \
-		break;                                                                                                                              \
-	} else                                                                                                                                  \
+#define ERR_BREAK_MSG(m_cond, m_msg)                                                                                             \
+	if (unlikely(m_cond)) {                                                                                                      \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg); \
+		break;                                                                                                                   \
+	} else                                                                                                                       \
+		((void)0)
+
+/**
+ * Same as `ERR_BREAK_MSG` but also notifies the editor.
+ */
+#define ERR_BREAK_EDMSG(m_cond, m_msg)                                                                                                 \
+	if (unlikely(m_cond)) {                                                                                                            \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg, true); \
+		break;                                                                                                                         \
+	} else                                                                                                                             \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -401,6 +527,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
 #define CRASH_COND(m_cond)                                                                                             \
 #define CRASH_COND(m_cond)                                                                                             \
 	if (unlikely(m_cond)) {                                                                                            \
 	if (unlikely(m_cond)) {                                                                                            \
 		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \
 		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \
+		::godot::_err_flush_stdout();                                                                                  \
 		GENERATE_TRAP();                                                                                               \
 		GENERATE_TRAP();                                                                                               \
 	} else                                                                                                             \
 	} else                                                                                                             \
 		((void)0)
 		((void)0)
@@ -412,11 +539,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * Ensures `m_cond` is false.
  * Ensures `m_cond` is false.
  * If `m_cond` is true, prints `m_msg` and the application crashes.
  * If `m_cond` is true, prints `m_msg` and the application crashes.
  */
  */
-#define CRASH_COND_MSG(m_cond, m_msg)                                                                                                    \
-	if (unlikely(m_cond)) {                                                                                                              \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \
-		GENERATE_TRAP();                                                                                                                 \
-	} else                                                                                                                               \
+#define CRASH_COND_MSG(m_cond, m_msg)                                                                                         \
+	if (unlikely(m_cond)) {                                                                                                   \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", m_msg); \
+		::godot::_err_flush_stdout();                                                                                         \
+		GENERATE_TRAP();                                                                                                      \
+	} else                                                                                                                    \
 		((void)0)
 		((void)0)
 
 
 // Generic error macros.
 // Generic error macros.
@@ -441,11 +569,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  *
  *
  * Prints `m_msg`, and the current function returns.
  * Prints `m_msg`, and the current function returns.
  */
  */
-#define ERR_FAIL_MSG(m_msg)                                                                                       \
-	if (true) {                                                                                                   \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", DEBUG_STR(m_msg)); \
-		return;                                                                                                   \
-	} else                                                                                                        \
+#define ERR_FAIL_MSG(m_msg)                                                                            \
+	if (true) {                                                                                        \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg); \
+		return;                                                                                        \
+	} else                                                                                             \
+		((void)0)
+
+/**
+ * Same as `ERR_FAIL_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_EDMSG(m_msg)                                                                                \
+	if (true) {                                                                                              \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg, true); \
+		return;                                                                                              \
+	} else                                                                                                   \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -468,15 +606,25 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  *
  *
  * Prints `m_msg`, and the current function returns `m_retval`.
  * Prints `m_msg`, and the current function returns `m_retval`.
  */
  */
-#define ERR_FAIL_V_MSG(m_retval, m_msg)                                                                                                      \
-	if (true) {                                                                                                                              \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
-		return m_retval;                                                                                                                     \
-	} else                                                                                                                                   \
+#define ERR_FAIL_V_MSG(m_retval, m_msg)                                                                                           \
+	if (true) {                                                                                                                   \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg); \
+		return m_retval;                                                                                                          \
+	} else                                                                                                                        \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
- * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG.
+ * Same as `ERR_FAIL_V_MSG` but also notifies the editor.
+ */
+#define ERR_FAIL_V_EDMSG(m_retval, m_msg)                                                                                               \
+	if (true) {                                                                                                                         \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg, true); \
+		return m_retval;                                                                                                                \
+	} else                                                                                                                              \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or `ERR_BREAK_MSG`.
  * Only use this macro at the start of a function that has not been implemented yet, or
  * Only use this macro at the start of a function that has not been implemented yet, or
  * if more complex error detection or recovery is required.
  * if more complex error detection or recovery is required.
  *
  *
@@ -485,6 +633,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
 #define ERR_PRINT(m_msg) \
 #define ERR_PRINT(m_msg) \
 	::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg)
 	::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg)
 
 
+/**
+ * Same as `ERR_PRINT` but also notifies the editor.
+ */
+#define ERR_PRINT_ED(m_msg) \
+	::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true)
+
 /**
 /**
  * Prints `m_msg` once during the application lifetime.
  * Prints `m_msg` once during the application lifetime.
  */
  */
@@ -498,6 +652,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
 	} else                                                                      \
 	} else                                                                      \
 		((void)0)
 		((void)0)
 
 
+/**
+ * Same as `ERR_PRINT_ONCE` but also notifies the editor.
+ */
+#define ERR_PRINT_ONCE_ED(m_msg)                                                      \
+	if (true) {                                                                       \
+		static bool first_print = true;                                               \
+		if (first_print) {                                                            \
+			::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
+			first_print = false;                                                      \
+		}                                                                             \
+	} else                                                                            \
+		((void)0)
+
 // Print warning message macros.
 // Print warning message macros.
 
 
 /**
 /**
@@ -506,21 +673,40 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
  * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
  */
  */
 #define WARN_PRINT(m_msg) \
 #define WARN_PRINT(m_msg) \
-	::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true)
+	::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, true)
+
+/**
+ * Same as `WARN_PRINT` but also notifies the editor.
+ */
+#define WARN_PRINT_ED(m_msg) \
+	::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, true)
 
 
 /**
 /**
  * Prints `m_msg` once during the application lifetime.
  * Prints `m_msg` once during the application lifetime.
  *
  *
  * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
  * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
  */
  */
-#define WARN_PRINT_ONCE(m_msg)                                                        \
-	if (true) {                                                                       \
-		static bool first_print = true;                                               \
-		if (first_print) {                                                            \
-			::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
-			first_print = false;                                                      \
-		}                                                                             \
-	} else                                                                            \
+#define WARN_PRINT_ONCE(m_msg)                                                               \
+	if (true) {                                                                              \
+		static bool first_print = true;                                                      \
+		if (first_print) {                                                                   \
+			::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, true); \
+			first_print = false;                                                             \
+		}                                                                                    \
+	} else                                                                                   \
+		((void)0)
+
+/**
+ * Same as `WARN_PRINT_ONCE` but also notifies the editor.
+ */
+#define WARN_PRINT_ONCE_ED(m_msg)                                                           \
+	if (true) {                                                                             \
+		static bool first_print = true;                                                     \
+		if (first_print) {                                                                  \
+			::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, true); \
+			first_print = false;                                                            \
+		}                                                                                   \
+	} else                                                                                  \
 		((void)0)
 		((void)0)
 
 
 // Print deprecated warning message macros.
 // Print deprecated warning message macros.
@@ -528,27 +714,27 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
 /**
 /**
  * Warns that the current function is deprecated.
  * Warns that the current function is deprecated.
  */
  */
-#define WARN_DEPRECATED                                                                                                                              \
-	if (true) {                                                                                                                                      \
-		static SafeFlag warning_shown;                                                                                                               \
-		if (!warning_shown.is_set()) {                                                                                                               \
-			::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", true); \
-			warning_shown.set();                                                                                                                     \
-		}                                                                                                                                            \
-	} else                                                                                                                                           \
+#define WARN_DEPRECATED                                                                                                                                     \
+	if (true) {                                                                                                                                             \
+		static std::atomic<bool> warning_shown;                                                                                                             \
+		if (!warning_shown.load()) {                                                                                                                        \
+			::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, true); \
+			warning_shown.store(true);                                                                                                                      \
+		}                                                                                                                                                   \
+	} else                                                                                                                                                  \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
  * Warns that the current function is deprecated and prints `m_msg`.
  * Warns that the current function is deprecated and prints `m_msg`.
  */
  */
-#define WARN_DEPRECATED_MSG(m_msg)                                                                                                                                     \
-	if (true) {                                                                                                                                                        \
-		static SafeFlag warning_shown;                                                                                                                                 \
-		if (!warning_shown.is_set()) {                                                                                                                                 \
-			::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", DEBUG_STR(m_msg), true); \
-			warning_shown.set();                                                                                                                                       \
-		}                                                                                                                                                              \
-	} else                                                                                                                                                             \
+#define WARN_DEPRECATED_MSG(m_msg)                                                                                                                                 \
+	if (true) {                                                                                                                                                    \
+		static std::atomic<bool> warning_shown;                                                                                                                    \
+		if (!warning_shown.load()) {                                                                                                                               \
+			::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, true); \
+			warning_shown.store(true);                                                                                                                             \
+		}                                                                                                                                                          \
+	} else                                                                                                                                                         \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -560,6 +746,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
 #define CRASH_NOW()                                                                                    \
 #define CRASH_NOW()                                                                                    \
 	if (true) {                                                                                        \
 	if (true) {                                                                                        \
 		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
 		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
+		::godot::_err_flush_stdout();                                                                  \
 		GENERATE_TRAP();                                                                               \
 		GENERATE_TRAP();                                                                               \
 	} else                                                                                             \
 	} else                                                                                             \
 		((void)0)
 		((void)0)
@@ -569,11 +756,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
  *
  *
  * Prints `m_msg`, and then the application crashes.
  * Prints `m_msg`, and then the application crashes.
  */
  */
-#define CRASH_NOW_MSG(m_msg)                                                                                             \
-	if (true) {                                                                                                          \
-		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", DEBUG_STR(m_msg)); \
-		GENERATE_TRAP();                                                                                                 \
-	} else                                                                                                               \
+#define CRASH_NOW_MSG(m_msg)                                                                                  \
+	if (true) {                                                                                               \
+		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", m_msg); \
+		::godot::_err_flush_stdout();                                                                         \
+		GENERATE_TRAP();                                                                                      \
+	} else                                                                                                    \
 		((void)0)
 		((void)0)
 
 
 /**
 /**
@@ -584,6 +772,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
 #define DEV_ASSERT(m_cond)                                                                                                       \
 #define DEV_ASSERT(m_cond)                                                                                                       \
 	if (unlikely(!(m_cond))) {                                                                                                   \
 	if (unlikely(!(m_cond))) {                                                                                                   \
 		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: DEV_ASSERT failed  \"" _STR(m_cond) "\" is false."); \
 		::godot::_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: DEV_ASSERT failed  \"" _STR(m_cond) "\" is false."); \
+		::godot::_err_flush_stdout();                                                                                            \
 		GENERATE_TRAP();                                                                                                         \
 		GENERATE_TRAP();                                                                                                         \
 	} else                                                                                                                       \
 	} else                                                                                                                       \
 		((void)0)
 		((void)0)

+ 26 - 31
src/core/error_macros.cpp

@@ -31,61 +31,56 @@
 #include <godot_cpp/core/error_macros.hpp>
 #include <godot_cpp/core/error_macros.hpp>
 
 
 #include <godot_cpp/godot.hpp>
 #include <godot_cpp/godot.hpp>
+#include <godot_cpp/variant/string.hpp>
 
 
-#include <string>
+#include <cstdio>
 
 
 namespace godot {
 namespace godot {
 
 
-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_is_warning) {
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify, bool p_is_warning) {
 	if (p_is_warning) {
 	if (p_is_warning) {
-		internal::gde_interface->print_warning(p_message, p_function, p_file, p_line);
+		internal::gde_interface->print_warning(p_error, p_function, p_file, p_line, p_editor_notify);
 	} else {
 	} else {
-		internal::gde_interface->print_error(p_message, p_function, p_file, p_line);
+		internal::gde_interface->print_error(p_error, p_function, p_file, p_line, p_editor_notify);
 	}
 	}
 }
 }
 
 
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_is_warning) {
-	if (p_is_warning) {
-		internal::gde_interface->print_warning(p_message, p_function, p_file, p_line);
-	} else {
-		internal::gde_interface->print_error(p_message, p_function, p_file, p_line);
-	}
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify, bool p_is_warning) {
+	_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_editor_notify, p_is_warning);
 }
 }
 
 
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_is_warning) {
+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, bool p_is_warning) {
 	if (p_is_warning) {
 	if (p_is_warning) {
-		internal::gde_interface->print_warning(p_message.utf8().get_data(), p_function, p_file, p_line);
+		internal::gde_interface->print_warning_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify);
 	} else {
 	} else {
-		internal::gde_interface->print_error(p_message.utf8().get_data(), p_function, p_file, p_line);
+		internal::gde_interface->print_error_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify);
 	}
 	}
 }
 }
 
 
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_is_warning) {
-	if (p_is_warning) {
-		internal::gde_interface->print_warning(p_message.utf8().get_data(), p_function, p_file, p_line);
-	} else {
-		internal::gde_interface->print_error(p_message.utf8().get_data(), p_function, p_file, p_line);
-	}
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify, bool p_is_warning) {
+	_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_editor_notify, p_is_warning);
+}
+
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify, bool p_is_warning) {
+	_err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_editor_notify, p_is_warning);
 }
 }
 
 
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_is_warning) {
-	_err_print_error(p_function, p_file, p_line, "", p_error, p_is_warning);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify, bool p_is_warning) {
+	_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_editor_notify, p_is_warning);
 }
 }
 
 
-void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_is_warning) {
-	_err_print_error(p_function, p_file, p_line, "", p_error, p_is_warning);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool p_editor_notify, bool p_fatal) {
+	String fstr(p_fatal ? "FATAL: " : "");
+	String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ").");
+	_err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message, p_editor_notify, false);
 }
 }
 
 
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool fatal) {
-	std::string fstr(fatal ? "FATAL: " : "");
-	std::string err(fstr + "Index " + p_index_str + " = " + std::to_string(p_index) + " is out of bounds (" + p_size_str + " = " + std::to_string(p_size) + ").");
-	_err_print_error(p_function, p_file, p_line, err.c_str(), p_message);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify, bool p_fatal) {
+	_err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), p_editor_notify, p_fatal);
 }
 }
 
 
-void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal) {
-	std::string fstr(fatal ? "FATAL: " : "");
-	std::string err(fstr + "Index " + p_index_str + " = " + std::to_string(p_index) + " is out of bounds (" + p_size_str + " = " + std::to_string(p_size) + ").");
-	_err_print_error(p_function, p_file, p_line, err.c_str(), p_message);
+void _err_flush_stdout() {
+	fflush(stdout);
 }
 }
 
 
 } // namespace godot
 } // namespace godot