diff options
52 files changed, 1160 insertions, 394 deletions
diff --git a/core/error_macros.cpp b/core/error_macros.cpp index 5919d38375..170a22e8dd 100644 --- a/core/error_macros.cpp +++ b/core/error_macros.cpp @@ -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; diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h index 9e41834561..309fc16d09 100644 --- a/core/io/file_access_buffered_fa.h +++ b/core/io/file_access_buffered_fa.h @@ -76,6 +76,11 @@ protected: }; public: + void flush() { + + f.flush(); + }; + void store_8(uint8_t p_dest) { f.store_8(p_dest); diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index 4750945854..514e3c65f0 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -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); diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h index 1a57e2d4ee..1d99e5bfd4 100644 --- a/core/io/file_access_compressed.h +++ b/core/io/file_access_compressed.h @@ -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 diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 461c5bafe2..c93e12f7da 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -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); diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index 82f60ac654..d83fed3e0e 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -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 diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index b948394385..0a5815fca8 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -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); diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index b7b8430089..23392719b4 100644 --- a/core/io/file_access_memory.h +++ b/core/io/file_access_memory.h @@ -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 diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 8c624226a1..a224abd9e7 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -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(); diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index abbe378b60..20614476d0 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -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 diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index ff4c28ec39..a7eb8ce6a9 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -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(); diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 3deb0d2bd3..12187a353a 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -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); diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 73b23ac702..ec809011a9 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -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(); diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index a40e1a753d..0977b241ee 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -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 diff --git a/core/io/logger.cpp b/core/io/logger.cpp new file mode 100644 index 0000000000..7ea5f06d7e --- /dev/null +++ b/core/io/logger.cpp @@ -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]); + } +} diff --git a/core/io/logger.h b/core/io/logger.h new file mode 100644 index 0000000000..cf0cc7699f --- /dev/null +++ b/core/io/logger.h @@ -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
\ No newline at end of file diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index b969b58bfb..fcb3b58fed 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -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); diff --git a/core/os/file_access.h b/core/os/file_access.h index 34e7549fa3..455dd1ea99 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -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 diff --git a/core/os/os.cpp b/core/os/os.cpp index 437ce01a5e..ff17cdb508 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -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; +} + +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) { - 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); + _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; } diff --git a/core/os/os.h b/core/os/os.h index 3806217f55..c9d25792b9 100644 --- a/core/os/os.h +++ b/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 - }; - - 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); + 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(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; diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 649f874cf4..206f57d4a2 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -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); diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index e2848e4128..96f2ff8e26 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -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 diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 75c8a153f6..29fe73f170 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -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::finalize_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::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::finalize_core() { } -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 diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 19e79728fb..1cc44c0ffd 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -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 diff --git a/drivers/unix/syslog_logger.cpp b/drivers/unix/syslog_logger.cpp new file mode 100644 index 0000000000..d57f391325 --- /dev/null +++ b/drivers/unix/syslog_logger.cpp @@ -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
\ No newline at end of file diff --git a/drivers/unix/syslog_logger.h b/drivers/unix/syslog_logger.h new file mode 100644 index 0000000000..b3cf2f9e3a --- /dev/null +++ b/drivers/unix/syslog_logger.h @@ -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
\ No newline at end of file diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 6d6a6027d9..8d6e78dbee 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -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; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index d128b58244..3b6e469c9c 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -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); diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 15cbdca739..e5e7fd4a13 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -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 diff --git a/editor/SCsub b/editor/SCsub index bf88ebb1b5..11cdb471a8 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -6,6 +6,16 @@ env.editor_sources = [] import os from compat import encode_utf8, byte_to_str, open_utf8 +def escape_string(s, encoding='ascii'): + if isinstance(s, unicode): + s = s.encode(encoding) + result = '' + for c in s: + if not (32 <= ord(c) < 127) or c in ('\\', '"'): + result += '\\%03o' % ord(c) + else: + result += c + return result def make_certs_header(target, source, env): @@ -162,7 +172,7 @@ def make_authors_header(target, source, env): for line in f: if reading: if line.startswith(" "): - g.write("\t\"" + line.strip() + "\",\n") + g.write("\t\"" + escape_string(line.strip()) + "\",\n") continue if line.startswith("## "): if reading: @@ -170,7 +180,7 @@ def make_authors_header(target, source, env): reading = False for i in range(len(sections)): if line.strip().endswith(sections[i]): - current_section = sections_id[i] + current_section = escape_string(sections_id[i]) reading = True g.write("static const char *" + current_section + "[] = {\n") break @@ -204,7 +214,7 @@ def make_donors_header(target, source, env): for line in f: if reading >= 0: if line.startswith(" "): - g.write("\t\"" + line.strip() + "\",\n") + g.write("\t\"" + escape_string(line.strip()) + "\",\n") continue if line.startswith("## "): if reading: @@ -212,7 +222,7 @@ def make_donors_header(target, source, env): reading = False for i in range(len(sections)): if line.strip().endswith(sections[i]): - current_section = sections_id[i] + current_section = escape_string(sections_id[i]) reading = True g.write("static const char *" + current_section + "[] = {\n") break @@ -237,7 +247,8 @@ def make_license_header(target, source, env): g.write("static const char *about_license =") for line in f: - g.write("\n\t\"" + line.strip().replace("\"", "\\\"") + "\\n\"") + escaped_string = escape_string(line.strip().replace("\"", "\\\"")) + g.write("\n\t\"" + escaped_string + "\\n\"") g.write(";\n") @@ -322,11 +333,13 @@ def make_license_header(target, source, env): for k in j[0].split("\n"): if file_body != "": file_body += "\\n\"\n" - file_body += "\t\"" + k.strip().replace("\"", "\\\"") + escaped_string = escape_string(k.strip().replace("\"", "\\\"")) + file_body += "\t\"" + escaped_string for k in j[1].split("\n"): if copyright_body != "": copyright_body += "\\n\"\n" - copyright_body += "\t\"" + k.strip().replace("\"", "\\\"") + escaped_string = escape_string(k.strip().replace("\"", "\\\"")) + copyright_body += "\t\"" + escaped_string about_tp_file += "\t" + file_body + "\",\n" about_tp_copyright += "\t" + copyright_body + "\",\n" @@ -340,7 +353,8 @@ def make_license_header(target, source, env): for j in i[1].split("\n"): if body != "": body += "\\n\"\n" - body += "\t\"" + j.strip().replace("\"", "\\\"") + escaped_string = escape_string(j.strip().replace("\"", "\\\"")) + body += "\t\"" + escaped_string about_license_name += "\t\"" + i[0] + "\",\n" about_license_body += "\t" + body + "\",\n" diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 69cfc05e2b..425390723c 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -49,13 +49,15 @@ #define DISTANCE_DEFAULT 4 -#define GIZMO_ARROW_SIZE 0.3 +#define GIZMO_ARROW_SIZE 0.35 #define GIZMO_RING_HALF_WIDTH 0.1 //#define GIZMO_SCALE_DEFAULT 0.28 #define GIZMO_SCALE_DEFAULT 0.15 #define GIZMO_PLANE_SIZE 0.2 #define GIZMO_PLANE_DST 0.3 -#define GIZMO_CIRCLE_SIZE 0.9 +#define GIZMO_CIRCLE_SIZE 1.1 +#define GIZMO_SCALE_OFFSET (GIZMO_CIRCLE_SIZE + 0.3) +#define GIZMO_ARROW_OFFSET (GIZMO_CIRCLE_SIZE + 0.3) #define ZOOM_MIN_DISTANCE 0.001 #define ZOOM_MULTIPLIER 1.08 @@ -538,8 +540,6 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) { List<Node *> &selection = editor_selection->get_selected_node_list(); - //Vector3 center; - //int nc=0; for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to<Spatial>(E->get()); @@ -551,14 +551,8 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) { continue; se->original = se->sp->get_global_transform(); - //center+=se->original.origin; - //nc++; + se->original_local = se->sp->get_transform(); } - - /* - if (nc) - _edit.center=center/float(nc); - */ } static int _get_key_modifier_setting(const String &p_property) { @@ -609,7 +603,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig for (int i = 0; i < 3; i++) { - Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs; + Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs * (GIZMO_ARROW_OFFSET + (GIZMO_ARROW_SIZE * 0.5)); float grabber_radius = gs * GIZMO_ARROW_SIZE; Vector3 r; @@ -624,7 +618,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig } bool is_plane_translate = false; - // second try + // plane select if (col_axis == -1) { col_d = 1e20; @@ -710,6 +704,43 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig } } + if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE) { + + int col_axis = -1; + float col_d = 1e20; + + for (int i = 0; i < 3; i++) { + + Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs * GIZMO_SCALE_OFFSET; + float grabber_radius = gs * GIZMO_ARROW_SIZE; + + Vector3 r; + + if (Geometry::segment_intersects_sphere(ray_pos, ray_pos + ray * 10000.0, grabber_pos, grabber_radius, &r)) { + float d = r.distance_to(ray_pos); + if (d < col_d) { + col_d = d; + col_axis = i; + } + } + } + + if (col_axis != -1) { + + if (p_highlight_only) { + + spatial_editor->select_gizmo_highlight_axis(col_axis + 9); + + } else { + //handle scale + _edit.mode = TRANSFORM_SCALE; + _compute_edit(Point2(p_screenpos.x, p_screenpos.y)); + _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis); + } + return true; + } + } + if (p_highlight_only) spatial_editor->select_gizmo_highlight_axis(-1); @@ -1182,7 +1213,28 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { case TRANSFORM_SCALE: { - Plane plane = Plane(_edit.center, _get_camera_normal()); + Vector3 motion_mask; + Plane plane; + bool plane_mv; + + switch (_edit.plane) { + case TRANSFORM_VIEW: + motion_mask = Vector3(0, 0, 0); + plane = Plane(_edit.center, _get_camera_normal()); + break; + case TRANSFORM_X_AXIS: + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0); + plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized()); + break; + case TRANSFORM_Y_AXIS: + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1); + plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized()); + break; + case TRANSFORM_Z_AXIS: + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2); + plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized()); + break; + } Vector3 intersection; if (!plane.intersects_ray(ray_pos, ray, &intersection)) @@ -1192,42 +1244,78 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (!plane.intersects_ray(_edit.click_ray_pos, _edit.click_ray, &click)) break; - float center_click_dist = click.distance_to(_edit.center); - float center_inters_dist = intersection.distance_to(_edit.center); - if (center_click_dist == 0) - break; + Vector3 motion = intersection - click; + print_line(String(intersection) + " --- " + String(click)); + if (motion_mask != Vector3()) { - float scale = (center_inters_dist / center_click_dist) * 100.0; + motion = motion_mask.dot(motion) * motion_mask; + } else { - if (_edit.snap || spatial_editor->is_snap_enabled()) { + float center_click_dist = click.distance_to(_edit.center); + float center_inters_dist = intersection.distance_to(_edit.center); + if (center_click_dist == 0) + break; - scale = Math::stepify(scale, spatial_editor->get_scale_snap()); + float scale = center_inters_dist - center_click_dist; + motion = Vector3(scale, scale, scale); } - set_message(vformat(TTR("Scaling to %s%%."), String::num(scale, 1))); - scale /= 100.0; + List<Node *> &selection = editor_selection->get_selected_node_list(); - Transform r; - r.basis.scale(Vector3(scale, scale, scale)); + bool local_coords = (spatial_editor->are_local_coords_enabled() && motion_mask != Vector3()); // Disable local transformation for TRANSFORM_VIEW - List<Node *> &selection = editor_selection->get_selected_node_list(); + float snap = 0; + if (_edit.snap || spatial_editor->is_snap_enabled()) { + + snap = spatial_editor->get_scale_snap() / 100; + } for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to<Spatial>(E->get()); - if (!sp) + if (!sp) { continue; + } SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp); - if (!se) + if (!se) { continue; + } Transform original = se->original; - + Transform original_local = se->original_local; Transform base = Transform(Basis(), _edit.center); - Transform t = base * (r * (base.inverse() * original)); + Transform t; + Vector3 local_scale; - sp->set_global_transform(t); + if (local_coords) { + + Basis g = original.basis.orthonormalized(); + Vector3 local_motion = g.inverse().xform(motion); + + if (_edit.snap || spatial_editor->is_snap_enabled()) { + local_motion.snap(Vector3(snap, snap, snap)); + } + + local_scale = original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1)); + + } else { + + if (_edit.snap || spatial_editor->is_snap_enabled()) { + motion.snap(Vector3(snap, snap, snap)); + } + + Transform r; + r.basis.scale(motion + Vector3(1, 1, 1)); + t = base * (r * (base.inverse() * original)); + } + + // Apply scale + if (local_coords) { + sp->set_scale(local_scale); + } else { + sp->set_global_transform(t); + } } surface->update(); @@ -2271,6 +2359,14 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) { //VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true); VS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); VS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i], layer); + + scale_gizmo_instance[i] = VS::get_singleton()->instance_create(); + VS::get_singleton()->instance_set_base(scale_gizmo_instance[i], spatial_editor->get_scale_gizmo(i)->get_rid()); + VS::get_singleton()->instance_set_scenario(scale_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); + VS::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false); + //VS::get_singleton()->instance_geometry_set_flag(scale_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true); + VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); + VS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer); } } @@ -2280,6 +2376,7 @@ void SpatialEditorViewport::_finish_gizmo_instances() { VS::get_singleton()->free(move_gizmo_instance[i]); VS::get_singleton()->free(move_plane_gizmo_instance[i]); VS::get_singleton()->free(rotate_gizmo_instance[i]); + VS::get_singleton()->free(scale_gizmo_instance[i]); } } void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { @@ -2374,6 +2471,8 @@ void SpatialEditorViewport::update_transform_gizmo_view() { VisualServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE)); VisualServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform); VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE)); + VisualServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform); + VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE)); } } @@ -3259,6 +3358,7 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) { move_gizmo[i]->surface_set_material(0, i == p_axis ? gizmo_hl : gizmo_color[i]); move_plane_gizmo[i]->surface_set_material(0, (i + 6) == p_axis ? gizmo_hl : plane_gizmo_color[i]); rotate_gizmo[i]->surface_set_material(0, (i + 3) == p_axis ? gizmo_hl : gizmo_color[i]); + scale_gizmo[i]->surface_set_material(0, (i + 9) == p_axis ? gizmo_hl : gizmo_color[i]); } } @@ -3269,7 +3369,7 @@ void SpatialEditor::update_transform_gizmo() { bool first = true; Basis gizmo_basis; - bool local_gizmo_coords = transform_menu->get_popup()->is_item_checked(transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS)); + bool local_gizmo_coords = are_local_coords_enabled(); for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { @@ -3720,10 +3820,6 @@ void SpatialEditor::_menu_item_pressed(int p_option) { void SpatialEditor::_init_indicators() { - //RID mat = VisualServer::get_singleton()->fixed_material_create(); - ///VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA,true); - //VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true); - { indicator_mat.instance(); @@ -3835,6 +3931,7 @@ void SpatialEditor::_init_indicators() { move_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); move_plane_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); rotate_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); + scale_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh)); Ref<SpatialMaterial> mat = memnew(SpatialMaterial); mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); @@ -3857,25 +3954,25 @@ void SpatialEditor::_init_indicators() { Vector3 ivec3; ivec3[(i + 2) % 3] = 1; + //translate { Ref<SurfaceTool> surftool = memnew(SurfaceTool); surftool->begin(Mesh::PRIMITIVE_TRIANGLES); - //translate - + // Arrow profile const int arrow_points = 5; Vector3 arrow[5] = { nivec * 0.0 + ivec * 0.0, nivec * 0.01 + ivec * 0.0, - nivec * 0.01 + ivec * 1.0, - nivec * 0.1 + ivec * 1.0, - nivec * 0.0 + ivec * (1 + GIZMO_ARROW_SIZE), + nivec * 0.01 + ivec * GIZMO_ARROW_OFFSET, + nivec * 0.065 + ivec * GIZMO_ARROW_OFFSET, + nivec * 0.0 + ivec * (GIZMO_ARROW_OFFSET + GIZMO_ARROW_SIZE), }; int arrow_sides = 6; - for (int k = 0; k < 7; k++) { + for (int k = 0; k < 6; k++) { Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides); Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides); @@ -3902,7 +3999,7 @@ void SpatialEditor::_init_indicators() { surftool->commit(move_gizmo[i]); } - // plane translation + // Plane Translation { Ref<SurfaceTool> surftool = memnew(SurfaceTool); surftool->begin(Mesh::PRIMITIVE_TRIANGLES); @@ -3945,6 +4042,7 @@ void SpatialEditor::_init_indicators() { surftool->commit(move_plane_gizmo[i]); } + // Rotate { Ref<SurfaceTool> surftool = memnew(SurfaceTool); @@ -3958,7 +4056,7 @@ void SpatialEditor::_init_indicators() { ivec * 0.02 + ivec2 * 0.02 + ivec2 * GIZMO_CIRCLE_SIZE, }; - for (int k = 0; k < 33; k++) { + for (int k = 0; k < 32; k++) { Basis ma(ivec, Math_PI * 2 * float(k) / 32); Basis mb(ivec, Math_PI * 2 * float(k + 1) / 32); @@ -3984,19 +4082,55 @@ void SpatialEditor::_init_indicators() { surftool->set_material(mat); surftool->commit(rotate_gizmo[i]); } - } - } - /*for(int i=0;i<4;i++) { + // Scale + { + Ref<SurfaceTool> surftool = memnew(SurfaceTool); + surftool->begin(Mesh::PRIMITIVE_TRIANGLES); - viewports[i]->init_gizmo_instance(i); - }*/ + // Cube arrow profile + const int arrow_points = 6; + Vector3 arrow[6] = { + nivec * 0.0 + ivec * 0.0, + nivec * 0.01 + ivec * 0.0, + nivec * 0.01 + ivec * 1.0 * GIZMO_SCALE_OFFSET, + nivec * 0.07 + ivec * 1.0 * GIZMO_SCALE_OFFSET, + nivec * 0.07 + ivec * 1.11 * GIZMO_SCALE_OFFSET, + nivec * 0.0 + ivec * 1.11 * GIZMO_SCALE_OFFSET, + }; - _generate_selection_box(); + int arrow_sides = 4; + + for (int k = 0; k < 4; k++) { - //Object::cast_to<EditorNode>(get_scene()->get_root_node())->get_scene_root()->add_child(camera); + Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides); + Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides); - //current_camera=camera; + for (int j = 0; j < arrow_points - 1; j++) { + + Vector3 points[4] = { + ma.xform(arrow[j]), + mb.xform(arrow[j]), + mb.xform(arrow[j + 1]), + ma.xform(arrow[j + 1]), + }; + surftool->add_vertex(points[0]); + surftool->add_vertex(points[1]); + surftool->add_vertex(points[2]); + + surftool->add_vertex(points[0]); + surftool->add_vertex(points[2]); + surftool->add_vertex(points[3]); + } + } + + surftool->set_material(mat); + surftool->commit(scale_gizmo[i]); + } + } + } + + _generate_selection_box(); } void SpatialEditor::_finish_indicators() { diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index e0ded6e646..4f4c540048 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -245,7 +245,7 @@ private: real_t zoom_indicator_delay; - RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3]; + RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3], scale_gizmo_instance[3]; String last_message; String message; @@ -319,6 +319,7 @@ class SpatialEditorSelectedItem : public Object { public: Rect3 aabb; Transform original; // original location when moving + Transform original_local; Transform last_xform; // last transform Spatial *sp; RID sbox_instance; @@ -407,7 +408,7 @@ private: bool grid_enable[3]; //should be always visible if true bool grid_enabled; - Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[3]; + Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[3], scale_gizmo[3]; Ref<SpatialMaterial> gizmo_color[3]; Ref<SpatialMaterial> plane_gizmo_color[3]; Ref<SpatialMaterial> gizmo_hl; @@ -557,6 +558,7 @@ public: Ref<ArrayMesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; } Ref<ArrayMesh> get_move_plane_gizmo(int idx) const { return move_plane_gizmo[idx]; } Ref<ArrayMesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; } + Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; } void update_transform_gizmo(); diff --git a/main/main.cpp b/main/main.cpp index f9422cdf0b..48df37ac63 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -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)); diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp index c7b0d9afcd..0fdf9002d7 100644 --- a/platform/android/file_access_android.cpp +++ b/platform/android/file_access_android.cpp @@ -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(); diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index beccf494dd..c8fedbe684 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -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 diff --git a/platform/android/file_access_jandroid.cpp b/platform/android/file_access_jandroid.cpp index fe934c89fb..980afd8f46 100644 --- a/platform/android/file_access_jandroid.cpp +++ b/platform/android/file_access_jandroid.cpp @@ -157,6 +157,9 @@ Error FileAccessJAndroid::get_error() const { return OK; } +void FileAccessJAndroid::flush() { +} + void FileAccessJAndroid::store_8(uint8_t p_dest) { } diff --git a/platform/android/file_access_jandroid.h b/platform/android/file_access_jandroid.h index 75a6a21335..368d2c98fa 100644 --- a/platform/android/file_access_jandroid.h +++ b/platform/android/file_access_jandroid.h @@ -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 diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index dbea2d7531..0eb14f6af3 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -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() { diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 119c14bff3..a614bb8067 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -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); diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 086cbe5010..5009f7d8ae 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -41,6 +41,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" @@ -98,6 +99,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; @@ -568,6 +576,8 @@ OSIPhone::OSIPhone(int width, int height) { vm.resizable = false; set_video_mode(vm); event_count = 0; + + _set_logger(memnew(SyslogLogger)); }; OSIPhone::~OSIPhone() { diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 3ebd5a74db..11f4eed5e7 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -90,6 +90,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); diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index f103035b27..82a8409615 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -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); diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 4c6469cb58..1c7bcfef45 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -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); diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 2662e40561..eb8c0566b4 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -127,6 +127,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(); @@ -141,8 +142,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); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 6502001100..8323aa84a8 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -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; - - const char *err_details; - if (p_rationale && p_rationale[0]) - err_details = p_rationale; - else - err_details = p_code; +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; + } - 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; + 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: + 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) { @@ -2016,6 +2040,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) { diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index b909ccccd6..031c714514 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -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() { diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index a7a5d32cb9..df38faa8e1 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -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); diff --git a/platform/windows/SCsub b/platform/windows/SCsub index d3c160f052..aa9eb3e69b 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -19,6 +19,7 @@ common_win = [ "stream_peer_winsock.cpp", "joypad.cpp", "power_windows.cpp", + "windows_terminal_logger.cpp" ] restarget = "godot_res" + env["OBJSUFFIX"] diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index d715c51a71..bee8c90ad3 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -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"; @@ -2429,6 +2304,8 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { #ifdef XAUDIO2_ENABLED AudioDriverManager::add_driver(&driver_xaudio2); #endif + + _set_logger(memnew(WindowsTerminalLogger)); } OS_Windows::~OS_Windows() { diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index bc1dc318cb..9560bc61ca 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -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); diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp new file mode 100644 index 0000000000..ef8140ffa7 --- /dev/null +++ b/platform/windows/windows_terminal_logger.cpp @@ -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
\ No newline at end of file diff --git a/platform/windows/windows_terminal_logger.h b/platform/windows/windows_terminal_logger.h new file mode 100644 index 0000000000..f6b1a68d18 --- /dev/null +++ b/platform/windows/windows_terminal_logger.h @@ -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
\ No newline at end of file |