diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/error_macros.h | 137 | ||||
-rw-r--r-- | core/func_ref.cpp | 13 | ||||
-rw-r--r-- | core/func_ref.h | 1 | ||||
-rw-r--r-- | core/image.cpp | 10 | ||||
-rw-r--r-- | core/image.h | 4 | ||||
-rw-r--r-- | core/object.h | 7 | ||||
-rw-r--r-- | core/translation.cpp | 64 |
7 files changed, 203 insertions, 33 deletions
diff --git a/core/error_macros.h b/core/error_macros.h index 69874e280b..65802de9d2 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -140,6 +140,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } while (0); // (*) +#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \ + do { \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return; \ + } \ + _err_error_exists = false; \ + } while (0); // (*) + /** An index has failed if m_index<0 or m_index >=m_size, the function exits. * This function returns an error value, if returning Error, please select the most * appropriate error condition from error_macros.h @@ -154,6 +164,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } while (0); // (*) +#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ + do { \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return m_retval; \ + } \ + _err_error_exists = false; \ + } while (0); // (*) + /** An index has failed if m_index >=m_size, the function exits. * This function returns an error value, if returning Error, please select the most * appropriate error condition from error_macros.h @@ -168,6 +188,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } while (0); // (*) +#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ + do { \ + if (unlikely((m_index) >= (m_size))) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return m_retval; \ + } \ + _err_error_exists = false; \ + } while (0); // (*) + /** Use this one if there is no sensible fallback, that is, the error is unrecoverable. * We'll return a null reference and try to keep running. */ @@ -179,6 +209,15 @@ extern bool _err_error_exists; } \ } while (0); // (*) +#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \ + do { \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), true); \ + GENERATE_TRAP \ + } \ + } while (0); // (*) + /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). * the function will exit. */ @@ -192,6 +231,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define ERR_FAIL_NULL_MSG(m_param, m_msg) \ + { \ + if (unlikely(!m_param)) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \ + return; \ + } \ + _err_error_exists = false; \ + } + #define ERR_FAIL_NULL_V(m_param, m_retval) \ { \ if (unlikely(!m_param)) { \ @@ -201,6 +250,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \ + { \ + if (unlikely(!m_param)) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \ + return m_retval; \ + } \ + _err_error_exists = false; \ + } + /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). * the function will exit. */ @@ -214,6 +273,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define ERR_FAIL_COND_MSG(m_cond, m_msg) \ + { \ + if (unlikely(m_cond)) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \ + return; \ + } \ + _err_error_exists = false; \ + } + /** Use this one if there is no sensible fallback, that is, the error is unrecoverable. */ @@ -225,6 +294,15 @@ extern bool _err_error_exists; } \ } +#define CRASH_COND_MSG(m_cond, m_msg) \ + { \ + if (unlikely(m_cond)) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition ' " _STR(m_cond) " ' is true."); \ + GENERATE_TRAP \ + } \ + } + /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). * the function will exit. * This function returns an error value, if returning Error, please select the most @@ -240,6 +318,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \ + { \ + if (unlikely(m_cond)) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. returned: " _STR(m_retval)); \ + return m_retval; \ + } \ + _err_error_exists = false; \ + } + /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). * the loop will skip to the next iteration. */ @@ -253,6 +341,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define ERR_CONTINUE_MSG(m_cond, m_msg) \ + { \ + if (unlikely(m_cond)) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \ + continue; \ + } \ + _err_error_exists = false; \ + } + /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). * the loop will break */ @@ -266,6 +364,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define ERR_BREAK_MSG(m_cond, m_msg) \ + { \ + if (unlikely(m_cond)) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \ + break; \ + } \ + _err_error_exists = false; \ + } + /** Print an error string and return */ @@ -276,6 +384,12 @@ extern bool _err_error_exists; return; \ } +#define ERR_FAIL_MSG(m_msg) \ + { \ + ERR_EXPLAIN(m_msg); \ + ERR_FAIL(); \ + } + /** Print an error string and return with value */ @@ -286,6 +400,12 @@ extern bool _err_error_exists; return m_value; \ } +#define ERR_FAIL_V_MSG(m_value, m_msg) \ + { \ + ERR_EXPLAIN(m_msg); \ + ERR_FAIL_V(m_value); \ + } + /** Use this one if there is no sensible fallback, that is, the error is unrecoverable. */ @@ -295,6 +415,12 @@ extern bool _err_error_exists; GENERATE_TRAP \ } +#define CRASH_NOW_MSG(m_msg) \ + { \ + ERR_EXPLAIN(m_msg); \ + CRASH_NOW(); \ + } + /** Print an error string. */ @@ -355,4 +481,15 @@ extern bool _err_error_exists; } \ } +#define WARN_DEPRECATED_MSG(m_msg) \ + { \ + static volatile bool warning_shown = false; \ + if (!warning_shown) { \ + ERR_EXPLAIN(m_msg); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future", ERR_HANDLER_WARNING); \ + _err_error_exists = false; \ + warning_shown = true; \ + } \ + } + #endif diff --git a/core/func_ref.cpp b/core/func_ref.cpp index 3d03137d09..66ef27f6b9 100644 --- a/core/func_ref.cpp +++ b/core/func_ref.cpp @@ -46,6 +46,17 @@ Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::Call return obj->call(function, p_args, p_argcount, r_error); } +Variant FuncRef::call_funcv(const Array &p_args) { + + ERR_FAIL_COND_V(id == 0, Variant()); + + Object *obj = ObjectDB::get_instance(id); + + ERR_FAIL_COND_V(!obj, Variant()); + + return obj->callv(function, p_args); +} + void FuncRef::set_instance(Object *p_obj) { ERR_FAIL_NULL(p_obj); @@ -77,6 +88,8 @@ void FuncRef::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_func", &FuncRef::call_func, mi, defargs); } + ClassDB::bind_method(D_METHOD("call_funcv", "arg_array"), &FuncRef::call_funcv); + ClassDB::bind_method(D_METHOD("set_instance", "instance"), &FuncRef::set_instance); ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function); ClassDB::bind_method(D_METHOD("is_valid"), &FuncRef::is_valid); diff --git a/core/func_ref.h b/core/func_ref.h index a143b58bf0..af0bf63203 100644 --- a/core/func_ref.h +++ b/core/func_ref.h @@ -44,6 +44,7 @@ protected: public: Variant call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error); + Variant call_funcv(const Array &p_args); void set_instance(Object *p_obj); void set_function(const StringName &p_func); bool is_valid() const; diff --git a/core/image.cpp b/core/image.cpp index 10778eced6..5ce744f709 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -83,6 +83,7 @@ const char *Image::format_names[Image::FORMAT_MAX] = { }; SavePNGFunc Image::save_png_func = NULL; +SaveEXRFunc Image::save_exr_func = NULL; void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) { @@ -1917,6 +1918,14 @@ Error Image::save_png(const String &p_path) const { return save_png_func(p_path, Ref<Image>((Image *)this)); } +Error Image::save_exr(const String &p_path, bool p_grayscale) const { + + if (save_exr_func == NULL) + return ERR_UNAVAILABLE; + + return save_exr_func(p_path, Ref<Image>((Image *)this), p_grayscale); +} + int Image::get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps) { int mm; @@ -2746,6 +2755,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("load", "path"), &Image::load); ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png); + ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false)); ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha); ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible); diff --git a/core/image.h b/core/image.h index cc796789cd..d17571399d 100644 --- a/core/image.h +++ b/core/image.h @@ -49,11 +49,14 @@ class Image; typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img); typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size); +typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale); + class Image : public Resource { GDCLASS(Image, Resource); public: static SavePNGFunc save_png_func; + static SaveEXRFunc save_exr_func; enum { MAX_WIDTH = 16384, // force a limit somehow @@ -258,6 +261,7 @@ public: Error load(const String &p_path); Error save_png(const String &p_path) const; + Error save_exr(const String &p_path, bool p_grayscale) const; /** * create an empty image diff --git a/core/object.h b/core/object.h index dce1cc74ae..15c3ab94c5 100644 --- a/core/object.h +++ b/core/object.h @@ -794,8 +794,13 @@ public: static int get_object_count(); _FORCE_INLINE_ static bool instance_validate(Object *p_ptr) { + rw_lock->read_lock(); - return instance_checks.has(p_ptr); + bool exists = instance_checks.has(p_ptr); + + rw_lock->read_unlock(); + + return exists; } }; diff --git a/core/translation.cpp b/core/translation.cpp index 0b55badc61..a3ff971f45 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -1044,6 +1044,13 @@ StringName TranslationServer::translate(const StringName &p_message) const { if (!enabled) return p_message; + // Locale can be of the form 'll_CC', i.e. language code and regional code, + // e.g. 'en_US', 'en_GB', etc. It might also be simply 'll', e.g. 'en'. + // To find the relevant translation, we look for those with locale starting + // with the language code, and then if any is an exact match for the long + // form. If not found, we fall back to a near match (another locale with + // same language code). + StringName res; bool near_match = false; const CharType *lptr = &locale[0]; @@ -1053,13 +1060,11 @@ StringName TranslationServer::translate(const StringName &p_message) const { const Ref<Translation> &t = E->get(); String l = t->get_locale(); if (lptr[0] != l[0] || lptr[1] != l[1]) - continue; // locale not match - - //near match - bool match = (l != locale); + continue; // Language code does not match. - if (near_match && !match) - continue; //only near-match once + bool exact_match = (l == locale); + if (!exact_match && near_match) + continue; // Only near-match once, but keep looking for exact matches. StringName r = t->get_message(p_message); @@ -1068,43 +1073,38 @@ StringName TranslationServer::translate(const StringName &p_message) const { res = r; - if (match) + if (exact_match) break; else near_match = true; } - if (!res) { - //try again with fallback - if (fallback.length() >= 2) { - - const CharType *fptr = &fallback[0]; - near_match = false; - for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) { + if (!res && fallback.length() >= 2) { + // Try again with the fallback locale. + const CharType *fptr = &fallback[0]; + near_match = false; + for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) { - const Ref<Translation> &t = E->get(); - String l = t->get_locale(); - if (fptr[0] != l[0] || fptr[1] != l[1]) - continue; // locale not match + const Ref<Translation> &t = E->get(); + String l = t->get_locale(); + if (fptr[0] != l[0] || fptr[1] != l[1]) + continue; // Language code does not match. - //near match - bool match = (l != fallback); + bool exact_match = (l == fallback); + if (!exact_match && near_match) + continue; // Only near-match once, but keep looking for exact matches. - if (near_match && !match) - continue; //only near-match once + StringName r = t->get_message(p_message); - StringName r = t->get_message(p_message); + if (!r) + continue; - if (!r) - continue; + res = r; - res = r; - - if (match) - break; - else - near_match = true; - } + if (exact_match) + break; + else + near_match = true; } } |