mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 12:12:28 +00:00
Extract logging logic
Previously logging logic was scattered over OS class implementations with plenty of duplication. Major changes in this commit: - Extracted logging logic into a separate Logger hierarchy. It allows easy configuration of logging mechanism depending on compile-time or run-time configuration. - Implemented RotatedFileLogger which is usually used with StdLogger, providing persistency of logs. It is often important to be able to obtain logs of the game even in production to be able to understand what happened prior to some problem. On mobile there previously was no way to obtain the logs aside from having the device connected to your machine. - flush() is not performed in release mode for every logged line. It is only performed for errors.
This commit is contained in:
parent
14b4ad931f
commit
1a2311e350
@ -29,6 +29,7 @@
|
||||
/*************************************************************************/
|
||||
#include "error_macros.h"
|
||||
|
||||
#include "io/logger.h"
|
||||
#include "os/os.h"
|
||||
|
||||
bool _err_error_exists = false;
|
||||
@ -79,7 +80,7 @@ void remove_error_handler(ErrorHandlerList *p_handler) {
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
|
||||
|
||||
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (OS::ErrorType)p_type);
|
||||
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (Logger::ErrorType)p_type);
|
||||
|
||||
_global_lock();
|
||||
ErrorHandlerList *l = error_handler_list;
|
||||
|
@ -76,6 +76,11 @@ protected:
|
||||
};
|
||||
|
||||
public:
|
||||
void flush() {
|
||||
|
||||
f.flush();
|
||||
};
|
||||
|
||||
void store_8(uint8_t p_dest) {
|
||||
|
||||
f.store_8(p_dest);
|
||||
|
@ -338,6 +338,13 @@ Error FileAccessCompressed::get_error() const {
|
||||
return read_eof ? ERR_FILE_EOF : OK;
|
||||
}
|
||||
|
||||
void FileAccessCompressed::flush() {
|
||||
ERR_FAIL_COND(!f);
|
||||
ERR_FAIL_COND(!writing);
|
||||
|
||||
// compressed files keep data in memory till close()
|
||||
}
|
||||
|
||||
void FileAccessCompressed::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_name); ///< return true if a file exists
|
||||
|
@ -268,6 +268,12 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
|
||||
}
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::flush() {
|
||||
ERR_FAIL_COND(!writing);
|
||||
|
||||
// encrypted files keep data in memory till close()
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL_COND(!writing);
|
||||
|
@ -71,6 +71,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
|
||||
|
||||
|
@ -170,6 +170,10 @@ Error FileAccessMemory::get_error() const {
|
||||
return pos >= length ? ERR_FILE_EOF : OK;
|
||||
}
|
||||
|
||||
void FileAccessMemory::flush() {
|
||||
ERR_FAIL_COND(!data);
|
||||
}
|
||||
|
||||
void FileAccessMemory::store_8(uint8_t p_byte) {
|
||||
|
||||
ERR_FAIL_COND(!data);
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_byte); ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
|
||||
|
||||
|
@ -456,6 +456,10 @@ Error FileAccessNetwork::get_error() const {
|
||||
return pos == total_size ? ERR_FILE_EOF : OK;
|
||||
}
|
||||
|
||||
void FileAccessNetwork::flush() {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessNetwork::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL();
|
||||
|
@ -155,6 +155,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_path); ///< return true if a file exists
|
||||
|
@ -293,6 +293,11 @@ Error FileAccessPack::get_error() const {
|
||||
return OK;
|
||||
}
|
||||
|
||||
void FileAccessPack::flush() {
|
||||
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessPack::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL();
|
||||
|
@ -161,6 +161,7 @@ public:
|
||||
|
||||
virtual Error get_error() const;
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest);
|
||||
|
||||
virtual void store_buffer(const uint8_t *p_src, int p_length);
|
||||
|
@ -353,6 +353,11 @@ Error FileAccessZip::get_error() const {
|
||||
return OK;
|
||||
};
|
||||
|
||||
void FileAccessZip::flush() {
|
||||
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessZip::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL();
|
||||
|
@ -108,6 +108,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
virtual bool file_exists(const String &p_name); ///< return true if a file exists
|
||||
|
||||
|
252
core/io/logger.cpp
Normal file
252
core/io/logger.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
/*************************************************************************/
|
||||
/* logger.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "logger.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "os/os.h"
|
||||
#include "print_string.h"
|
||||
|
||||
bool Logger::should_log(bool p_err) {
|
||||
return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
|
||||
}
|
||||
|
||||
void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *err_type = "**ERROR**";
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: err_type = "**ERROR**"; break;
|
||||
case ERR_WARNING: err_type = "**WARNING**"; break;
|
||||
case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
|
||||
case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
|
||||
default: ERR_PRINT("Unknown error type"); break;
|
||||
}
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && *p_rationale)
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
logf_error("%s: %s\n", err_type, err_details);
|
||||
logf_error(" At: %s:%i:%s() - %s\n", p_file, p_line, p_function, p_code);
|
||||
}
|
||||
|
||||
void Logger::logf(const char *p_format, ...) {
|
||||
if (!should_log(false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
|
||||
logv(p_format, argp, false);
|
||||
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
void Logger::logf_error(const char *p_format, ...) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
|
||||
logv(p_format, argp, true);
|
||||
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
Logger::~Logger() {}
|
||||
|
||||
void RotatedFileLogger::close_file() {
|
||||
if (file) {
|
||||
memdelete(file);
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void RotatedFileLogger::clear_old_backups() {
|
||||
int max_backups = max_files - 1; // -1 for the current file
|
||||
|
||||
String basename = base_path.get_basename();
|
||||
String extension = "." + base_path.get_extension();
|
||||
|
||||
DirAccess *da = DirAccess::open(base_path.get_base_dir());
|
||||
if (!da) {
|
||||
return;
|
||||
}
|
||||
|
||||
da->list_dir_begin();
|
||||
String f = da->get_next();
|
||||
Set<String> backups;
|
||||
while (f != String()) {
|
||||
if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path) {
|
||||
backups.insert(f);
|
||||
}
|
||||
f = da->get_next();
|
||||
}
|
||||
da->list_dir_end();
|
||||
|
||||
if (backups.size() > max_backups) {
|
||||
// since backups are appended with timestamp and Set iterates them in sorted order,
|
||||
// first backups are the oldest
|
||||
int to_delete = backups.size() - max_backups;
|
||||
for (Set<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) {
|
||||
da->remove(E->get());
|
||||
}
|
||||
}
|
||||
|
||||
memdelete(da);
|
||||
}
|
||||
|
||||
void RotatedFileLogger::rotate_file() {
|
||||
close_file();
|
||||
|
||||
if (FileAccess::exists(base_path)) {
|
||||
if (max_files > 1) {
|
||||
char timestamp[21];
|
||||
OS::Date date = OS::get_singleton()->get_date();
|
||||
OS::Time time = OS::get_singleton()->get_time();
|
||||
sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day + 1, time.hour, time.min, time.sec);
|
||||
|
||||
String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension();
|
||||
|
||||
DirAccess *da = DirAccess::open(base_path.get_base_dir());
|
||||
if (da) {
|
||||
da->copy(base_path, backup_name);
|
||||
memdelete(da);
|
||||
}
|
||||
clear_old_backups();
|
||||
}
|
||||
} else {
|
||||
DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA);
|
||||
if (da) {
|
||||
da->make_dir_recursive(base_path.get_base_dir());
|
||||
memdelete(da);
|
||||
}
|
||||
}
|
||||
|
||||
file = FileAccess::open(base_path, FileAccess::WRITE);
|
||||
}
|
||||
|
||||
RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) {
|
||||
file = NULL;
|
||||
base_path = p_base_path.simplify_path();
|
||||
max_files = p_max_files > 0 ? p_max_files : 1;
|
||||
|
||||
rotate_file();
|
||||
}
|
||||
|
||||
void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
const int static_buf_size = 512;
|
||||
char static_buf[static_buf_size];
|
||||
char *buf = static_buf;
|
||||
int len = vsnprintf(buf, static_buf_size, p_format, p_list);
|
||||
if (len >= static_buf_size) {
|
||||
buf = (char *)Memory::alloc_static(len + 1);
|
||||
vsnprintf(buf, len + 1, p_format, p_list);
|
||||
}
|
||||
file->store_buffer((uint8_t *)buf, len);
|
||||
if (len >= static_buf_size) {
|
||||
Memory::free_static(buf);
|
||||
}
|
||||
#ifdef DEBUG_ENABLED
|
||||
const bool need_flush = true;
|
||||
#else
|
||||
bool need_flush = p_err;
|
||||
#endif
|
||||
if (need_flush) {
|
||||
file->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RotatedFileLogger::~RotatedFileLogger() {
|
||||
close_file();
|
||||
}
|
||||
|
||||
void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_err) {
|
||||
vfprintf(stderr, p_format, p_list);
|
||||
} else {
|
||||
vprintf(p_format, p_list);
|
||||
#ifdef DEBUG_ENABLED
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
StdLogger::~StdLogger() {}
|
||||
|
||||
CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) {
|
||||
loggers = p_loggers;
|
||||
}
|
||||
|
||||
void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loggers.size(); ++i) {
|
||||
va_list list_copy;
|
||||
va_copy(list_copy, p_list);
|
||||
loggers[i]->logv(p_format, list_copy, p_err);
|
||||
va_end(list_copy);
|
||||
}
|
||||
}
|
||||
|
||||
void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loggers.size(); ++i) {
|
||||
loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
|
||||
}
|
||||
}
|
||||
|
||||
CompositeLogger::~CompositeLogger() {
|
||||
for (int i = 0; i < loggers.size(); ++i) {
|
||||
memdelete(loggers[i]);
|
||||
}
|
||||
}
|
107
core/io/logger.h
Normal file
107
core/io/logger.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*************************************************************************/
|
||||
/* logger.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include "os/file_access.h"
|
||||
#include "ustring.h"
|
||||
#include "vector.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
class Logger {
|
||||
protected:
|
||||
bool should_log(bool p_err);
|
||||
|
||||
public:
|
||||
enum ErrorType {
|
||||
ERR_ERROR,
|
||||
ERR_WARNING,
|
||||
ERR_SCRIPT,
|
||||
ERR_SHADER
|
||||
};
|
||||
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err) = 0;
|
||||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
|
||||
void logf(const char *p_format, ...);
|
||||
void logf_error(const char *p_format, ...);
|
||||
|
||||
virtual ~Logger();
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes messages to stdout/stderr.
|
||||
*/
|
||||
class StdLogger : public Logger {
|
||||
|
||||
public:
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
virtual ~StdLogger();
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes messages to the specified file. If the file already exists, creates a copy (backup)
|
||||
* of it with timestamp appended to the file name. Maximum number of backups is configurable.
|
||||
* When maximum is reached, the oldest backups are erased. With the maximum being equal to 1,
|
||||
* it acts as a simple file logger.
|
||||
*/
|
||||
class RotatedFileLogger : public Logger {
|
||||
String base_path;
|
||||
int max_files;
|
||||
|
||||
FileAccess *file;
|
||||
|
||||
void rotate_file_without_closing();
|
||||
void close_file();
|
||||
void clear_old_backups();
|
||||
void rotate_file();
|
||||
|
||||
public:
|
||||
RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
|
||||
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
|
||||
virtual ~RotatedFileLogger();
|
||||
};
|
||||
|
||||
class CompositeLogger : public Logger {
|
||||
Vector<Logger *> loggers;
|
||||
|
||||
public:
|
||||
CompositeLogger(Vector<Logger *> p_loggers);
|
||||
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
|
||||
virtual ~CompositeLogger();
|
||||
};
|
||||
|
||||
#endif
|
@ -55,7 +55,7 @@ FileAccess *FileAccess::create(AccessType p_access) {
|
||||
|
||||
bool FileAccess::exists(const String &p_name) {
|
||||
|
||||
if (PackedData::get_singleton()->has_path(p_name))
|
||||
if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name))
|
||||
return true;
|
||||
|
||||
FileAccess *f = open(p_name, READ);
|
||||
|
@ -119,6 +119,7 @@ public:
|
||||
|
||||
virtual Error get_error() const = 0; ///< get last error
|
||||
|
||||
virtual void flush() = 0;
|
||||
virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
|
||||
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
|
||||
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
|
||||
|
@ -62,20 +62,20 @@ void OS::debug_break(){
|
||||
// something
|
||||
};
|
||||
|
||||
void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
|
||||
const char *err_type = "**ERROR**";
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: err_type = "**ERROR**"; break;
|
||||
case ERR_WARNING: err_type = "**WARNING**"; break;
|
||||
case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
|
||||
case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
|
||||
default: ERR_PRINT("Unknown error type"); break;
|
||||
void OS::_set_logger(Logger *p_logger) {
|
||||
if (_logger) {
|
||||
memdelete(_logger);
|
||||
}
|
||||
_logger = p_logger;
|
||||
}
|
||||
|
||||
if (p_rationale && *p_rationale)
|
||||
print("%s: %s\n ", err_type, p_rationale);
|
||||
print("%s: At: %s:%i:%s() - %s\n", err_type, p_file, p_line, p_function, p_code);
|
||||
void OS::initialize_logger() {
|
||||
_set_logger(memnew(StdLogger));
|
||||
}
|
||||
|
||||
void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) {
|
||||
|
||||
_logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
|
||||
}
|
||||
|
||||
void OS::print(const char *p_format, ...) {
|
||||
@ -83,17 +83,16 @@ void OS::print(const char *p_format, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
|
||||
vprint(p_format, argp);
|
||||
_logger->logv(p_format, argp, false);
|
||||
|
||||
va_end(argp);
|
||||
};
|
||||
|
||||
void OS::printerr(const char *p_format, ...) {
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
|
||||
vprint(p_format, argp, true);
|
||||
_logger->logv(p_format, argp, true);
|
||||
|
||||
va_end(argp);
|
||||
};
|
||||
@ -533,9 +532,12 @@ OS::OS() {
|
||||
|
||||
_allow_hidpi = true;
|
||||
_stack_bottom = (void *)(&stack_bottom);
|
||||
|
||||
_logger = NULL;
|
||||
_set_logger(memnew(StdLogger));
|
||||
}
|
||||
|
||||
OS::~OS() {
|
||||
|
||||
memdelete(_logger);
|
||||
singleton = NULL;
|
||||
}
|
||||
|
21
core/os/os.h
21
core/os/os.h
@ -32,6 +32,7 @@
|
||||
|
||||
#include "engine.h"
|
||||
#include "image.h"
|
||||
#include "io/logger.h"
|
||||
#include "list.h"
|
||||
#include "os/main_loop.h"
|
||||
#include "ustring.h"
|
||||
@ -61,6 +62,11 @@ class OS {
|
||||
|
||||
void *_stack_bottom;
|
||||
|
||||
Logger *_logger;
|
||||
|
||||
protected:
|
||||
void _set_logger(Logger *p_logger);
|
||||
|
||||
public:
|
||||
typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection);
|
||||
|
||||
@ -108,6 +114,7 @@ protected:
|
||||
virtual int get_audio_driver_count() const = 0;
|
||||
virtual const char *get_audio_driver_name(int p_driver) const = 0;
|
||||
|
||||
virtual void initialize_logger();
|
||||
virtual void initialize_core() = 0;
|
||||
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0;
|
||||
|
||||
@ -127,18 +134,10 @@ public:
|
||||
|
||||
static OS *get_singleton();
|
||||
|
||||
enum ErrorType {
|
||||
ERR_ERROR,
|
||||
ERR_WARNING,
|
||||
ERR_SCRIPT,
|
||||
ERR_SHADER
|
||||
};
|
||||
void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR);
|
||||
void print(const char *p_format, ...);
|
||||
void printerr(const char *p_format, ...);
|
||||
|
||||
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
|
||||
virtual void print(const char *p_format, ...);
|
||||
virtual void printerr(const char *p_format, ...);
|
||||
virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false) = 0;
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0;
|
||||
virtual String get_stdin_string(bool p_block = true) = 0;
|
||||
|
||||
|
@ -223,6 +223,12 @@ Error FileAccessUnix::get_error() const {
|
||||
return last_error;
|
||||
}
|
||||
|
||||
void FileAccessUnix::flush() {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
void FileAccessUnix::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
|
@ -72,6 +72,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_path); ///< return true if a file exists
|
||||
|
@ -64,39 +64,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
extern bool _print_error_enabled;
|
||||
|
||||
void OS_Unix::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
|
||||
if (!_print_error_enabled)
|
||||
return;
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && p_rationale[0])
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
switch (p_type) {
|
||||
case ERR_ERROR:
|
||||
print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
print("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_WARNING:
|
||||
print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
print("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SCRIPT:
|
||||
print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
print("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SHADER:
|
||||
print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
print("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#include <unistd.h>
|
||||
|
||||
void OS_Unix::debug_break() {
|
||||
|
||||
@ -165,29 +133,16 @@ void OS_Unix::initialize_core() {
|
||||
}
|
||||
}
|
||||
|
||||
void OS_Unix::initialize_logger() {
|
||||
Vector<Logger *> loggers;
|
||||
loggers.push_back(memnew(UnixTerminalLogger));
|
||||
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
|
||||
_set_logger(memnew(CompositeLogger(loggers)));
|
||||
}
|
||||
|
||||
void OS_Unix::finalize_core() {
|
||||
}
|
||||
|
||||
void OS_Unix::vprint(const char *p_format, va_list p_list, bool p_stder) {
|
||||
|
||||
if (p_stder) {
|
||||
|
||||
vfprintf(stderr, p_format, p_list);
|
||||
fflush(stderr);
|
||||
} else {
|
||||
|
||||
vprintf(p_format, p_list);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void OS_Unix::print(const char *p_format, ...) {
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
vprintf(p_format, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
void OS_Unix::alert(const String &p_alert, const String &p_title) {
|
||||
|
||||
fprintf(stderr, "ERROR: %s\n", p_alert.utf8().get_data());
|
||||
@ -559,4 +514,38 @@ String OS_Unix::get_executable_path() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && p_rationale[0])
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
switch (p_type) {
|
||||
case ERR_WARNING:
|
||||
logf_error("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SCRIPT:
|
||||
logf_error("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SHADER:
|
||||
logf_error("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
logf_error("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_ERROR:
|
||||
default:
|
||||
logf_error("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
logf_error("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UnixTerminalLogger::~UnixTerminalLogger() {}
|
||||
|
||||
#endif
|
||||
|
@ -54,11 +54,11 @@ protected:
|
||||
virtual int get_audio_driver_count() const;
|
||||
virtual const char *get_audio_driver_name(int p_driver) const;
|
||||
|
||||
virtual void initialize_logger();
|
||||
virtual void initialize_core();
|
||||
virtual int unix_initialize_audio(int p_audio_driver);
|
||||
//virtual void initialize(int p_video_driver,int p_audio_driver);
|
||||
|
||||
//virtual void finalize();
|
||||
virtual void finalize_core();
|
||||
|
||||
String stdin_buf;
|
||||
@ -66,10 +66,6 @@ protected:
|
||||
String get_global_settings_path() const;
|
||||
|
||||
public:
|
||||
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
|
||||
virtual void print(const char *p_format, ...);
|
||||
virtual void vprint(const char *p_format, va_list p_list, bool p_stder = false);
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
virtual String get_stdin_string(bool p_block);
|
||||
|
||||
@ -120,6 +116,12 @@ public:
|
||||
//virtual void run( MainLoop * p_main_loop );
|
||||
};
|
||||
|
||||
class UnixTerminalLogger : public StdLogger {
|
||||
public:
|
||||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
virtual ~UnixTerminalLogger();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
71
drivers/unix/syslog_logger.cpp
Normal file
71
drivers/unix/syslog_logger.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*************************************************************************/
|
||||
/* syslog_logger.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#include "syslog_logger.h"
|
||||
#include "print_string.h"
|
||||
#include <syslog.h>
|
||||
|
||||
void SyslogLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vsyslog(p_err ? LOG_ERR : LOG_INFO, p_format, p_list);
|
||||
}
|
||||
|
||||
void SyslogLogger::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *err_type = "**ERROR**";
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: err_type = "**ERROR**"; break;
|
||||
case ERR_WARNING: err_type = "**WARNING**"; break;
|
||||
case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
|
||||
case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
|
||||
default: ERR_PRINT("Unknown error type"); break;
|
||||
}
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && *p_rationale)
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
syslog(p_type == ERR_WARNING ? LOG_WARNING : LOG_ERR, "%s: %s\n At: %s:%i:%s() - %s", err_type, err_details, p_file, p_line, p_function, p_code);
|
||||
}
|
||||
|
||||
SyslogLogger::~SyslogLogger() {
|
||||
}
|
||||
|
||||
#endif
|
48
drivers/unix/syslog_logger.h
Normal file
48
drivers/unix/syslog_logger.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*************************************************************************/
|
||||
/* syslog_logger.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef SYSLOG_LOGGER_H
|
||||
#define SYSLOG_LOGGER_H
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#include "io/logger.h"
|
||||
|
||||
class SyslogLogger : public Logger {
|
||||
public:
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
|
||||
|
||||
virtual ~SyslogLogger();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -162,10 +162,10 @@ Error DirAccessWindows::make_dir(String p_dir) {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION
|
||||
|
||||
p_dir = fix_path(p_dir);
|
||||
if (p_dir.is_rel_path())
|
||||
p_dir = get_current_dir().plus_file(p_dir);
|
||||
|
||||
p_dir = fix_path(p_dir);
|
||||
p_dir = p_dir.replace("/", "\\");
|
||||
|
||||
bool success;
|
||||
|
@ -207,6 +207,12 @@ Error FileAccessWindows::get_error() const {
|
||||
return last_error;
|
||||
}
|
||||
|
||||
void FileAccessWindows::flush() {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
void FileAccessWindows::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_name); ///< return true if a file exists
|
||||
|
@ -231,7 +231,6 @@ void Main::print_help(const char *p_binary) {
|
||||
}
|
||||
|
||||
Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_phase) {
|
||||
|
||||
RID_OwnerBase::init_rid();
|
||||
|
||||
OS::get_singleton()->initialize_core();
|
||||
@ -254,6 +253,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||
|
||||
register_core_settings(); //here globals is present
|
||||
|
||||
OS::get_singleton()->initialize_logger();
|
||||
|
||||
translation_server = memnew(TranslationServer);
|
||||
performance = memnew(Performance);
|
||||
globals->add_singleton(ProjectSettings::Singleton("Performance", performance));
|
||||
|
@ -146,6 +146,11 @@ Error FileAccessAndroid::get_error() const {
|
||||
return eof ? ERR_FILE_EOF : OK; //not sure what else it may happen
|
||||
}
|
||||
|
||||
void FileAccessAndroid::flush() {
|
||||
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessAndroid::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL();
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_path); ///< return true if a file exists
|
||||
|
@ -157,6 +157,9 @@ Error FileAccessJAndroid::get_error() const {
|
||||
return OK;
|
||||
}
|
||||
|
||||
void FileAccessJAndroid::flush() {
|
||||
}
|
||||
|
||||
void FileAccessJAndroid::store_8(uint8_t p_dest) {
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ public:
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_path); ///< return true if a file exists
|
||||
|
@ -47,6 +47,15 @@
|
||||
#include "file_access_jandroid.h"
|
||||
#endif
|
||||
|
||||
class AndroidLogger : public Logger {
|
||||
public:
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
__android_log_vprint(p_err ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "godot", p_format, p_list);
|
||||
}
|
||||
|
||||
virtual ~AndroidLogger() {}
|
||||
};
|
||||
|
||||
int OS_Android::get_video_driver_count() const {
|
||||
|
||||
return 1;
|
||||
@ -111,6 +120,13 @@ void OS_Android::initialize_core() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void OS_Android::initialize_logger() {
|
||||
Vector<Logger *> loggers;
|
||||
loggers.push_back(memnew(AndroidLogger));
|
||||
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
|
||||
_set_logger(memnew(CompositeLogger(loggers)));
|
||||
}
|
||||
|
||||
void OS_Android::set_opengl_extensions(const char *p_gl_extensions) {
|
||||
|
||||
ERR_FAIL_COND(!p_gl_extensions);
|
||||
@ -162,23 +178,9 @@ void OS_Android::delete_main_loop() {
|
||||
}
|
||||
|
||||
void OS_Android::finalize() {
|
||||
|
||||
memdelete(input);
|
||||
}
|
||||
|
||||
void OS_Android::vprint(const char *p_format, va_list p_list, bool p_stderr) {
|
||||
|
||||
__android_log_vprint(p_stderr ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "godot", p_format, p_list);
|
||||
}
|
||||
|
||||
void OS_Android::print(const char *p_format, ...) {
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
__android_log_vprint(ANDROID_LOG_INFO, "godot", p_format, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
void OS_Android::alert(const String &p_alert, const String &p_title) {
|
||||
|
||||
//print("ALERT: %s\n", p_alert.utf8().get_data());
|
||||
@ -737,6 +739,8 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI
|
||||
set_keep_screen_on_func = p_set_keep_screen_on_func;
|
||||
alert_func = p_alert_func;
|
||||
use_reload_hooks = false;
|
||||
|
||||
_set_logger(memnew(AndroidLogger));
|
||||
}
|
||||
|
||||
OS_Android::~OS_Android() {
|
||||
|
@ -149,6 +149,7 @@ public:
|
||||
virtual int get_audio_driver_count() const;
|
||||
virtual const char *get_audio_driver_name(int p_driver) const;
|
||||
|
||||
virtual void initialize_logger();
|
||||
virtual void initialize_core();
|
||||
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
|
||||
|
||||
@ -161,8 +162,6 @@ public:
|
||||
|
||||
static OS *get_singleton();
|
||||
|
||||
virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
|
||||
virtual void print(const char *p_format, ...);
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
|
||||
virtual void set_mouse_show(bool p_show);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "core/os/dir_access.h"
|
||||
#include "core/os/file_access.h"
|
||||
#include "core/project_settings.h"
|
||||
#include "drivers/unix/syslog_logger.h"
|
||||
|
||||
#include "sem_iphone.h"
|
||||
|
||||
@ -99,6 +100,13 @@ void OSIPhone::initialize_core() {
|
||||
SemaphoreIphone::make_default();
|
||||
};
|
||||
|
||||
void OSIPhone::initialize_logger() {
|
||||
Vector<Logger *> loggers;
|
||||
loggers.push_back(memnew(SyslogLogger));
|
||||
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
|
||||
_set_logger(memnew(CompositeLogger(loggers)));
|
||||
}
|
||||
|
||||
void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
|
||||
|
||||
supported_orientations = 0;
|
||||
@ -570,6 +578,8 @@ OSIPhone::OSIPhone(int width, int height) {
|
||||
vm.resizable = false;
|
||||
set_video_mode(vm);
|
||||
event_count = 0;
|
||||
|
||||
_set_logger(memnew(SyslogLogger));
|
||||
};
|
||||
|
||||
OSIPhone::~OSIPhone() {
|
||||
|
@ -91,6 +91,7 @@ private:
|
||||
|
||||
virtual VideoMode get_default_video_mode() const;
|
||||
|
||||
virtual void initialize_logger();
|
||||
virtual void initialize_core();
|
||||
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
|
||||
|
||||
|
@ -85,6 +85,10 @@ void OS_JavaScript::initialize_core() {
|
||||
FileAccess::make_default<FileAccessBufferedFA<FileAccessUnix> >(FileAccess::ACCESS_RESOURCES);
|
||||
}
|
||||
|
||||
void OS_JavaScript::initialize_logger() {
|
||||
_set_logger(memnew(StdLogger));
|
||||
}
|
||||
|
||||
void OS_JavaScript::set_opengl_extensions(const char *p_gl_extensions) {
|
||||
|
||||
ERR_FAIL_COND(!p_gl_extensions);
|
||||
|
@ -92,6 +92,7 @@ public:
|
||||
virtual int get_audio_driver_count() const;
|
||||
virtual const char *get_audio_driver_name(int p_driver) const;
|
||||
|
||||
virtual void initialize_logger();
|
||||
virtual void initialize_core();
|
||||
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
|
||||
|
||||
@ -104,11 +105,6 @@ public:
|
||||
|
||||
//static OS* get_singleton();
|
||||
|
||||
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
|
||||
OS::print_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
|
||||
}
|
||||
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
|
||||
virtual void set_mouse_mode(MouseMode p_mode);
|
||||
|
@ -129,6 +129,7 @@ protected:
|
||||
virtual const char *get_video_driver_name(int p_driver) const;
|
||||
virtual VideoMode get_default_video_mode() const;
|
||||
|
||||
virtual void initialize_logger();
|
||||
virtual void initialize_core();
|
||||
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
|
||||
virtual void finalize();
|
||||
@ -143,8 +144,6 @@ public:
|
||||
|
||||
virtual String get_name();
|
||||
|
||||
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
|
||||
virtual void set_cursor_shape(CursorShape p_shape);
|
||||
|
@ -1145,43 +1145,67 @@ String OS_OSX::get_name() {
|
||||
return "OSX";
|
||||
}
|
||||
|
||||
void OS_OSX::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||
if (!_print_error_enabled)
|
||||
return;
|
||||
class OSXTerminalLogger : public StdLogger {
|
||||
public:
|
||||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && p_rationale[0])
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
const char *err_details;
|
||||
if (p_rationale && p_rationale[0])
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
switch (p_type) {
|
||||
case ERR_ERROR:
|
||||
os_log_error(OS_LOG_DEFAULT, "ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
|
||||
print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
print("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_WARNING:
|
||||
os_log_info(OS_LOG_DEFAULT, "WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
|
||||
print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
print("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SCRIPT:
|
||||
os_log_error(OS_LOG_DEFAULT, "SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
|
||||
print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
print("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SHADER:
|
||||
os_log_error(OS_LOG_DEFAULT, "SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
|
||||
print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
print("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
switch (p_type) {
|
||||
case ERR_WARNING:
|
||||
os_log_info(OS_LOG_DEFAULT,
|
||||
"WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.",
|
||||
p_function, err_details, p_file, p_line);
|
||||
logf_error("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function,
|
||||
err_details);
|
||||
logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SCRIPT:
|
||||
os_log_error(OS_LOG_DEFAULT,
|
||||
"SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
|
||||
p_function, err_details, p_file, p_line);
|
||||
logf_error("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function,
|
||||
err_details);
|
||||
logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SHADER:
|
||||
os_log_error(OS_LOG_DEFAULT,
|
||||
"SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
|
||||
p_function, err_details, p_file, p_line);
|
||||
logf_error("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function,
|
||||
err_details);
|
||||
logf_error("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_ERROR:
|
||||
default:
|
||||
os_log_error(OS_LOG_DEFAULT,
|
||||
"ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
|
||||
p_function, err_details, p_file, p_line);
|
||||
logf_error("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
|
||||
logf_error("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
OS_Unix::print_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
|
||||
|
||||
typedef UnixTerminalLogger OSXTerminalLogger;
|
||||
#endif
|
||||
|
||||
void OS_OSX::initialize_logger() {
|
||||
Vector<Logger *> loggers;
|
||||
loggers.push_back(memnew(OSXTerminalLogger));
|
||||
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
|
||||
_set_logger(memnew(CompositeLogger(loggers)));
|
||||
}
|
||||
|
||||
void OS_OSX::alert(const String &p_alert, const String &p_title) {
|
||||
@ -2003,6 +2027,8 @@ OS_OSX::OS_OSX() {
|
||||
window_size = Vector2(1024, 600);
|
||||
zoomed = false;
|
||||
display_scale = 1.0;
|
||||
|
||||
_set_logger(memnew(OSXTerminalLogger));
|
||||
}
|
||||
|
||||
bool OS_OSX::_check_internal_feature_support(const String &p_feature) {
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "platform/windows/packet_peer_udp_winsock.h"
|
||||
#include "platform/windows/stream_peer_winsock.h"
|
||||
#include "platform/windows/tcp_server_winsock.h"
|
||||
#include "platform/windows/windows_terminal_logger.h"
|
||||
#include "project_settings.h"
|
||||
#include "servers/audio_server.h"
|
||||
#include "servers/visual/visual_server_raster.h"
|
||||
@ -182,6 +183,13 @@ void OSUWP::initialize_core() {
|
||||
cursor_shape = CURSOR_ARROW;
|
||||
}
|
||||
|
||||
void OSUWP::initialize_logger() {
|
||||
Vector<Logger *> loggers;
|
||||
loggers.push_back(memnew(WindowsTerminalLogger));
|
||||
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
|
||||
_set_logger(memnew(CompositeLogger(loggers)));
|
||||
}
|
||||
|
||||
bool OSUWP::can_draw() const {
|
||||
|
||||
return !minimized;
|
||||
@ -371,32 +379,6 @@ void OSUWP::finalize() {
|
||||
void OSUWP::finalize_core() {
|
||||
}
|
||||
|
||||
void OSUWP::vprint(const char *p_format, va_list p_list, bool p_stderr) {
|
||||
|
||||
char buf[16384 + 1];
|
||||
int len = vsnprintf(buf, 16384, p_format, p_list);
|
||||
if (len <= 0)
|
||||
return;
|
||||
buf[len] = 0;
|
||||
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
|
||||
if (wlen < 0)
|
||||
return;
|
||||
|
||||
wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
|
||||
wbuf[wlen] = 0;
|
||||
|
||||
if (p_stderr)
|
||||
fwprintf(stderr, L"%s", wbuf);
|
||||
else
|
||||
wprintf(L"%s", wbuf);
|
||||
|
||||
free(wbuf);
|
||||
|
||||
fflush(stdout);
|
||||
};
|
||||
|
||||
void OSUWP::alert(const String &p_alert, const String &p_title) {
|
||||
|
||||
Platform::String ^ alert = ref new Platform::String(p_alert.c_str());
|
||||
@ -520,30 +502,6 @@ OS::VideoMode OSUWP::get_video_mode(int p_screen) const {
|
||||
void OSUWP::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
|
||||
}
|
||||
|
||||
void OSUWP::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && p_rationale[0])
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
switch (p_type) {
|
||||
case ERR_ERROR:
|
||||
print("ERROR: %s: %s\n", p_function, err_details);
|
||||
print(" At: %s:%i\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_WARNING:
|
||||
print("WARNING: %s: %s\n", p_function, err_details);
|
||||
print(" At: %s:%i\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SCRIPT:
|
||||
print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
|
||||
print(" At: %s:%i\n", p_file, p_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String OSUWP::get_name() {
|
||||
|
||||
return "UWP";
|
||||
@ -890,6 +848,8 @@ OSUWP::OSUWP() {
|
||||
mouse_mode_changed = CreateEvent(NULL, TRUE, FALSE, L"os_mouse_mode_changed");
|
||||
|
||||
AudioDriverManager::add_driver(&audio_driver);
|
||||
|
||||
_set_logger(memnew(WindowsTerminalLogger));
|
||||
}
|
||||
|
||||
OSUWP::~OSUWP() {
|
||||
|
@ -163,6 +163,7 @@ protected:
|
||||
virtual int get_audio_driver_count() const;
|
||||
virtual const char *get_audio_driver_name(int p_driver) const;
|
||||
|
||||
virtual void initialize_logger();
|
||||
virtual void initialize_core();
|
||||
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
|
||||
|
||||
@ -180,9 +181,6 @@ public:
|
||||
// Event to send to the app wrapper
|
||||
HANDLE mouse_mode_changed;
|
||||
|
||||
void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
|
||||
|
||||
virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
String get_stdin_string(bool p_block);
|
||||
|
||||
|
@ -19,6 +19,7 @@ common_win = [
|
||||
"stream_peer_winsock.cpp",
|
||||
"joypad.cpp",
|
||||
"power_windows.cpp",
|
||||
"windows_terminal_logger.cpp"
|
||||
]
|
||||
|
||||
restarget = "godot_res" + env["OBJSUFFIX"]
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "servers/visual/visual_server_wrap_mt.h"
|
||||
#include "stream_peer_winsock.h"
|
||||
#include "tcp_server_winsock.h"
|
||||
#include "windows_terminal_logger.h"
|
||||
|
||||
#include <process.h>
|
||||
#include <regstr.h>
|
||||
@ -205,6 +206,13 @@ void OS_Windows::initialize_core() {
|
||||
cursor_shape = CURSOR_ARROW;
|
||||
}
|
||||
|
||||
void OS_Windows::initialize_logger() {
|
||||
Vector<Logger *> loggers;
|
||||
loggers.push_back(memnew(WindowsTerminalLogger));
|
||||
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
|
||||
_set_logger(memnew(CompositeLogger(loggers)));
|
||||
}
|
||||
|
||||
bool OS_Windows::can_draw() const {
|
||||
|
||||
return !minimized;
|
||||
@ -1231,38 +1239,6 @@ void OS_Windows::finalize_core() {
|
||||
StreamPeerWinsock::cleanup();
|
||||
}
|
||||
|
||||
void OS_Windows::vprint(const char *p_format, va_list p_list, bool p_stderr) {
|
||||
|
||||
const unsigned int BUFFER_SIZE = 16384;
|
||||
char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
|
||||
int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
|
||||
if (len <= 0)
|
||||
return;
|
||||
if (len >= BUFFER_SIZE)
|
||||
len = BUFFER_SIZE; // Output is too big, will be truncated
|
||||
buf[len] = 0;
|
||||
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
|
||||
if (wlen < 0)
|
||||
return;
|
||||
|
||||
wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
|
||||
wbuf[wlen] = 0;
|
||||
|
||||
if (p_stderr)
|
||||
fwprintf(stderr, L"%ls", wbuf);
|
||||
else
|
||||
wprintf(L"%ls", wbuf);
|
||||
|
||||
#ifdef STDOUT_FILE
|
||||
//vwfprintf(stdo,p_format,p_list);
|
||||
#endif
|
||||
free(wbuf);
|
||||
|
||||
fflush(stdout);
|
||||
};
|
||||
|
||||
void OS_Windows::alert(const String &p_alert, const String &p_title) {
|
||||
|
||||
if (!is_no_window_mode_enabled())
|
||||
@ -1676,107 +1652,6 @@ void OS_Windows::request_attention() {
|
||||
FlashWindowEx(&info);
|
||||
}
|
||||
|
||||
void OS_Windows::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
|
||||
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (!hCon || hCon == INVALID_HANDLE_VALUE) {
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && p_rationale[0])
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
switch (p_type) {
|
||||
case ERR_ERROR:
|
||||
print("ERROR: %s: %s\n", p_function, err_details);
|
||||
print(" At: %s:%i\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_WARNING:
|
||||
print("WARNING: %s: %s\n", p_function, err_details);
|
||||
print(" At: %s:%i\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SCRIPT:
|
||||
print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
|
||||
print(" At: %s:%i\n", p_file, p_line);
|
||||
break;
|
||||
case ERR_SHADER:
|
||||
print("SHADER ERROR: %s: %s\n", p_function, err_details);
|
||||
print(" At: %s:%i\n", p_file, p_line);
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
|
||||
GetConsoleScreenBufferInfo(hCon, &sbi);
|
||||
|
||||
WORD current_fg = sbi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||
WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
|
||||
|
||||
uint32_t basecol = 0;
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: basecol = FOREGROUND_RED; break;
|
||||
case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
|
||||
case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
|
||||
case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
|
||||
}
|
||||
|
||||
basecol |= current_bg;
|
||||
|
||||
if (p_rationale && p_rationale[0]) {
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: print("ERROR: "); break;
|
||||
case ERR_WARNING: print("WARNING: "); break;
|
||||
case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
|
||||
case ERR_SHADER: print("SHADER ERROR: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
|
||||
print("%s\n", p_rationale);
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: print(" At: "); break;
|
||||
case ERR_WARNING: print(" At: "); break;
|
||||
case ERR_SCRIPT: print(" At: "); break;
|
||||
case ERR_SHADER: print(" At: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg);
|
||||
print("%s:%i\n", p_file, p_line);
|
||||
|
||||
} else {
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: print("ERROR: %s: ", p_function); break;
|
||||
case ERR_WARNING: print("WARNING: %s: ", p_function); break;
|
||||
case ERR_SCRIPT: print("SCRIPT ERROR: %s: ", p_function); break;
|
||||
case ERR_SHADER: print("SCRIPT ERROR: %s: ", p_function); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
|
||||
print("%s\n", p_code);
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: print(" At: "); break;
|
||||
case ERR_WARNING: print(" At: "); break;
|
||||
case ERR_SCRIPT: print(" At: "); break;
|
||||
case ERR_SHADER: print(" At: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg);
|
||||
print("%s:%i\n", p_file, p_line);
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, sbi.wAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
String OS_Windows::get_name() {
|
||||
|
||||
return "Windows";
|
||||
@ -2402,6 +2277,8 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
|
||||
#ifdef XAUDIO2_ENABLED
|
||||
AudioDriverManager::add_driver(&driver_xaudio2);
|
||||
#endif
|
||||
|
||||
_set_logger(memnew(WindowsTerminalLogger));
|
||||
}
|
||||
|
||||
OS_Windows::~OS_Windows() {
|
||||
|
@ -152,6 +152,7 @@ protected:
|
||||
virtual int get_audio_driver_count() const;
|
||||
virtual const char *get_audio_driver_name(int p_driver) const;
|
||||
|
||||
virtual void initialize_logger();
|
||||
virtual void initialize_core();
|
||||
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
|
||||
|
||||
@ -180,9 +181,6 @@ protected:
|
||||
public:
|
||||
LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
|
||||
|
||||
virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
String get_stdin_string(bool p_block);
|
||||
|
||||
|
157
platform/windows/windows_terminal_logger.cpp
Normal file
157
platform/windows/windows_terminal_logger.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/*************************************************************************/
|
||||
/* windows_terminal_logger.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "windows_terminal_logger.h"
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int BUFFER_SIZE = 16384;
|
||||
char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
|
||||
int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
|
||||
if (len <= 0)
|
||||
return;
|
||||
if (len >= BUFFER_SIZE)
|
||||
len = BUFFER_SIZE; // Output is too big, will be truncated
|
||||
buf[len] = 0;
|
||||
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
|
||||
if (wlen < 0)
|
||||
return;
|
||||
|
||||
wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
|
||||
wbuf[wlen] = 0;
|
||||
|
||||
if (p_err)
|
||||
fwprintf(stderr, L"%ls", wbuf);
|
||||
else
|
||||
wprintf(L"%ls", wbuf);
|
||||
|
||||
free(wbuf);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef UWP_ENABLED
|
||||
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (!hCon || hCon == INVALID_HANDLE_VALUE) {
|
||||
#endif
|
||||
StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
|
||||
#ifndef UWP_ENABLED
|
||||
} else {
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
|
||||
GetConsoleScreenBufferInfo(hCon, &sbi);
|
||||
|
||||
WORD current_fg = sbi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||
WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
|
||||
|
||||
uint32_t basecol = 0;
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: basecol = FOREGROUND_RED; break;
|
||||
case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
|
||||
case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
|
||||
case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
|
||||
}
|
||||
|
||||
basecol |= current_bg;
|
||||
|
||||
if (p_rationale && p_rationale[0]) {
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: logf("ERROR: "); break;
|
||||
case ERR_WARNING: logf("WARNING: "); break;
|
||||
case ERR_SCRIPT: logf("SCRIPT ERROR: "); break;
|
||||
case ERR_SHADER: logf("SHADER ERROR: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
|
||||
logf("%s\n", p_rationale);
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: logf(" At: "); break;
|
||||
case ERR_WARNING: logf(" At: "); break;
|
||||
case ERR_SCRIPT: logf(" At: "); break;
|
||||
case ERR_SHADER: logf(" At: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg);
|
||||
logf("%s:%i\n", p_file, p_line);
|
||||
|
||||
} else {
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: logf("ERROR: %s: ", p_function); break;
|
||||
case ERR_WARNING: logf("WARNING: %s: ", p_function); break;
|
||||
case ERR_SCRIPT: logf("SCRIPT ERROR: %s: ", p_function); break;
|
||||
case ERR_SHADER: logf("SCRIPT ERROR: %s: ", p_function); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
|
||||
logf("%s\n", p_code);
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: logf(" At: "); break;
|
||||
case ERR_WARNING: logf(" At: "); break;
|
||||
case ERR_SCRIPT: logf(" At: "); break;
|
||||
case ERR_SHADER: logf(" At: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg);
|
||||
logf("%s:%i\n", p_file, p_line);
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, sbi.wAttributes);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
WindowsTerminalLogger::~WindowsTerminalLogger() {}
|
||||
|
||||
#endif
|
47
platform/windows/windows_terminal_logger.h
Normal file
47
platform/windows/windows_terminal_logger.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*************************************************************************/
|
||||
/* windows_terminal_logger.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef WINDOWS_TERMINAL_LOGGER_H
|
||||
#define WINDOWS_TERMINAL_LOGGER_H
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
|
||||
#include "io/logger.h"
|
||||
|
||||
class WindowsTerminalLogger : public StdLogger {
|
||||
public:
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
virtual ~WindowsTerminalLogger();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user