@@ -210,8 +210,79 @@ void ResourceSaver::_bind_methods() {
210210 BIND_BITFIELD_FLAG (FLAG_REPLACE_SUBRESOURCE_PATHS);
211211}
212212
213+ // //// Logger ///////
214+
215+ void Logger::_bind_methods () {
216+ GDVIRTUAL_BIND (_log_error, " function" , " file" , " line" , " code" , " rationale" , " editor_notify" , " error_type" , " script_backtraces" );
217+ GDVIRTUAL_BIND (_log_message, " message" , " error" );
218+ BIND_ENUM_CONSTANT (ERROR_TYPE_ERROR);
219+ BIND_ENUM_CONSTANT (ERROR_TYPE_WARNING);
220+ BIND_ENUM_CONSTANT (ERROR_TYPE_SCRIPT);
221+ BIND_ENUM_CONSTANT (ERROR_TYPE_SHADER);
222+ }
223+
224+ void Logger::log_error (const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const TypedArray<ScriptBacktrace> &p_script_backtraces) {
225+ GDVIRTUAL_CALL (_log_error, String::utf8 (p_function), String::utf8 (p_file), p_line, String::utf8 (p_code), String::utf8 (p_rationale), p_editor_notify, p_type, p_script_backtraces);
226+ }
227+
228+ void Logger::log_message (const String &p_text, bool p_error) {
229+ GDVIRTUAL_CALL (_log_message, p_text, p_error);
230+ }
231+
213232// //// OS //////
214233
234+ void OS::LoggerBind::logv (const char *p_format, va_list p_list, bool p_err) {
235+ if (!should_log (p_err) || is_logging) {
236+ return ;
237+ }
238+
239+ is_logging = true ;
240+
241+ constexpr int static_buf_size = 1024 ;
242+ char static_buf[static_buf_size] = { ' \0 ' };
243+ char *buf = static_buf;
244+ va_list list_copy;
245+ va_copy (list_copy, p_list);
246+ int len = vsnprintf (buf, static_buf_size, p_format, p_list);
247+ if (len >= static_buf_size) {
248+ buf = (char *)Memory::alloc_static (len + 1 );
249+ vsnprintf (buf, len + 1 , p_format, list_copy);
250+ }
251+ va_end (list_copy);
252+
253+ String str;
254+ str.append_utf8 (buf, len);
255+ for (Ref<CoreBind::Logger> &logger : loggers) {
256+ logger->log_message (str, p_err);
257+ }
258+
259+ if (len >= static_buf_size) {
260+ Memory::free_static (buf);
261+ }
262+
263+ is_logging = false ;
264+ }
265+
266+ void OS::LoggerBind::log_error (const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const Vector<Ref<ScriptBacktrace>> &p_script_backtraces) {
267+ if (!should_log (true ) || is_logging) {
268+ return ;
269+ }
270+
271+ TypedArray<ScriptBacktrace> backtraces;
272+ backtraces.resize (p_script_backtraces.size ());
273+ for (int i = 0 ; i < p_script_backtraces.size (); i++) {
274+ backtraces[i] = p_script_backtraces[i];
275+ }
276+
277+ is_logging = true ;
278+
279+ for (Ref<CoreBind::Logger> &logger : loggers) {
280+ logger->log_error (p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, CoreBind::Logger::ErrorType (p_type), backtraces);
281+ }
282+
283+ is_logging = false ;
284+ }
285+
215286PackedByteArray OS::get_entropy (int p_bytes) {
216287 PackedByteArray pba;
217288 pba.resize (p_bytes);
@@ -628,6 +699,24 @@ String OS::get_unique_id() const {
628699 return ::OS::get_singleton ()->get_unique_id ();
629700}
630701
702+ void OS::add_logger (const Ref<Logger> &p_logger) {
703+ ERR_FAIL_COND (p_logger.is_null ());
704+
705+ if (!logger_bind) {
706+ logger_bind = memnew (LoggerBind);
707+ ::OS::get_singleton ()->add_logger(logger_bind);
708+ }
709+
710+ ERR_FAIL_COND_MSG (logger_bind->loggers .find (p_logger) != -1 , " Could not add logger, as it has already been added." );
711+ logger_bind->loggers .push_back (p_logger);
712+ }
713+
714+ void OS::remove_logger (const Ref<Logger> &p_logger) {
715+ ERR_FAIL_COND (p_logger.is_null ());
716+ ERR_FAIL_COND_MSG (!logger_bind || logger_bind->loggers .find (p_logger) == -1 , " Could not remove logger, as it hasn't been added." );
717+ logger_bind->loggers .erase (p_logger);
718+ }
719+
631720OS *OS::singleton = nullptr ;
632721
633722void OS::_bind_methods () {
@@ -734,6 +823,9 @@ void OS::_bind_methods() {
734823 ClassDB::bind_method (D_METHOD (" get_granted_permissions" ), &OS::get_granted_permissions);
735824 ClassDB::bind_method (D_METHOD (" revoke_granted_permissions" ), &OS::revoke_granted_permissions);
736825
826+ ClassDB::bind_method (D_METHOD (" add_logger" , " logger" ), &OS::add_logger);
827+ ClassDB::bind_method (D_METHOD (" remove_logger" , " logger" ), &OS::remove_logger);
828+
737829 ADD_PROPERTY (PropertyInfo (Variant::BOOL, " low_processor_usage_mode" ), " set_low_processor_usage_mode" , " is_in_low_processor_usage_mode" );
738830 ADD_PROPERTY (PropertyInfo (Variant::INT, " low_processor_usage_mode_sleep_usec" ), " set_low_processor_usage_mode_sleep_usec" , " get_low_processor_usage_mode_sleep_usec" );
739831 ADD_PROPERTY (PropertyInfo (Variant::BOOL, " delta_smoothing" ), " set_delta_smoothing" , " is_delta_smoothing_enabled" );
@@ -764,6 +856,20 @@ void OS::_bind_methods() {
764856 BIND_ENUM_CONSTANT (STD_HANDLE_UNKNOWN);
765857}
766858
859+ OS::OS () {
860+ singleton = this ;
861+ }
862+
863+ OS::~OS () {
864+ if (singleton == this ) {
865+ singleton = nullptr ;
866+ }
867+
868+ if (logger_bind) {
869+ logger_bind->clear ();
870+ }
871+ }
872+
767873// //// Geometry2D //////
768874
769875Geometry2D *Geometry2D::singleton = nullptr ;
@@ -1898,6 +2004,16 @@ ScriptLanguage *Engine::get_script_language(int p_index) const {
18982004 return ScriptServer::get_language (p_index);
18992005}
19002006
2007+ TypedArray<ScriptBacktrace> Engine::capture_script_backtraces (bool p_include_variables) const {
2008+ Vector<Ref<ScriptBacktrace>> backtraces = ScriptServer::capture_script_backtraces (p_include_variables);
2009+ TypedArray<ScriptBacktrace> result;
2010+ result.resize (backtraces.size ());
2011+ for (int i = 0 ; i < backtraces.size (); i++) {
2012+ result[i] = backtraces[i];
2013+ }
2014+ return result;
2015+ }
2016+
19012017void Engine::set_editor_hint (bool p_enabled) {
19022018 ::Engine::get_singleton ()->set_editor_hint(p_enabled);
19032019}
@@ -1985,6 +2101,7 @@ void Engine::_bind_methods() {
19852101 ClassDB::bind_method (D_METHOD (" unregister_script_language" , " language" ), &Engine::unregister_script_language);
19862102 ClassDB::bind_method (D_METHOD (" get_script_language_count" ), &Engine::get_script_language_count);
19872103 ClassDB::bind_method (D_METHOD (" get_script_language" , " index" ), &Engine::get_script_language);
2104+ ClassDB::bind_method (D_METHOD (" capture_script_backtraces" , " include_variables" ), &Engine::capture_script_backtraces, DEFVAL (false ));
19882105
19892106 ClassDB::bind_method (D_METHOD (" is_editor_hint" ), &Engine::is_editor_hint);
19902107 ClassDB::bind_method (D_METHOD (" is_embedded_in_editor" ), &Engine::is_embedded_in_editor);
0 commit comments