diff options
70 files changed, 1059 insertions, 593 deletions
diff --git a/SConstruct b/SConstruct index 6703038bed..6af363090b 100644 --- a/SConstruct +++ b/SConstruct @@ -78,7 +78,6 @@ env_base.__class__.add_module_version_string = methods.add_module_version_string env_base.__class__.add_source_files = methods.add_source_files env_base.__class__.use_windows_spawn_fix = methods.use_windows_spawn_fix -env_base.__class__.split_lib = methods.split_lib env_base.__class__.add_shared_library = methods.add_shared_library env_base.__class__.add_library = methods.add_library @@ -118,7 +117,6 @@ opts.Add(BoolVariable('use_precise_math_checks', 'Math checks use very precise e # Components opts.Add(BoolVariable('deprecated', "Enable deprecated features", True)) -opts.Add(BoolVariable('gdscript', "Enable GDScript support", True)) opts.Add(BoolVariable('minizip', "Enable ZIP archive support using minizip", True)) opts.Add(BoolVariable('xaudio2', "Enable the XAudio2 audio driver", False)) @@ -131,7 +129,6 @@ opts.Add(BoolVariable('dev', "If yes, alias for verbose=yes warnings=extra werro opts.Add('extra_suffix', "Custom extra suffix added to the base filename of all generated binary files", '') opts.Add(BoolVariable('vsproj', "Generate a Visual Studio solution", False)) opts.Add(EnumVariable('macports_clang', "Build using Clang from MacPorts", 'no', ('no', '5.0', 'devel'))) -opts.Add(BoolVariable('split_libmodules', "Split intermediate libmodules.a in smaller chunks to prevent exceeding linker command line size (forced to True when using MinGW)", False)) opts.Add(BoolVariable('disable_3d', "Disable 3D nodes for a smaller executable", False)) opts.Add(BoolVariable('disable_advanced_gui', "Disable advanced GUI nodes and behaviors", False)) opts.Add(BoolVariable('no_editor_splash', "Don't use the custom splash screen for the editor", False)) @@ -410,7 +407,7 @@ if selected_platform in platform_list: env.module_icons_paths = [] env.doc_class_path = {} - for x in module_list: + for x in sorted(module_list): if not env['module_' + x + '_enabled']: continue tmppath = "./modules/" + x @@ -427,7 +424,7 @@ if selected_platform in platform_list: "signature in its config.py file, it should be " "`can_build(env, platform)`." % x) can_build = config.can_build(selected_platform) - if (can_build): + if can_build: config.configure(env) env.module_list.append(x) @@ -477,8 +474,6 @@ if selected_platform in platform_list: sys.exit(255) else: env.Append(CPPDEFINES=['_3D_DISABLED']) - if env['gdscript']: - env.Append(CPPDEFINES=['GDSCRIPT_ENABLED']) if env['disable_advanced_gui']: if env['tools']: print("Build option 'disable_advanced_gui=yes' cannot be used with 'tools=yes' (editor), only with 'tools=no' (export template).") diff --git a/core/core_builders.py b/core/core_builders.py index f3a9e3b221..7720183595 100644 --- a/core/core_builders.py +++ b/core/core_builders.py @@ -1,8 +1,8 @@ """Functions used to generate source files during build time All such functions are invoked in a subprocess on Windows to prevent build flakiness. - """ + from platform_methods import subprocess_main from compat import iteritems, itervalues, open_utf8, escape_string, byte_to_str diff --git a/core/error_macros.h b/core/error_macros.h index 80ceede043..4a3ea28957 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -108,8 +108,6 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * running application to fail or crash. * Always try to return processable data, so the engine can keep running well. * Use the _MSG versions to print a meaningful message to help with debugging. - * - * Note: See https://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for */ // Index out of bounds error macros. @@ -124,25 +122,23 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. * If not, the current function returns. */ -#define ERR_FAIL_INDEX(m_index, m_size) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ - return; \ - } \ - } while (0) +#define ERR_FAIL_INDEX(m_index, m_size) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return; \ + } else \ + ((void)0) /** * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. * If not, prints `m_msg` and the current function returns. */ -#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ - return; \ - } \ - } while (0) +#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_INDEX_V_MSG`. @@ -151,25 +147,23 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. * If not, the current function returns `m_retval`. */ -#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ - return m_retval; \ - } \ - } while (0) +#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return m_retval; \ + } else \ + ((void)0) /** * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. * If not, prints `m_msg` and the current function returns `m_retval`. */ -#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_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ - return m_retval; \ - } \ - } while (0) +#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`. @@ -179,13 +173,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. * If not, the application crashes. */ -#define CRASH_BAD_INDEX(m_index, m_size) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \ - GENERATE_TRAP(); \ - } \ - } while (0) +#define CRASH_BAD_INDEX(m_index, m_size) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`. @@ -194,13 +187,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. * If not, prints `m_msg` and the application crashes. */ -#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \ - do { \ - if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \ - GENERATE_TRAP(); \ - } \ - } while (0) +#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) // Unsigned integer index out of bounds error macros. @@ -211,25 +203,23 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures an unsigned integer index `m_index` is less than `m_size`. * If not, the current function returns. */ -#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \ - do { \ - if (unlikely((m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ - return; \ - } \ - } while (0) +#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return; \ + } else \ + ((void)0) /** * Ensures an unsigned integer index `m_index` is less than `m_size`. * If not, prints `m_msg` and the current function returns. */ -#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \ - do { \ - if (unlikely((m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ - return; \ - } \ - } while (0) +#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_UNSIGNED_INDEX_V_MSG`. @@ -238,25 +228,23 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures an unsigned integer index `m_index` is less than `m_size`. * If not, the current function returns `m_retval`. */ -#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \ - do { \ - if (unlikely((m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ - return m_retval; \ - } \ - } while (0) +#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \ + return m_retval; \ + } else \ + ((void)0) /** * Ensures an unsigned integer index `m_index` is less than `m_size`. * If not, prints `m_msg` and the current function returns `m_retval`. */ -#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ - do { \ - if (unlikely((m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ - return m_retval; \ - } \ - } while (0) +#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`. @@ -266,13 +254,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures an unsigned integer index `m_index` is less than `m_size`. * If not, the application crashes. */ -#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \ - do { \ - if (unlikely((m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \ - GENERATE_TRAP(); \ - } \ - } while (0) +#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`. @@ -281,13 +268,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures an unsigned integer index `m_index` is less than `m_size`. * If not, prints `m_msg` and the application crashes. */ -#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \ - do { \ - if (unlikely((m_index) >= (m_size))) { \ - _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \ - GENERATE_TRAP(); \ - } \ - } while (0) +#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) // Null reference error macros. @@ -298,25 +284,23 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures a pointer `m_param` is not null. * If it is null, the current function returns. */ -#define ERR_FAIL_NULL(m_param) \ - do { \ - if (unlikely(!m_param)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ - return; \ - } \ - } while (0) +#define ERR_FAIL_NULL(m_param) \ + if (unlikely(!m_param)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ + return; \ + } else \ + ((void)0) /** * Ensures a pointer `m_param` is not null. * If it is null, prints `m_msg` and the current function returns. */ -#define ERR_FAIL_NULL_MSG(m_param, m_msg) \ - do { \ - if (unlikely(!m_param)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ - return; \ - } \ - } while (0) +#define ERR_FAIL_NULL_MSG(m_param, m_msg) \ + if (unlikely(!m_param)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_NULL_V_MSG`. @@ -325,25 +309,23 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures a pointer `m_param` is not null. * If it is null, the current function returns `m_retval`. */ -#define ERR_FAIL_NULL_V(m_param, m_retval) \ - do { \ - if (unlikely(!m_param)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ - return m_retval; \ - } \ - } while (0) +#define ERR_FAIL_NULL_V(m_param, m_retval) \ + if (unlikely(!m_param)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ + return m_retval; \ + } else \ + ((void)0) /** * Ensures a pointer `m_param` is not null. * If it is null, prints `m_msg` and the current function returns `m_retval`. */ -#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \ - do { \ - if (unlikely(!m_param)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ - return m_retval; \ - } \ - } while (0) +#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \ + if (unlikely(!m_param)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_COND_MSG`. @@ -354,13 +336,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures `m_cond` is false. * If `m_cond` is true, the current function returns. */ -#define ERR_FAIL_COND(m_cond) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \ - return; \ - } \ - } while (0) +#define ERR_FAIL_COND(m_cond) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \ + return; \ + } else \ + ((void)0) /** * Ensures `m_cond` is false. @@ -369,13 +350,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If checking for null use ERR_FAIL_NULL_MSG instead. * If checking index bounds use ERR_FAIL_INDEX_MSG instead. */ -#define ERR_FAIL_COND_MSG(m_cond, m_msg) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \ - return; \ - } \ - } while (0) +#define ERR_FAIL_COND_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \ + return; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_COND_V_MSG`. @@ -386,13 +366,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures `m_cond` is false. * If `m_cond` is true, the current function returns `m_retval`. */ -#define ERR_FAIL_COND_V(m_cond, m_retval) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval)); \ - return m_retval; \ - } \ - } while (0) +#define ERR_FAIL_COND_V(m_cond, m_retval) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval)); \ + return m_retval; \ + } else \ + ((void)0) /** * Ensures `m_cond` is false. @@ -401,13 +380,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If checking for null use ERR_FAIL_NULL_V_MSG instead. * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead. */ -#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval), DEBUG_STR(m_msg)); \ - return m_retval; \ - } \ - } while (0) +#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval), DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ + ((void)0) /** * Try using `ERR_CONTINUE_MSG`. @@ -416,25 +394,23 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures `m_cond` is false. * If `m_cond` is true, the current loop continues. */ -#define ERR_CONTINUE(m_cond) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \ - continue; \ - } \ - } while (0) +#define ERR_CONTINUE(m_cond) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \ + continue; \ + } else \ + ((void)0) /** * Ensures `m_cond` is false. * If `m_cond` is true, prints `m_msg` and the current loop continues. */ -#define ERR_CONTINUE_MSG(m_cond, m_msg) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", DEBUG_STR(m_msg)); \ - continue; \ - } \ - } while (0) +#define ERR_CONTINUE_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", DEBUG_STR(m_msg)); \ + continue; \ + } else \ + ((void)0) /** * Try using `ERR_BREAK_MSG`. @@ -443,25 +419,23 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures `m_cond` is false. * If `m_cond` is true, the current loop breaks. */ -#define ERR_BREAK(m_cond) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \ - break; \ - } \ - } while (0) +#define ERR_BREAK(m_cond) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \ + break; \ + } else \ + ((void)0) /** * Ensures `m_cond` is false. * If `m_cond` is true, prints `m_msg` and the current loop breaks. */ -#define ERR_BREAK_MSG(m_cond, m_msg) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", DEBUG_STR(m_msg)); \ - break; \ - } \ - } while (0) +#define ERR_BREAK_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", DEBUG_STR(m_msg)); \ + break; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`. @@ -471,13 +445,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures `m_cond` is false. * If `m_cond` is true, the application crashes. */ -#define CRASH_COND(m_cond) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \ - GENERATE_TRAP(); \ - } \ - } while (0) +#define CRASH_COND(m_cond) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`. @@ -486,13 +459,12 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures `m_cond` is false. * If `m_cond` is true, prints `m_msg` and the application crashes. */ -#define CRASH_COND_MSG(m_cond, m_msg) \ - do { \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \ - GENERATE_TRAP(); \ - } \ - } while (0) +#define CRASH_COND_MSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \ + GENERATE_TRAP(); \ + } else \ + ((void)0) // Generic error macros. @@ -504,10 +476,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * The current function returns. */ #define ERR_FAIL() \ - do { \ + if (1) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed."); \ return; \ - } while (0) + } else \ + ((void)0) /** * Try using `ERR_FAIL_COND_MSG`. @@ -516,10 +489,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Prints `m_msg`, and the current function returns. */ #define ERR_FAIL_MSG(m_msg) \ - do { \ + if (1) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed.", DEBUG_STR(m_msg)); \ return; \ - } while (0) + } else \ + ((void)0) /** * Try using `ERR_FAIL_COND_V_MSG` or `ERR_FAIL_V_MSG`. @@ -529,10 +503,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * The current function returns `m_retval`. */ #define ERR_FAIL_V(m_retval) \ - do { \ + if (1) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " __STR(m_value)); \ return m_retval; \ - } while (0) + } else \ + ((void)0) /** * Try using `ERR_FAIL_COND_V_MSG`. @@ -541,10 +516,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Prints `m_msg`, and the current function returns `m_retval`. */ #define ERR_FAIL_V_MSG(m_retval, m_msg) \ - do { \ + if (1) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " __STR(m_value), DEBUG_STR(m_msg)); \ return m_retval; \ - } while (0) + } else \ + ((void)0) /** * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG. @@ -553,22 +529,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * * Prints `m_msg`. */ -#define ERR_PRINT(m_msg) \ - do { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)); \ - } while (0) +#define ERR_PRINT(m_msg) \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)) /** * Prints `m_msg` once during the application lifetime. */ #define ERR_PRINT_ONCE(m_msg) \ - do { \ + if (1) { \ static bool first_print = true; \ if (first_print) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)); \ first_print = false; \ } \ - } while (0) + } else \ + ((void)0) // Print warning message macros. @@ -577,10 +552,8 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ -#define WARN_PRINT(m_msg) \ - do { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \ - } while (0) +#define WARN_PRINT(m_msg) \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING) /** * Prints `m_msg` once during the application lifetime. @@ -588,13 +561,14 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ #define WARN_PRINT_ONCE(m_msg) \ - do { \ + if (1) { \ static bool first_print = true; \ if (first_print) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \ first_print = false; \ } \ - } while (0) + } else \ + ((void)0) // Print deprecated warning message macros. @@ -602,25 +576,27 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Warns that the current function is deprecated. */ #define WARN_DEPRECATED \ - do { \ + if (1) { \ static volatile bool warning_shown = false; \ if (!warning_shown) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", ERR_HANDLER_WARNING); \ warning_shown = true; \ } \ - } while (0) + } else \ + ((void)0) /** * Warns that the current function is deprecated and prints `m_msg`. */ #define WARN_DEPRECATED_MSG(m_msg) \ - do { \ + if (1) { \ static volatile bool warning_shown = false; \ if (!warning_shown) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \ warning_shown = true; \ } \ - } while (0) + } else \ + ((void)0) /** * Do not use. @@ -629,10 +605,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * The application crashes. */ #define CRASH_NOW() \ - do { \ + if (1) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed."); \ GENERATE_TRAP(); \ - } while (0) + } else \ + ((void)0) /** * Only use if the application should never reach this point. @@ -640,9 +617,10 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Prints `m_msg`, and then the application crashes. */ #define CRASH_NOW_MSG(m_msg) \ - do { \ + if (1) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed.", DEBUG_STR(m_msg)); \ GENERATE_TRAP(); \ - } while (0) + } else \ + ((void)0) #endif diff --git a/core/math/rect2.h b/core/math/rect2.h index 9017377770..0d2e7eb6e5 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -60,6 +60,19 @@ struct Rect2 { return true; } + inline bool intersects_touch(const Rect2 &p_rect) const { + if (position.x > (p_rect.position.x + p_rect.size.width)) + return false; + if ((position.x + size.width) < p_rect.position.x) + return false; + if (position.y > (p_rect.position.y + p_rect.size.height)) + return false; + if ((position.y + size.height) < p_rect.position.y) + return false; + + return true; + } + inline real_t distance_to(const Vector2 &p_point) const { real_t dist = 0.0; diff --git a/doc/classes/BoxContainer.xml b/doc/classes/BoxContainer.xml index 214afd519b..4b5d4c853a 100644 --- a/doc/classes/BoxContainer.xml +++ b/doc/classes/BoxContainer.xml @@ -23,7 +23,6 @@ <member name="alignment" type="int" setter="set_alignment" getter="get_alignment" enum="BoxContainer.AlignMode" default="0"> The alignment of the container's children (must be one of [constant ALIGN_BEGIN], [constant ALIGN_CENTER] or [constant ALIGN_END]). </member> - <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" override="true" enum="Control.MouseFilter" default="1" /> </members> <constants> <constant name="ALIGN_BEGIN" value="0" enum="AlignMode"> diff --git a/doc/classes/Container.xml b/doc/classes/Container.xml index 4593e00e05..c285b448d8 100644 --- a/doc/classes/Container.xml +++ b/doc/classes/Container.xml @@ -29,6 +29,9 @@ </description> </method> </methods> + <members> + <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" override="true" enum="Control.MouseFilter" default="1" /> + </members> <signals> <signal name="sort_children"> <description> diff --git a/doc/classes/EditorSceneImporterAssimp.xml b/doc/classes/EditorSceneImporterAssimp.xml index ede3c75b09..c72d4ee25a 100644 --- a/doc/classes/EditorSceneImporterAssimp.xml +++ b/doc/classes/EditorSceneImporterAssimp.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="EditorSceneImporterAssimp" inherits="EditorSceneImporter" version="4.0"> <brief_description> - Multi-format 3D asset importer based on [url=http://assimp.org/]Assimp[/url]. + FBX 3D asset importer based on [url=http://assimp.org/]Assimp[/url]. </brief_description> <description> - This is a multi-format 3D asset importer based on [url=http://assimp.org/]Assimp[/url]. See [url=https://assimp-docs.readthedocs.io/en/latest/about/intoduction.html#installation]this page[/url] for a full list of supported formats. + This is an FBX 3D asset importer based on [url=http://assimp.org/]Assimp[/url]. It currently has many known limitations and works best with static meshes. Most animated meshes won't import correctly. If exporting a FBX scene from Autodesk Maya, use these FBX export settings: [codeblock] - Smoothing Groups diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index 3387150429..cc6e3dc7f9 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -184,6 +184,7 @@ <member name="comment" type="bool" setter="set_comment" getter="is_comment" default="false"> If [code]true[/code], the GraphNode is a comment node. </member> + <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" override="true" enum="Control.MouseFilter" default="0" /> <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2( 0, 0 )"> The offset of the GraphNode, relative to the scroll offset of the [GraphEdit]. [b]Note:[/b] You cannot use position directly, as [GraphEdit] is a [Container]. diff --git a/doc/classes/GridContainer.xml b/doc/classes/GridContainer.xml index 472578f29b..4493ee8dc1 100644 --- a/doc/classes/GridContainer.xml +++ b/doc/classes/GridContainer.xml @@ -15,7 +15,6 @@ <member name="columns" type="int" setter="set_columns" getter="get_columns" default="1"> The number of columns in the [GridContainer]. If modified, [GridContainer] reorders its children to accommodate the new layout. </member> - <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" override="true" enum="Control.MouseFilter" default="1" /> </members> <constants> </constants> diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index 006066dea3..5c4a956c08 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -513,32 +513,46 @@ </constants> <theme_items> <theme_item name="bg" type="StyleBox"> + Default [StyleBox] for the [ItemList], i.e. used when the control is not being focused. </theme_item> <theme_item name="bg_focus" type="StyleBox"> + [StyleBox] used when the [ItemList] is being focused. </theme_item> <theme_item name="cursor" type="StyleBox"> + [StyleBox] used for the cursor, when the [ItemList] is being focused. </theme_item> <theme_item name="cursor_unfocused" type="StyleBox"> + [StyleBox] used for the cursor, when the [ItemList] is not being focused. </theme_item> <theme_item name="font" type="Font"> + [Font] of the item's text. </theme_item> <theme_item name="font_color" type="Color" default="Color( 0.63, 0.63, 0.63, 1 )"> + Default text [Color] of the item. </theme_item> <theme_item name="font_color_selected" type="Color" default="Color( 1, 1, 1, 1 )"> + Text [Color] used when the item is selected. </theme_item> <theme_item name="guide_color" type="Color" default="Color( 0, 0, 0, 0.1 )"> + [Color] of the guideline. The guideline is a line drawn between each row of items. </theme_item> <theme_item name="hseparation" type="int" default="4"> + The horizontal spacing between items. </theme_item> <theme_item name="icon_margin" type="int" default="4"> + The spacing between item's icon and text. </theme_item> <theme_item name="line_separation" type="int" default="2"> + The vertical spacing between each line of text. </theme_item> <theme_item name="selected" type="StyleBox"> + [StyleBox] for the selected items, used when the [ItemList] is not being focused. </theme_item> <theme_item name="selected_focus" type="StyleBox"> + [StyleBox] for the selected items, used when the [ItemList] is being focused. </theme_item> <theme_item name="vseparation" type="int" default="2"> + The vertical spacing between items. </theme_item> </theme_items> </class> diff --git a/doc/classes/PanelContainer.xml b/doc/classes/PanelContainer.xml index 5863093662..9803a8dc51 100644 --- a/doc/classes/PanelContainer.xml +++ b/doc/classes/PanelContainer.xml @@ -10,6 +10,9 @@ </tutorials> <methods> </methods> + <members> + <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" override="true" enum="Control.MouseFilter" default="0" /> + </members> <constants> </constants> <theme_items> diff --git a/doc/classes/Skeleton2D.xml b/doc/classes/Skeleton2D.xml index ccae59d72c..e1b7d60763 100644 --- a/doc/classes/Skeleton2D.xml +++ b/doc/classes/Skeleton2D.xml @@ -4,6 +4,7 @@ Skeleton for 2D characters and animated objects. </brief_description> <description> + Skeleton2D parents a hierarchy of [Bone2D] objects. It is a requirement of [Bone2D]. Skeleton2D holds a reference to the rest pose of its children and acts as a single point of access to its bones. </description> <tutorials> <link>https://docs.godotengine.org/en/latest/tutorials/animation/2d_skeletons.html</link> @@ -15,19 +16,21 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns a [Bone2D] from the node hierarchy parented by Skeleton2D. The object to return is identified by the parameter [code]idx[/code]. Bones are indexed by descending the node hierarchy from top to bottom, adding the children of each branch before moving to the next sibling. </description> </method> <method name="get_bone_count" qualifiers="const"> <return type="int"> </return> <description> - Returns the amount of bones in the skeleton. + Returns the number of [Bone2D] nodes in the node hierarchy parented by Skeleton2D. </description> </method> <method name="get_skeleton" qualifiers="const"> <return type="RID"> </return> <description> + Returns the [RID] of a Skeleton2D instance. </description> </method> </methods> diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index a28dcec92b..54aa85ff48 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -387,80 +387,112 @@ </constants> <theme_items> <theme_item name="arrow" type="Texture"> + The arrow icon used when a foldable item is not collapsed. </theme_item> <theme_item name="arrow_collapsed" type="Texture"> + The arrow icon used when a foldable item is collapsed. </theme_item> <theme_item name="bg" type="StyleBox"> + Default [StyleBox] for the [Tree], i.e. used when the control is not being focused. </theme_item> <theme_item name="bg_focus" type="StyleBox"> + [StyleBox] used when the [Tree] is being focused. </theme_item> <theme_item name="button_margin" type="int" default="4"> + The horizontal space between each button in a cell. </theme_item> <theme_item name="button_pressed" type="StyleBox"> + [StyleBox] used when a button in the tree is pressed. </theme_item> <theme_item name="checked" type="Texture"> + The check icon to display when the [constant TreeItem.CELL_MODE_CHECK] mode cell is checked. </theme_item> <theme_item name="cursor" type="StyleBox"> - </theme_item> - <theme_item name="cursor_color" type="Color" default="Color( 0, 0, 0, 1 )"> + [StyleBox] used for the cursor, when the [Tree] is being focused. </theme_item> <theme_item name="cursor_unfocused" type="StyleBox"> + [StyleBox] used for the cursor, when the [Tree] is not being focused. </theme_item> <theme_item name="custom_button" type="StyleBox"> + Default [StyleBox] for a [constant TreeItem.CELL_MODE_CUSTOM] mode cell. </theme_item> <theme_item name="custom_button_font_highlight" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )"> + Text [Color] for a [constant TreeItem.CELL_MODE_CUSTOM] mode cell when it's hovered. </theme_item> <theme_item name="custom_button_hover" type="StyleBox"> + [StyleBox] for a [constant TreeItem.CELL_MODE_CUSTOM] mode cell when it's hovered. </theme_item> <theme_item name="custom_button_pressed" type="StyleBox"> + [StyleBox] for a [constant TreeItem.CELL_MODE_CUSTOM] mode cell when it's pressed. </theme_item> <theme_item name="draw_guides" type="int" default="1"> + Draws the guidelines if not zero, this acts as a boolean. The guideline is a horizontal line drawn at the bottom of each item. </theme_item> <theme_item name="draw_relationship_lines" type="int" default="0"> + Draws the relationship lines if not zero, this acts as a boolean. Relationship lines are drawn at the start of child items to show hierarchy. </theme_item> <theme_item name="drop_position_color" type="Color" default="Color( 1, 0.3, 0.2, 1 )"> + [Color] used to draw possible drop locations. See [enum DropModeFlags] constants for further description of drop locations. </theme_item> <theme_item name="font" type="Font"> + [Font] of the item's text. </theme_item> <theme_item name="font_color" type="Color" default="Color( 0.69, 0.69, 0.69, 1 )"> + Default text [Color] of the item. </theme_item> <theme_item name="font_color_selected" type="Color" default="Color( 1, 1, 1, 1 )"> + Text [Color] used when the item is selected. </theme_item> <theme_item name="guide_color" type="Color" default="Color( 0, 0, 0, 0.1 )"> + [Color] of the guideline. </theme_item> <theme_item name="hseparation" type="int" default="4"> + The horizontal space between item cells. This is also used as the margin at the start of an item when folding is disabled. </theme_item> <theme_item name="item_margin" type="int" default="12"> + The horizontal margin at the start of an item. This is used when folding is enabled for the item. </theme_item> <theme_item name="relationship_line_color" type="Color" default="Color( 0.27, 0.27, 0.27, 1 )"> + [Color] of the relationship lines. </theme_item> <theme_item name="scroll_border" type="int" default="4"> + The maximum distance between the mouse cursor and the control's border to trigger border scrolling when dragging. </theme_item> <theme_item name="scroll_speed" type="int" default="12"> + The speed of border scrolling. </theme_item> <theme_item name="select_arrow" type="Texture"> + The arrow icon to display for the [constant TreeItem.CELL_MODE_RANGE] mode cell. </theme_item> <theme_item name="selected" type="StyleBox"> + [StyleBox] for the selected items, used when the [Tree] is not being focused. </theme_item> <theme_item name="selected_focus" type="StyleBox"> - </theme_item> - <theme_item name="selection_color" type="Color" default="Color( 0.1, 0.1, 1, 0.8 )"> + [StyleBox] for the selected items, used when the [Tree] is being focused. </theme_item> <theme_item name="title_button_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> + Default text [Color] of the title button. </theme_item> <theme_item name="title_button_font" type="Font"> + [Font] of the title button's text. </theme_item> <theme_item name="title_button_hover" type="StyleBox"> + [StyleBox] used when the title button is being hovered. </theme_item> <theme_item name="title_button_normal" type="StyleBox"> + Default [StyleBox] for the title button. </theme_item> <theme_item name="title_button_pressed" type="StyleBox"> + [StyleBox] used when the title button is being pressed. </theme_item> <theme_item name="unchecked" type="Texture"> + The check icon to display when the [constant TreeItem.CELL_MODE_CHECK] mode cell is unchecked. </theme_item> <theme_item name="updown" type="Texture"> + The updown arrow icon to display for the [constant TreeItem.CELL_MODE_RANGE] mode cell. </theme_item> <theme_item name="vseparation" type="int" default="4"> + The vertical padding inside each item, i.e. the distance between the item's content and top/bottom border. </theme_item> </theme_items> </class> diff --git a/doc/classes/VisualShaderNodeScalarUniform.xml b/doc/classes/VisualShaderNodeScalarUniform.xml index d1a4742555..fab766d3f9 100644 --- a/doc/classes/VisualShaderNodeScalarUniform.xml +++ b/doc/classes/VisualShaderNodeScalarUniform.xml @@ -1,13 +1,38 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeScalarUniform" inherits="VisualShaderNodeUniform" version="4.0"> <brief_description> + A scalar uniform to be used within the visual shader graph. </brief_description> <description> + Translated to [code]uniform float[/code] in the shader language. </description> <tutorials> </tutorials> <methods> </methods> + <members> + <member name="hint" type="int" setter="set_hint" getter="get_hint" enum="VisualShaderNodeScalarUniform.Hint" default="0"> + A hint applied to the uniform, which controls the values it can take when set through the inspector. + </member> + <member name="max" type="float" setter="set_max" getter="get_max" default="1.0"> + Minimum value for range hints. Used if [member hint] is set to [constant HINT_RANGE] or [constant HINT_RANGE_STEP]. + </member> + <member name="min" type="float" setter="set_min" getter="get_min" default="0.0"> + Maximum value for range hints. Used if [member hint] is set to [constant HINT_RANGE] or [constant HINT_RANGE_STEP]. + </member> + <member name="step" type="float" setter="set_step" getter="get_step" default="0.1"> + Step (increment) value for the range hint with step. Used if [member hint] is set to [constant HINT_RANGE_STEP]. + </member> + </members> <constants> + <constant name="HINT_NONE" value="0" enum="Hint"> + No hint used. + </constant> + <constant name="HINT_RANGE" value="1" enum="Hint"> + A range hint for scalar value, which limits possible input values between [member min] and [member max]. Translated to [code]hint_range(min, max)[/code] in shader code. + </constant> + <constant name="HINT_RANGE_STEP" value="2" enum="Hint"> + A range hint for scalar value with step, which limits possible input values between [member min] and [member max], with a step (increment) of [member step]). Translated to [code]hint_range(min, max, step)[/code] in shader code. + </constant> </constants> </class> diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index c0ba93db6a..bb6a45e240 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -53,6 +53,11 @@ #endif #endif +#if !defined(GLES_OVER_GL) +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_3D 0x806F +#endif + static const GLenum _cube_side_enum[6] = { GL_TEXTURE_CUBE_MAP_NEGATIVE_X, @@ -1343,6 +1348,7 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m const Pair<StringName, RID> *textures = p_material->textures.ptr(); const ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptr(); + const ShaderLanguage::DataType *texture_types = p_material->shader->texture_types.ptr(); state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size); @@ -1356,22 +1362,66 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m if (!t) { - switch (texture_hints[i]) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { - glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); + GLenum target = GL_TEXTURE_2D; + GLuint tex = 0; + switch (texture_types[i]) { + case ShaderLanguage::TYPE_ISAMPLER2D: + case ShaderLanguage::TYPE_USAMPLER2D: + case ShaderLanguage::TYPE_SAMPLER2D: { + + switch (texture_hints[i]) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { + tex = storage->resources.black_tex; + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { + tex = storage->resources.aniso_tex; + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { + tex = storage->resources.normal_tex; + } break; + default: { + tex = storage->resources.white_tex; + } break; + } + + } break; + + case ShaderLanguage::TYPE_SAMPLERCUBE: { + // TODO } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { - glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex); + + case ShaderLanguage::TYPE_ISAMPLER3D: + case ShaderLanguage::TYPE_USAMPLER3D: + case ShaderLanguage::TYPE_SAMPLER3D: { + + target = GL_TEXTURE_3D; + tex = storage->resources.white_tex_3d; + + //switch (texture_hints[i]) { + // TODO + //} + } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); + + case ShaderLanguage::TYPE_ISAMPLER2DARRAY: + case ShaderLanguage::TYPE_USAMPLER2DARRAY: + case ShaderLanguage::TYPE_SAMPLER2DARRAY: { + + target = GL_TEXTURE_2D_ARRAY; + tex = storage->resources.white_tex_array; + + //switch (texture_hints[i]) { + // TODO + //} + } break; + default: { - glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - } break; + } } + glBindTexture(target, tex); continue; } diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 828f6907e3..a1c5d20a14 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -103,6 +103,13 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT #define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT #define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleEXT +PFNGLTEXIMAGE3DOESPROC glTexImage3DOES; +PFNGLTEXSUBIMAGE3DOESPROC glTexSubImage3DOES; +PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glCompressedTexSubImage3DOES; +#define glTexImage3D glTexImage3DOES +#define glTexSubImage3D glTexSubImage3DOES +#define glCompressedTexSubImage3D glCompressedTexSubImage3DOES + #elif defined(UWP_ENABLED) #include <GLES2/gl2ext.h> #define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleANGLE @@ -113,6 +120,11 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT #define GL_MAX_SAMPLES 0x8D57 #endif //!GLES_OVER_GL +#if !defined(GLES_OVER_GL) +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_3D 0x806F +#endif + void RasterizerStorageGLES2::bind_quad_array() const { glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); @@ -566,11 +578,23 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ texture->target = GL_TEXTURE_CUBE_MAP; texture->images.resize(6); } break; - case VS::TEXTURE_TYPE_2D_ARRAY: + case VS::TEXTURE_TYPE_2D_ARRAY: { + if (config.texture_array_supported) { + texture->target = GL_TEXTURE_2D_ARRAY; + texture->images.resize(p_depth_3d); + } else { + WARN_PRINT_ONCE("Texture Arrays not supported on this hardware."); + return; + } + } break; case VS::TEXTURE_TYPE_3D: { - texture->target = GL_TEXTURE_3D; - ERR_PRINT("3D textures and Texture Arrays are not supported in GLES2. Please switch to the GLES3 backend."); - return; + if (config.texture_3d_supported) { + texture->target = GL_TEXTURE_3D; + texture->images.resize(p_depth_3d); + } else { + WARN_PRINT_ONCE("3D textures not supported on this hardware."); + return; + } } break; default: { ERR_PRINT("Unknown texture type!"); @@ -615,7 +639,42 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); - if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { +#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED) + if ((p_type == VS::TEXTURE_TYPE_3D && config.texture_3d_supported) || (p_type == VS::TEXTURE_TYPE_2D_ARRAY && config.texture_array_supported)) { + + int width = p_width; + int height = p_height; + int depth = p_depth_3d; + + int mipmaps = 0; + + while (width > 0 || height > 0 || (p_type == VS::TEXTURE_TYPE_3D && depth > 0)) { + width = MAX(1, width); + height = MAX(1, height); + depth = MAX(1, depth); + + glTexImage3D(texture->target, mipmaps, internal_format, width, height, depth, 0, format, type, NULL); + + width /= 2; + height /= 2; + + if (p_type == VS::TEXTURE_TYPE_3D) { + depth /= 2; + } + + mipmaps++; + + if (!(p_flags & VS::TEXTURE_FLAG_MIPMAPS)) + break; + } +#ifdef GLES_OVER_GL + glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1); +#endif + + } else +#endif + if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { //prealloc if video glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL); } @@ -627,8 +686,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p Texture *texture = texture_owner.getornull(p_texture); ERR_FAIL_COND(!texture); - if (texture->target == GL_TEXTURE_3D) { - // Target is set to a 3D texture or array texture, exit early to avoid spamming errors + if ((texture->type == VS::TEXTURE_TYPE_2D_ARRAY && !config.texture_array_supported) || (texture->type == VS::TEXTURE_TYPE_3D && !config.texture_3d_supported)) { return; } ERR_FAIL_COND(!texture->active); @@ -673,7 +731,23 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p } } - GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D; + GLenum blit_target = GL_TEXTURE_2D; + + switch (texture->type) { + case VS::TEXTURE_TYPE_2D: { + blit_target = GL_TEXTURE_2D; + } break; + case VS::TEXTURE_TYPE_CUBEMAP: { + ERR_FAIL_INDEX(p_layer, 6); + blit_target = _cube_side_enum[p_layer]; + } break; + case VS::TEXTURE_TYPE_2D_ARRAY: { + blit_target = GL_TEXTURE_2D_ARRAY; + } break; + case VS::TEXTURE_TYPE_3D: { + blit_target = GL_TEXTURE_3D; + } break; + } texture->data_size = img->get_data().size(); PoolVector<uint8_t>::Read read = img->get_data().read(); @@ -730,23 +804,41 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p int size, ofs; img->get_mipmap_offset_and_size(i, ofs, size); + if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) { - if (compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + if (compressed) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - int bw = w; - int bh = h; + int bw = w; + int bh = h; - glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]); - } else { + glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]); + } else { + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]); + } else { + glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]); + } + } + } +#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED) + else { + if (texture->compressed) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { - glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]); + int bw = w; + int bh = h; + + glCompressedTexSubImage3D(blit_target, i, 0, 0, p_layer, bw, bh, 1, internal_format, size, &read[ofs]); } else { - glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glTexSubImage3D(blit_target, i, 0, 0, p_layer, w, h, 1, format, type, &read[ofs]); } } +#endif tsize += size; @@ -1492,6 +1584,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { p_shader->texture_count = gen_code.texture_uniforms.size(); p_shader->texture_hints = gen_code.texture_hints; + p_shader->texture_types = gen_code.texture_types; p_shader->uses_vertex_time = gen_code.uses_vertex_time; p_shader->uses_fragment_time = gen_code.uses_fragment_time; @@ -1639,11 +1732,19 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn case ShaderLanguage::TYPE_SAMPLER2DARRAY: case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: + case ShaderLanguage::TYPE_USAMPLER2DARRAY: { + + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "TextureArray"; + } break; + case ShaderLanguage::TYPE_SAMPLER3D: case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: { - // Not implemented in GLES2 + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Texture3D"; } break; } @@ -5795,6 +5896,8 @@ void RasterizerStorageGLES2::initialize() { config.depth_type = GL_UNSIGNED_INT; #ifdef GLES_OVER_GL + config.texture_3d_supported = true; + config.texture_array_supported = config.extensions.has("GL_EXT_texture_array"); config.float_texture_supported = true; config.s3tc_supported = true; config.pvrtc_supported = false; @@ -5802,6 +5905,8 @@ void RasterizerStorageGLES2::initialize() { config.support_npot_repeat_mipmap = true; config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24; #else + config.texture_3d_supported = config.extensions.has("GL_OES_texture_3D"); + config.texture_array_supported = false; config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float"); config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc"); config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1"); @@ -5840,6 +5945,9 @@ void RasterizerStorageGLES2::initialize() { void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY); glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT"); glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glFramebufferTexture2DMultisampleEXT"); + glTexImage3DOES = (PFNGLTEXIMAGE3DOESPROC)dlsym(gles2_lib, "glTexImage3DOES"); + glTexSubImage3DOES = (PFNGLTEXSUBIMAGE3DOESPROC)dlsym(gles2_lib, "glTexSubImage3DOES"); + glCompressedTexSubImage3DOES = (PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC)dlsym(gles2_lib, "glCompressedTexSubImage3DOES"); #endif #endif @@ -6062,6 +6170,26 @@ void RasterizerStorageGLES2::initialize() { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata); glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); + +#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED) + glGenTextures(1, &resources.white_tex_3d); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_3D, resources.white_tex_3d); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 2, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata); + +#ifdef GLES_OVER_GL + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0); +#endif + + glGenTextures(1, &resources.white_tex_array); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D_ARRAY, resources.white_tex_array); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 8, 8, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 1, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata); + glGenerateMipmap(GL_TEXTURE_2D_ARRAY); + glBindTexture(GL_TEXTURE_2D, 0); +#endif } // skeleton buffer diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 83697b9872..d006d2e7f4 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -71,6 +71,8 @@ public: Set<String> extensions; + bool texture_3d_supported; + bool texture_array_supported; bool float_texture_supported; bool s3tc_supported; bool etc1_supported; @@ -109,6 +111,8 @@ public: GLuint black_tex; GLuint normal_tex; GLuint aniso_tex; + GLuint white_tex_3d; + GLuint white_tex_array; GLuint mipmap_blur_fbo; GLuint mipmap_blur_color; @@ -414,6 +418,7 @@ public: Map<StringName, RID> default_textures; + Vector<ShaderLanguage::DataType> texture_types; Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints; bool valid; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 5dec6f2fee..b4b9b70abc 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -305,6 +305,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener r_gen_code.texture_uniforms.resize(max_texture_uniforms); r_gen_code.texture_hints.resize(max_texture_uniforms); + r_gen_code.texture_types.resize(max_texture_uniforms); r_gen_code.uniforms.resize(max_uniforms + max_texture_uniforms); @@ -332,6 +333,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener if (SL::is_sampler_type(E->get().type)) { r_gen_code.texture_uniforms.write[E->get().texture_order] = E->key(); r_gen_code.texture_hints.write[E->get().texture_order] = E->get().hint; + r_gen_code.texture_types.write[E->get().texture_order] = E->get().type; } else { r_gen_code.uniforms.write[E->get().order] = E->key(); } @@ -660,6 +662,10 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener code += "texture2D"; } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) { code += "textureCube"; + } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER3D) { + code += "texture3D"; + } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2DARRAY) { + code += "texture2DArray"; } } else if (var_node->name == "textureLod") { @@ -669,6 +675,10 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener code += "texture2DLod"; } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) { code += "textureCubeLod"; + } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER3D) { + code += "texture3DLod"; + } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2DARRAY) { + code += "texture2DArrayLod"; } } else if (var_node->name == "mix") { @@ -869,6 +879,7 @@ Error ShaderCompilerGLES2::compile(VS::ShaderMode p_mode, const String &p_code, r_gen_code.uniforms.clear(); r_gen_code.texture_uniforms.clear(); r_gen_code.texture_hints.clear(); + r_gen_code.texture_types.clear(); r_gen_code.vertex = String(); r_gen_code.vertex_global = String(); r_gen_code.fragment = String(); diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 683c8bf3c4..15cfac9f03 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -54,6 +54,7 @@ public: Vector<CharString> custom_defines; Vector<StringName> uniforms; Vector<StringName> texture_uniforms; + Vector<ShaderLanguage::DataType> texture_types; Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints; String vertex_global; diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index afce403a9f..3b685b3f0b 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -10,6 +10,12 @@ precision highp float; precision highp int; #endif +#ifndef USE_GLES_OVER_GL +#extension GL_OES_texture_3D : enable +#else +#extension GL_EXT_texture_array : enable +#endif + uniform highp mat4 projection_matrix; /* clang-format on */ @@ -229,6 +235,12 @@ VERTEX_SHADER_CODE /* clang-format off */ [fragment] +#ifndef USE_GLES_OVER_GL +#extension GL_OES_texture_3D : enable +#else +#extension GL_EXT_texture_array : enable +#endif + // texture2DLodEXT and textureCubeLodEXT are fragment shader specific. // Do not copy these defines in the vertex section. #ifndef USE_GLES_OVER_GL diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index ac7a8796a3..84aadcbbc3 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -10,6 +10,12 @@ precision highp float; precision highp int; #endif +#ifndef USE_GLES_OVER_GL +#extension GL_OES_texture_3D : enable +#else +#extension GL_EXT_texture_array : enable +#endif + /* clang-format on */ #include "stdlib.glsl" /* clang-format off */ @@ -672,6 +678,12 @@ VERTEX_SHADER_CODE /* clang-format off */ [fragment] +#ifndef USE_GLES_OVER_GL +#extension GL_OES_texture_3D : enable +#else +#extension GL_EXT_texture_array : enable +#endif + // texture2DLodEXT and textureCubeLodEXT are fragment shader specific. // Do not copy these defines in the vertex section. #ifndef USE_GLES_OVER_GL diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 8037045e77..28bc20a957 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -35,7 +35,11 @@ #include "editor_icons.gen.h" #include "editor_scale.h" #include "editor_settings.h" + +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_SVG_ENABLED #include "modules/svg/image_loader_svg.h" +#endif static Ref<StyleBoxTexture> make_stylebox(Ref<Texture> p_texture, float p_left, float p_top, float p_right, float p_botton, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1, bool p_draw_center = true) { Ref<StyleBoxTexture> style(memnew(StyleBoxTexture)); @@ -109,7 +113,7 @@ Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = true, int p_thumb_size = 32, bool p_only_thumbs = false) { -#ifdef SVG_ENABLED +#ifdef MODULE_SVG_ENABLED // The default icon theme is designed to be used for a dark theme. // This dictionary stores color codes to convert to other colors // for better readability on a light theme. diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index fc9c877ac7..d4664e1bb9 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "editor_scene_importer_gltf.h" + #include "core/crypto/crypto_core.h" #include "core/io/json.h" #include "core/math/disjoint_set.h" diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 07b87633a9..1506ba319c 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -35,9 +35,13 @@ #include "editor/editor_plugin.h" #include "editor/editor_scale.h" #include "editor/project_settings_editor.h" -#include "modules/gdscript/gdscript.h" #include "scene/gui/grid_container.h" +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_GDSCRIPT_ENABLED +#include "modules/gdscript/gdscript.h" +#endif + void PluginConfigDialog::_clear_fields() { name_edit->set_text(""); subfolder_edit->set_text(""); @@ -75,6 +79,9 @@ void PluginConfigDialog::_on_confirmed() { // TODO Use script templates. Right now, this code won't add the 'tool' annotation to other languages. // TODO Better support script languages with named classes (has_named_classes). + // FIXME: It's hacky to have hardcoded access to the GDScript module here. + // The editor code should not have to know what languages are enabled. +#ifdef MODULE_GDSCRIPT_ENABLED if (lang_name == GDScriptLanguage::get_singleton()->get_name()) { // Hard-coded GDScript template to keep usability until we use script templates. Ref<Script> gdscript = memnew(GDScript); @@ -95,12 +102,15 @@ void PluginConfigDialog::_on_confirmed() { ResourceSaver::save(script_path, gdscript); script = gdscript; } else { +#endif String script_path = path.plus_file(script_edit->get_text()); String class_name = script_path.get_file().get_basename(); script = ScriptServer::get_language(lang_idx)->get_template(class_name, "EditorPlugin"); script->set_path(script_path); ResourceSaver::save(script_path, script); +#ifdef MODULE_GDSCRIPT_ENABLED } +#endif emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? subfolder_edit->get_text() : ""); } else { @@ -229,9 +239,11 @@ PluginConfigDialog::PluginConfigDialog() { for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptLanguage *lang = ScriptServer::get_language(i); script_option_edit->add_item(lang->get_name()); +#ifdef MODULE_GDSCRIPT_ENABLED if (lang == GDScriptLanguage::get_singleton()) { default_lang = i; } +#endif } script_option_edit->select(default_lang); grid->add_child(script_option_edit); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 1d8f3a2bbd..a0e5b1c6ea 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4967,6 +4967,7 @@ void CanvasItemEditor::_focus_selection(int p_op) { zoom = scale_x < scale_y ? scale_x : scale_y; zoom *= 0.90; viewport->update(); + _update_zoom_label(); call_deferred("_popup_callback", VIEW_CENTER_TO_SELECTION); } } diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index c24a666c55..a19f0b4975 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -369,6 +369,7 @@ void ShaderEditor::_editor_settings_changed() { shader_editor->get_text_edit()->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type")); shader_editor->get_text_edit()->set_auto_indent(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent")); shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs")); + shader_editor->get_text_edit()->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/indent/draw_spaces")); shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers")); shader_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting")); shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences")); @@ -381,6 +382,9 @@ void ShaderEditor::_editor_settings_changed() { shader_editor->get_text_edit()->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed")); shader_editor->get_text_edit()->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap")); shader_editor->get_text_edit()->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE); + shader_editor->get_text_edit()->set_show_line_length_guideline(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guideline")); + shader_editor->get_text_edit()->set_line_length_guideline_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_column")); + shader_editor->get_text_edit()->set_breakpoint_gutter_enabled(false); } void ShaderEditor::_bind_methods() { diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index 8b5fe7d2c5..9101c64eab 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -103,8 +103,10 @@ void SkeletonEditor::create_physical_skeleton() { PhysicalBone *SkeletonEditor::create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos) { - real_t half_height(skeleton->get_bone_rest(bone_child_id).origin.length() * 0.5); - real_t radius(half_height * 0.2); + const Transform child_rest = skeleton->get_bone_rest(bone_child_id); + + const real_t half_height(child_rest.origin.length() * 0.5); + const real_t radius(half_height * 0.2); CapsuleShape *bone_shape_capsule = memnew(CapsuleShape); bone_shape_capsule->set_height((half_height - radius) * 2); @@ -114,7 +116,8 @@ PhysicalBone *SkeletonEditor::create_physical_bone(int bone_id, int bone_child_i bone_shape->set_shape(bone_shape_capsule); Transform body_transform; - body_transform.origin = Vector3(0, 0, -half_height); + body_transform.set_look_at(Vector3(0, 0, 0), child_rest.origin, Vector3(0, 1, 0)); + body_transform.origin = body_transform.basis.xform(Vector3(0, 0, -half_height)); Transform joint_transform; joint_transform.origin = Vector3(0, 0, half_height); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index e334d4b093..fb095692bc 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -556,6 +556,7 @@ void VisualShaderEditor::_update_graph() { } Ref<VisualShaderNodeUniform> uniform = vsnode; + Ref<VisualShaderNodeScalarUniform> scalar_uniform = vsnode; if (uniform.is_valid()) { graph->add_child(node); _update_created_node(node); @@ -570,7 +571,9 @@ void VisualShaderEditor::_update_graph() { //shortcut VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); - continue; + if (!scalar_uniform.is_valid()) { + continue; + } } port_offset++; } @@ -582,11 +585,16 @@ void VisualShaderEditor::_update_graph() { } } - if (custom_editor && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { + if (custom_editor && !scalar_uniform.is_valid() && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { //will be embedded in first port } else if (custom_editor) { + port_offset++; node->add_child(custom_editor); + if (scalar_uniform.is_valid()) { + custom_editor->call_deferred("_show_prop_names", true); + continue; + } custom_editor = NULL; } @@ -2972,6 +2980,13 @@ public: bool updating; Ref<VisualShaderNode> node; Vector<EditorProperty *> properties; + Vector<Label *> prop_names; + + void _show_prop_names(bool p_show) { + for (int i = 0; i < prop_names.size(); i++) { + prop_names[i]->set_visible(p_show); + } + } void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, Ref<VisualShaderNode> p_node) { parent_resource = p_parent_resource; @@ -2981,7 +2996,20 @@ public: for (int i = 0; i < p_properties.size(); i++) { - add_child(p_properties[i]); + HBoxContainer *hbox = memnew(HBoxContainer); + hbox->set_h_size_flags(SIZE_EXPAND_FILL); + add_child(hbox); + + Label *prop_name = memnew(Label); + String prop_name_str = p_names[i]; + prop_name_str = prop_name_str.capitalize() + ":"; + prop_name->set_text(prop_name_str); + prop_name->set_visible(false); + hbox->add_child(prop_name); + prop_names.push_back(prop_name); + + p_properties[i]->set_h_size_flags(SIZE_EXPAND_FILL); + hbox->add_child(p_properties[i]); bool res_prop = Object::cast_to<EditorPropertyResource>(p_properties[i]); if (res_prop) { @@ -3003,6 +3031,7 @@ public: ClassDB::bind_method("_refresh_request", &VisualShaderNodePluginDefaultEditor::_refresh_request); ClassDB::bind_method("_resource_selected", &VisualShaderNodePluginDefaultEditor::_resource_selected); ClassDB::bind_method("_open_inspector", &VisualShaderNodePluginDefaultEditor::_open_inspector); + ClassDB::bind_method("_show_prop_names", &VisualShaderNodePluginDefaultEditor::_show_prop_names); } }; diff --git a/main/tests/test_gdscript.cpp b/main/tests/test_gdscript.cpp index a6ef0e9cf4..a2891de8ff 100644 --- a/main/tests/test_gdscript.cpp +++ b/main/tests/test_gdscript.cpp @@ -34,7 +34,8 @@ #include "core/os/main_loop.h" #include "core/os/os.h" -#ifdef GDSCRIPT_ENABLED +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_GDSCRIPT_ENABLED #include "modules/gdscript/gdscript.h" #include "modules/gdscript/gdscript_compiler.h" @@ -1091,7 +1092,7 @@ MainLoop *test(TestType p_type) { namespace TestGDScript { MainLoop *test(TestType p_type) { - + ERR_PRINT("The GDScript module is disabled, therefore GDScript tests cannot be used."); return NULL; } } // namespace TestGDScript diff --git a/main/tests/test_string.cpp b/main/tests/test_string.cpp index 9e8c8706ff..eef3d9b84c 100644 --- a/main/tests/test_string.cpp +++ b/main/tests/test_string.cpp @@ -28,15 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "core/ustring.h" -#include <wchar.h> -//#include "core/math/math_funcs.h" +#include "test_string.h" + #include "core/io/ip_address.h" #include "core/os/os.h" +#include "core/ustring.h" + +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_REGEX_ENABLED #include "modules/regex/regex.h" -#include <stdio.h> +#endif -#include "test_string.h" +#include <stdio.h> +#include <wchar.h> namespace TestString { diff --git a/methods.py b/methods.py index 33b8f1cbe7..a1d101af18 100644 --- a/methods.py +++ b/methods.py @@ -160,20 +160,22 @@ def detect_modules(): except IOError: pass - modules_cpp = """ -// modules.cpp - THIS FILE IS GENERATED, DO NOT EDIT!!!!!!! + modules_cpp = """// register_module_types.gen.cpp +/* THIS FILE IS GENERATED DO NOT EDIT */ #include "register_module_types.h" -""" + includes_cpp + """ +#include "modules/modules_enabled.gen.h" + +%s void register_module_types() { -""" + register_cpp + """ +%s } void unregister_module_types() { -""" + unregister_cpp + """ +%s } -""" +""" % (includes_cpp, register_cpp, unregister_cpp) # NOTE: It is safe to generate this file here, since this is still executed serially with open("modules/register_module_types.gen.cpp", "w") as f: @@ -200,38 +202,11 @@ def win32_spawn(sh, escape, cmd, args, env): print("=====") return rv -""" -def win32_spawn(sh, escape, cmd, args, spawnenv): - import win32file - import win32event - import win32process - import win32security - for var in spawnenv: - spawnenv[var] = spawnenv[var].encode('ascii', 'replace') - - sAttrs = win32security.SECURITY_ATTRIBUTES() - StartupInfo = win32process.STARTUPINFO() - newargs = ' '.join(map(escape, args[1:])) - cmdline = cmd + " " + newargs - - # check for any special operating system commands - if cmd == 'del': - for arg in args[1:]: - win32file.DeleteFile(arg) - exit_code = 0 - else: - # otherwise execute the command. - hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(None, cmdline, None, None, 1, 0, spawnenv, None, StartupInfo) - win32event.WaitForSingleObject(hProcess, win32event.INFINITE) - exit_code = win32process.GetExitCodeProcess(hProcess) - win32file.CloseHandle(hProcess); - win32file.CloseHandle(hThread); - return exit_code -""" def disable_module(self): self.disabled_modules.append(self.current_module) + def use_windows_spawn_fix(self, platform=None): if (os.name != "nt"): @@ -282,67 +257,6 @@ def use_windows_spawn_fix(self, platform=None): self['SPAWN'] = mySpawn -def split_lib(self, libname, src_list = None, env_lib = None): - env = self - - num = 0 - cur_base = "" - max_src = 64 - list = [] - lib_list = [] - - if src_list is None: - src_list = getattr(env, libname + "_sources") - - if type(env_lib) == type(None): - env_lib = env - - for f in src_list: - fname = "" - if type(f) == type(""): - fname = env.File(f).path - else: - fname = env.File(f)[0].path - fname = fname.replace("\\", "/") - base = "/".join(fname.split("/")[:2]) - if base != cur_base and len(list) > max_src: - if num > 0: - lib = env_lib.add_library(libname + str(num), list) - lib_list.append(lib) - list = [] - num = num + 1 - cur_base = base - list.append(f) - - lib = env_lib.add_library(libname + str(num), list) - lib_list.append(lib) - - lib_base = [] - env_lib.add_source_files(lib_base, "*.cpp") - lib = env_lib.add_library(libname, lib_base) - lib_list.insert(0, lib) - - env.Prepend(LIBS=lib_list) - - # When we split modules into arbitrary chunks, we end up with linking issues - # due to symbol dependencies split over several libs, which may not be linked - # in the required order. We use --start-group and --end-group to tell the - # linker that those archives should be searched repeatedly to resolve all - # undefined references. - # As SCons doesn't give us much control over how inserting libs in LIBS - # impacts the linker call, we need to hack our way into the linking commands - # LINKCOM and SHLINKCOM to set those flags. - - if '-Wl,--start-group' in env['LINKCOM'] and '-Wl,--start-group' in env['SHLINKCOM']: - # Already added by a previous call, skip. - return - - env['LINKCOM'] = str(env['LINKCOM']).replace('$_LIBFLAGS', - '-Wl,--start-group $_LIBFLAGS -Wl,--end-group') - env['SHLINKCOM'] = str(env['LINKCOM']).replace('$_LIBFLAGS', - '-Wl,--start-group $_LIBFLAGS -Wl,--end-group') - - def save_active_platforms(apnames, ap): for x in ap: diff --git a/misc/dist/html/fixed-size.html b/misc/dist/html/fixed-size.html index 1cc6fd715e..6c6a3a5d2d 100644 --- a/misc/dist/html/fixed-size.html +++ b/misc/dist/html/fixed-size.html @@ -2,6 +2,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> <head> <meta charset="utf-8" /> + <link id='-gd-engine-icon' rel='icon' type='image/png' href='favicon.png' /> <title></title> <style type="text/css"> diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html index 9269227d02..92b65257d4 100644 --- a/misc/dist/html/full-size.html +++ b/misc/dist/html/full-size.html @@ -3,6 +3,7 @@ <head> <meta charset='utf-8' /> <meta name='viewport' content='width=device-width, user-scalable=no' /> + <link id='-gd-engine-icon' rel='icon' type='image/png' href='favicon.png' /> <title></title> <style type='text/css'> diff --git a/modules/SCsub b/modules/SCsub index dc0420616c..5b39b18334 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -2,23 +2,32 @@ Import('env') +import modules_builders + env_modules = env.Clone() Export('env_modules') -env.modules_sources = [] +# Header with MODULE_*_ENABLED defines. +env.CommandNoCache("modules_enabled.gen.h", Value(env.module_list), modules_builders.generate_modules_enabled) -env_modules.add_source_files(env.modules_sources, "register_module_types.gen.cpp") +# libmodule_<name>.a for each active module. +for module in env.module_list: + env.modules_sources = [] + SConscript(module + "/SCsub") -for x in env.module_list: - if (x in env.disabled_modules): + # Some modules are not linked automatically but can be enabled optionally + # on iOS, so we handle those specially. + if env["platform"] == "iphone" and module in ["arkit", "camera"]: continue - env_modules.Append(CPPDEFINES=["MODULE_" + x.upper() + "_ENABLED"]) - SConscript(x + "/SCsub") - -if env['split_libmodules']: - env.split_lib("modules", env_lib = env_modules) -else: - lib = env_modules.add_library("modules", env.modules_sources) + lib = env_modules.add_library("module_%s" % module, env.modules_sources) env.Prepend(LIBS=[lib]) + +# libmodules.a with only register_module_types. +# Must be last so that all libmodule_<name>.a libraries are on the right side +# in the linker command. +env.modules_sources = [] +env_modules.add_source_files(env.modules_sources, "register_module_types.gen.cpp") +lib = env_modules.add_library("modules", env.modules_sources) +env.Prepend(LIBS=[lib]) diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index 8f4a8de895..7b66aa1c76 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -102,5 +102,3 @@ if env['builtin_freetype']: # Godot source files env_freetype.add_source_files(env.modules_sources, "*.cpp") -# Used in scene/, needs to be in main env -env.Append(CPPDEFINES=['FREETYPE_ENABLED']) diff --git a/modules/modules_builders.py b/modules/modules_builders.py new file mode 100644 index 0000000000..0e9cba2b0b --- /dev/null +++ b/modules/modules_builders.py @@ -0,0 +1,16 @@ +"""Functions used to generate source files during build time + +All such functions are invoked in a subprocess on Windows to prevent build flakiness. +""" + +from platform_methods import subprocess_main + + +def generate_modules_enabled(target, source, env): + with open(target[0].path, 'w') as f: + for module in env.module_list: + f.write('#define %s\n' % ("MODULE_" + module.upper() + "_ENABLED")) + + +if __name__ == '__main__': + subprocess_main(globals()) diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 752fc9e2cc..2847f3b414 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1721,8 +1721,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const { Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - if (!script.is_valid()) - ERR_FAIL_V(Variant()); + ERR_FAIL_COND_V(!script.is_valid(), Variant()); GD_MONO_SCOPE_THREAD_ATTACH; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index b926037e5a..e096d37a6f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -474,7 +474,7 @@ namespace Godot int source = 0; int target = 0; - while (instance[source] != 0 && text[target] != 0) + while (source < len && target < text.Length) { bool match; @@ -491,7 +491,7 @@ namespace Godot if (match) { source++; - if (instance[source] == 0) + if (source >= len) return true; } diff --git a/modules/mono/mono_gd/gd_mono_android.cpp b/modules/mono/mono_gd/gd_mono_android.cpp index 27f394fae0..761368878f 100644 --- a/modules/mono/mono_gd/gd_mono_android.cpp +++ b/modules/mono/mono_gd/gd_mono_android.cpp @@ -315,7 +315,7 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) { char *alias_utf8 = mono_string_to_utf8_checked(p_alias, &mono_error); if (!mono_error_ok(&mono_error)) { - ERR_PRINTS(String() + "Failed to convert MonoString* to UTF-8: '" + mono_error_get_message(&mono_error) + "'."); + ERR_PRINT(String() + "Failed to convert MonoString* to UTF-8: '" + mono_error_get_message(&mono_error) + "'."); mono_error_cleanup(&mono_error); return NULL; } diff --git a/modules/recast/navigation_mesh_generator.cpp b/modules/recast/navigation_mesh_generator.cpp index c67136b814..b6f5b38038 100644 --- a/modules/recast/navigation_mesh_generator.cpp +++ b/modules/recast/navigation_mesh_generator.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "navigation_mesh_generator.h" + #include "core/math/quick_hull.h" #include "core/os/thread.h" #include "editor/editor_settings.h" @@ -45,10 +46,10 @@ #include "scene/resources/shape.h" #include "scene/resources/sphere_shape.h" +#include "modules/modules_enabled.gen.h" #ifdef MODULE_CSG_ENABLED #include "modules/csg/csg_shape.h" #endif - #ifdef MODULE_GRIDMAP_ENABLED #include "modules/gridmap/grid_map.h" #endif diff --git a/modules/register_module_types.h b/modules/register_module_types.h index a8eb68b929..b410457201 100644 --- a/modules/register_module_types.h +++ b/modules/register_module_types.h @@ -31,9 +31,7 @@ #ifndef REGISTER_MODULE_TYPES_H #define REGISTER_MODULE_TYPES_H -// - void register_module_types(); void unregister_module_types(); -#endif +#endif // REGISTER_MODULE_TYPES_H diff --git a/modules/svg/SCsub b/modules/svg/SCsub index 9324c1634b..7961d1f33e 100644 --- a/modules/svg/SCsub +++ b/modules/svg/SCsub @@ -13,10 +13,6 @@ thirdparty_sources = [ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] env_svg.Prepend(CPPPATH=[thirdparty_dir]) -# FIXME: Needed in editor/editor_themes.cpp for now, but ideally there -# shouldn't be a dependency on modules/ and its own 3rd party deps. -env.Prepend(CPPPATH=[thirdparty_dir]) -env.Append(CPPDEFINES=["SVG_ENABLED"]) env_thirdparty = env_svg.Clone() env_thirdparty.disable_warnings() diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index 11ae2f81bf..7f91908a33 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -30,9 +30,8 @@ #include "image_loader_svg.h" -#include "core/os/os.h" -#include "core/print_string.h" -#include "core/ustring.h" +#include <nanosvg.h> +#include <nanosvgrast.h> void SVGRasterizer::rasterize(NSVGimage *p_image, float p_tx, float p_ty, float p_scale, unsigned char *p_dst, int p_w, int p_h, int p_stride) { nsvgRasterize(rasterizer, p_image, p_tx, p_ty, p_scale, p_dst, p_w, p_h, p_stride); diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h index 9e9366e91b..24cee82480 100644 --- a/modules/svg/image_loader_svg.h +++ b/modules/svg/image_loader_svg.h @@ -34,13 +34,14 @@ #include "core/io/image_loader.h" #include "core/ustring.h" -#include <nanosvg.h> -#include <nanosvgrast.h> - /** @author Daniel Ramirez <djrmuv@gmail.com> */ +// Forward declare and include thirdparty headers in .cpp. +struct NSVGrasterizer; +struct NSVGimage; + class SVGRasterizer { NSVGrasterizer *rasterizer; diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index cf1fc3f175..00c7e87568 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -363,8 +363,10 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { }; float VideoStreamPlaybackTheora::get_time() const { - - return time - AudioServer::get_singleton()->get_output_latency() - delay_compensation; //-((get_total())/(float)vi.rate); + // FIXME: AudioServer output latency was fixed in af9bb0e, previously it used to + // systematically return 0. Now that it gives a proper latency, it broke this + // code where the delay compensation likely never really worked. + return time - /* AudioServer::get_singleton()->get_output_latency() - */ delay_compensation; }; Ref<Texture> VideoStreamPlaybackTheora::get_texture() const { diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp index 41f9e67672..2763d30bb5 100644 --- a/modules/webm/video_stream_webm.cpp +++ b/modules/webm/video_stream_webm.cpp @@ -393,17 +393,22 @@ int VideoStreamPlaybackWebm::get_mix_rate() const { inline bool VideoStreamPlaybackWebm::has_enough_video_frames() const { if (video_frames_pos > 0) { - - const double audio_delay = AudioServer::get_singleton()->get_output_latency(); + // FIXME: AudioServer output latency was fixed in af9bb0e, previously it used to + // systematically return 0. Now that it gives a proper latency, it broke this + // code where the delay compensation likely never really worked. + //const double audio_delay = AudioServer::get_singleton()->get_output_latency(); const double video_time = video_frames[video_frames_pos - 1]->time; - return video_time >= time + audio_delay + delay_compensation; + return video_time >= time + /* audio_delay + */ delay_compensation; } return false; } bool VideoStreamPlaybackWebm::should_process(WebMFrame &video_frame) { - const double audio_delay = AudioServer::get_singleton()->get_output_latency(); - return video_frame.time >= time + audio_delay + delay_compensation; + // FIXME: AudioServer output latency was fixed in af9bb0e, previously it used to + // systematically return 0. Now that it gives a proper latency, it broke this + // code where the delay compensation likely never really worked. + //const double audio_delay = AudioServer::get_singleton()->get_output_latency(); + return video_frame.time >= time + /* audio_delay + */ delay_compensation; } void VideoStreamPlaybackWebm::delete_pointers() { diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 9b93d4f140..c1cb8bcb58 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -86,7 +86,7 @@ public: ERR_FAIL_COND_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", "Invalid method or HTTP version."); String filepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export"); - String basereq = "/tmp_js_export"; + const String basereq = "/tmp_js_export"; String ctype = ""; if (req[1] == basereq + ".html") { filepath += ".html"; @@ -97,8 +97,13 @@ public: } else if (req[1] == basereq + ".pck") { filepath += ".pck"; ctype = "application/octet-stream"; - } else if (req[1] == basereq + ".png") { - filepath += ".png"; + } else if (req[1] == basereq + ".png" || req[1] == "/favicon.png") { + // Also allow serving the generated favicon for a smoother loading experience. + if (req[1] == "/favicon.png") { + filepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("favicon.png"); + } else { + filepath += ".png"; + } ctype = "image/png"; } else if (req[1] == basereq + ".wasm") { filepath += ".wasm"; @@ -470,11 +475,10 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese } Ref<Image> splash; - String splash_path = GLOBAL_GET("application/boot_splash/image"); - splash_path = splash_path.strip_edges(); + const String splash_path = String(GLOBAL_GET("application/boot_splash/image")).strip_edges(); if (!splash_path.empty()) { splash.instance(); - Error err = splash->load(splash_path); + const Error err = splash->load(splash_path); if (err) { EditorNode::get_singleton()->show_warning(TTR("Could not read boot splash image file:") + "\n" + splash_path + "\n" + TTR("Using default boot splash image.")); splash.unref(); @@ -483,11 +487,32 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese if (splash.is_null()) { splash = Ref<Image>(memnew(Image(boot_splash_png))); } - String png_path = p_path.get_base_dir().plus_file(p_path.get_file().get_basename() + ".png"); - if (splash->save_png(png_path) != OK) { - EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + png_path); + const String splash_png_path = p_path.get_base_dir().plus_file(p_path.get_file().get_basename() + ".png"); + if (splash->save_png(splash_png_path) != OK) { + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + splash_png_path); return ERR_FILE_CANT_WRITE; } + + // Save a favicon that can be accessed without waiting for the project to finish loading. + // This way, the favicon can be displayed immediately when loading the page. + Ref<Image> favicon; + const String favicon_path = String(GLOBAL_GET("application/config/icon")).strip_edges(); + if (!favicon_path.empty()) { + favicon.instance(); + const Error err = favicon->load(favicon_path); + if (err) { + favicon.unref(); + } + } + + if (favicon.is_valid()) { + const String favicon_png_path = p_path.get_base_dir().plus_file("favicon.png"); + if (favicon->save_png(favicon_png_path) != OK) { + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + favicon_png_path); + return ERR_FILE_CANT_WRITE; + } + } + return OK; } @@ -536,9 +561,8 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese return OK; } - String basepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export"); - String path = basepath + ".html"; - Error err = export_project(p_preset, true, path, p_debug_flags); + const String basepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export"); + Error err = export_project(p_preset, true, basepath + ".html", p_debug_flags); if (err != OK) { // Export generates several files, clean them up on failure. DirAccess::remove_file_or_error(basepath + ".html"); @@ -546,13 +570,14 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese DirAccess::remove_file_or_error(basepath + ".pck"); DirAccess::remove_file_or_error(basepath + ".png"); DirAccess::remove_file_or_error(basepath + ".wasm"); + DirAccess::remove_file_or_error(EditorSettings::get_singleton()->get_cache_dir().plus_file("favicon.png")); return err; } - IP_Address bind_ip; - uint16_t bind_port = EDITOR_GET("export/web/http_port"); + const uint16_t bind_port = EDITOR_GET("export/web/http_port"); // Resolve host if needed. - String bind_host = EDITOR_GET("export/web/http_host"); + const String bind_host = EDITOR_GET("export/web/http_host"); + IP_Address bind_ip; if (bind_host.is_valid_ip_address()) { bind_ip = bind_host; } else { diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 87764d5750..34dce90b6b 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -980,7 +980,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, EMSCRIPTEN_RESULT result; #define EM_CHECK(ev) \ if (result != EMSCRIPTEN_RESULT_SUCCESS) \ - ERR_PRINT("Error while setting " #ev " callback: Code " + itos(result)) + ERR_PRINT("Error while setting " #ev " callback: Code " + itos(result)); #define SET_EM_CALLBACK(target, ev, cb) \ result = emscripten_set_##ev##_callback(target, NULL, true, &cb); \ EM_CHECK(ev) diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 500736bd3f..72c3f60d99 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -293,12 +293,7 @@ def configure_mingw(env): ## Compiler configuration - if (os.name == "nt"): - # Force splitting libmodules.a in multiple chunks to work around - # issues reaching the linker command line size limit, which also - # seem to induce huge slowdown for 'ar' (GH-30892). - env['split_libmodules'] = True - else: + if os.name != "nt": env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation if (env["bits"] == "default"): diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index f59e3461b1..acb1b0b5a0 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "cpu_particles_2d.h" - +#include "core/core_string_names.h" #include "scene/2d/canvas_item.h" #include "scene/2d/particles_2d.h" #include "scene/resources/particles_material.h" @@ -169,10 +169,20 @@ void CPUParticles2D::_update_mesh_texture() { vertices.push_back(-tex_size * 0.5 + Vector2(tex_size.x, tex_size.y)); vertices.push_back(-tex_size * 0.5 + Vector2(0, tex_size.y)); PoolVector<Vector2> uvs; - uvs.push_back(Vector2(0, 0)); - uvs.push_back(Vector2(1, 0)); - uvs.push_back(Vector2(1, 1)); - uvs.push_back(Vector2(0, 1)); + AtlasTexture *atlas_texure = Object::cast_to<AtlasTexture>(*texture); + if (atlas_texure && atlas_texure->get_atlas().is_valid()) { + Rect2 region_rect = atlas_texure->get_region(); + Size2 atlas_size = atlas_texure->get_atlas()->get_size(); + uvs.push_back(Vector2(region_rect.position.x / atlas_size.x, region_rect.position.y / atlas_size.y)); + uvs.push_back(Vector2((region_rect.position.x + region_rect.size.x) / atlas_size.x, region_rect.position.y / atlas_size.y)); + uvs.push_back(Vector2((region_rect.position.x + region_rect.size.x) / atlas_size.x, (region_rect.position.y + region_rect.size.y) / atlas_size.y)); + uvs.push_back(Vector2(region_rect.position.x / atlas_size.x, (region_rect.position.y + region_rect.size.y) / atlas_size.y)); + } else { + uvs.push_back(Vector2(0, 0)); + uvs.push_back(Vector2(1, 0)); + uvs.push_back(Vector2(1, 1)); + uvs.push_back(Vector2(0, 1)); + } PoolVector<Color> colors; colors.push_back(Color(1, 1, 1, 1)); colors.push_back(Color(1, 1, 1, 1)); @@ -198,12 +208,29 @@ void CPUParticles2D::_update_mesh_texture() { } void CPUParticles2D::set_texture(const Ref<Texture> &p_texture) { + if (p_texture == texture) + return; + + if (texture.is_valid()) + texture->disconnect(CoreStringNames::get_singleton()->changed, this, "_texture_changed"); texture = p_texture; + + if (texture.is_valid()) + texture->connect(CoreStringNames::get_singleton()->changed, this, "_texture_changed"); + update(); _update_mesh_texture(); } +void CPUParticles2D::_texture_changed() { + + if (texture.is_valid()) { + update(); + _update_mesh_texture(); + } +} + Ref<Texture> CPUParticles2D::get_texture() const { return texture; @@ -1315,6 +1342,7 @@ void CPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles2D::convert_from_particles); ClassDB::bind_method(D_METHOD("_update_render_thread"), &CPUParticles2D::_update_render_thread); + ClassDB::bind_method(D_METHOD("_texture_changed"), &CPUParticles2D::_texture_changed); ADD_GROUP("Emission Shape", "emission_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 085ec99ea0..d59b94bcbb 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -186,6 +186,8 @@ private: void _set_redraw(bool p_redraw); + void _texture_changed(); + protected: static void _bind_methods(); void _notification(int p_what); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index caeae90238..a1a221b5bb 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1562,6 +1562,24 @@ void PhysicalBone::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); } +void PhysicalBone::reset_physics_simulation_state() { + if (simulate_physics) { + _start_physics_simulation(); + } else { + _stop_physics_simulation(); + } +} + +void PhysicalBone::reset_to_rest_position() { + if (parent_skeleton) { + if (-1 == bone_id) { + set_global_transform(parent_skeleton->get_global_transform() * body_offset); + } else { + set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); + } + } +} + bool PhysicalBone::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { if (JointData::_set(p_name, p_value, j)) { return true; @@ -2167,7 +2185,7 @@ void PhysicalBone::_notification(int p_what) { parent_skeleton = find_skeleton_parent(get_parent()); update_bone_id(); reset_to_rest_position(); - _reset_physics_simulation_state(); + reset_physics_simulation_state(); if (!joint.is_valid() && joint_data) { _reload_joint(); } @@ -2238,8 +2256,6 @@ void PhysicalBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset); ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset); - ClassDB::bind_method(D_METHOD("is_static_body"), &PhysicalBone::is_static_body); - ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone::get_simulate_physics); ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics); @@ -2508,26 +2524,13 @@ const Transform &PhysicalBone::get_joint_offset() const { return joint_offset; } -void PhysicalBone::set_static_body(bool p_static) { - - static_body = p_static; - - set_as_toplevel(!static_body); - - _reset_physics_simulation_state(); -} - -bool PhysicalBone::is_static_body() { - return static_body; -} - void PhysicalBone::set_simulate_physics(bool p_simulate) { if (simulate_physics == p_simulate) { return; } simulate_physics = p_simulate; - _reset_physics_simulation_state(); + reset_physics_simulation_state(); } bool PhysicalBone::get_simulate_physics() { @@ -2535,7 +2538,7 @@ bool PhysicalBone::get_simulate_physics() { } bool PhysicalBone::is_simulating_physics() { - return _internal_simulate_physics && !_internal_static_body; + return _internal_simulate_physics; } void PhysicalBone::set_bone_name(const String &p_name) { @@ -2618,8 +2621,6 @@ PhysicalBone::PhysicalBone() : #endif joint_data(NULL), parent_skeleton(NULL), - static_body(false), - _internal_static_body(false), simulate_physics(false), _internal_simulate_physics(false), bone_id(-1), @@ -2629,8 +2630,7 @@ PhysicalBone::PhysicalBone() : friction(1), gravity_scale(1) { - set_static_body(static_body); - _reset_physics_simulation_state(); + reset_physics_simulation_state(); } PhysicalBone::~PhysicalBone() { @@ -2657,8 +2657,7 @@ void PhysicalBone::update_bone_id() { parent_skeleton->bind_physical_bone_to_bone(bone_id, this); _fix_joint_offset(); - _internal_static_body = !static_body; // Force staticness reset - _reset_staticness_state(); + reset_physics_simulation_state(); } } @@ -2680,49 +2679,6 @@ void PhysicalBone::update_offset() { #endif } -void PhysicalBone::reset_to_rest_position() { - if (parent_skeleton) { - if (-1 == bone_id) { - set_global_transform(parent_skeleton->get_global_transform() * body_offset); - } else { - set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); - } - } -} - -void PhysicalBone::_reset_physics_simulation_state() { - if (simulate_physics && !static_body) { - _start_physics_simulation(); - } else { - _stop_physics_simulation(); - } - - _reset_staticness_state(); -} - -void PhysicalBone::_reset_staticness_state() { - - if (parent_skeleton && -1 != bone_id) { - if (static_body && simulate_physics) { // With this check I'm sure the position of this body is updated only when it's necessary - - if (_internal_static_body) { - return; - } - - parent_skeleton->bind_child_node_to_bone(bone_id, this); - _internal_static_body = true; - } else { - - if (!_internal_static_body) { - return; - } - - parent_skeleton->unbind_child_node_from_bone(bone_id, this); - _internal_static_body = false; - } - } -} - void PhysicalBone::_start_physics_simulation() { if (_internal_simulate_physics || !parent_skeleton) { return; @@ -2732,17 +2688,27 @@ void PhysicalBone::_start_physics_simulation() { PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + set_as_toplevel(true); _internal_simulate_physics = true; } void PhysicalBone::_stop_physics_simulation() { - if (!_internal_simulate_physics || !parent_skeleton) { + if (!parent_skeleton) { return; } - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); - parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); - _internal_simulate_physics = false; + if (parent_skeleton->get_animate_physical_bones()) { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); + } else { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); + } + if (_internal_simulate_physics) { + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); + parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); + set_as_toplevel(false); + _internal_simulate_physics = false; + } } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 05bcbe22f0..6a1e803eaf 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -562,8 +562,6 @@ private: Skeleton *parent_skeleton; Transform body_offset; Transform body_offset_inverse; - bool static_body; - bool _internal_static_body; bool simulate_physics; bool _internal_simulate_physics; int bone_id; @@ -613,9 +611,6 @@ public: void set_body_offset(const Transform &p_offset); const Transform &get_body_offset() const; - void set_static_body(bool p_static); - bool is_static_body(); - void set_simulate_physics(bool p_simulate); bool get_simulate_physics(); bool is_simulating_physics(); @@ -641,16 +636,15 @@ public: void apply_central_impulse(const Vector3 &p_impulse); void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + void reset_physics_simulation_state(); + void reset_to_rest_position(); + PhysicalBone(); ~PhysicalBone(); private: void update_bone_id(); void update_offset(); - void reset_to_rest_position(); - - void _reset_physics_simulation_state(); - void _reset_staticness_state(); void _start_physics_simulation(); void _stop_physics_simulation(); diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 17e67c47d1..4089e0c23b 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -32,6 +32,7 @@ #include "core/message_queue.h" +#include "core/engine.h" #include "core/project_settings.h" #include "scene/3d/physics_body.h" #include "scene/resources/surface_tool.h" @@ -332,6 +333,27 @@ void Skeleton::_notification(int p_what) { dirty = false; } break; + +#ifndef _3D_DISABLED + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + // This is active only if the skeleton animates the physical bones + // and the state of the bone is not active. + if (animate_physical_bones) { + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + if (bones[i].physical_bone->is_simulating_physics() == false) { + bones[i].physical_bone->reset_to_rest_position(); + } + } + } + } + } break; + case NOTIFICATION_READY: { + if (Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(true); + } + } break; +#endif } } @@ -584,6 +606,27 @@ void Skeleton::localize_rests() { #ifndef _3D_DISABLED +void Skeleton::set_animate_physical_bones(bool p_animate) { + animate_physical_bones = p_animate; + + if (Engine::get_singleton()->is_editor_hint() == false) { + bool sim = false; + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + bones[i].physical_bone->reset_physics_simulation_state(); + if (bones[i].physical_bone->is_simulating_physics()) { + sim = true; + } + } + } + set_physics_process_internal(sim == false && p_animate); + } +} + +bool Skeleton::get_animate_physical_bones() const { + return animate_physical_bones; +} + void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(bones[p_bone].physical_bone); @@ -653,12 +696,14 @@ void _pb_stop_simulation(Node *p_node) { PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); if (pb) { pb->set_simulate_physics(false); - pb->set_static_body(false); } } void Skeleton::physical_bones_stop_simulation() { _pb_stop_simulation(this); + if (Engine::get_singleton()->is_editor_hint() == false && animate_physical_bones) { + set_physics_process_internal(true); + } } void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) { @@ -669,24 +714,17 @@ void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); if (pb) { - bool sim = false; for (int i = p_sim_bones.size() - 1; 0 <= i; --i) { if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) { - sim = true; + pb->set_simulate_physics(true); break; } } - - pb->set_simulate_physics(true); - if (sim) { - pb->set_static_body(false); - } else { - pb->set_static_body(true); - } } } void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { + set_physics_process_internal(false); Vector<int> sim_bones; if (p_bones.size() <= 0) { @@ -836,11 +874,15 @@ void Skeleton::_bind_methods() { #ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton::set_animate_physical_bones); + ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton::get_animate_physical_bones); + ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation); ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton::physical_bones_start_simulation_on, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton::physical_bones_add_collision_exception); ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton::physical_bones_remove_collision_exception); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); #endif // _3D_DISABLED BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); @@ -848,6 +890,7 @@ void Skeleton::_bind_methods() { Skeleton::Skeleton() { + animate_physical_bones = true; dirty = false; process_order_dirty = true; } diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 056f70e22b..9599510850 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -115,6 +115,7 @@ private: } }; + bool animate_physical_bones; Vector<Bone> bones; Vector<int> process_order; bool process_order_dirty; @@ -199,6 +200,9 @@ public: #ifndef _3D_DISABLED // Physical bone API + void set_animate_physical_bones(bool p_animate); + bool get_animate_physical_bones() const; + void bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone); void unbind_physical_bone_from_bone(int p_bone); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 6a6fe43876..c09b2414b2 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -261,6 +261,7 @@ void GraphEdit::add_child_notify(Node *p_child) { gn->connect("raise_request", this, "_graph_node_raised", varray(gn)); gn->connect("item_rect_changed", connections_layer, "update"); _graph_node_moved(gn); + gn->set_mouse_filter(MOUSE_FILTER_PASS); } } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 7afc3b0d00..7cc47d351e 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -240,15 +240,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { deselect(); text = text.substr(cursor_pos, text.length() - cursor_pos); - - Ref<Font> font = get_font("font"); - - cached_width = 0; - if (font != NULL) { - for (int i = 0; i < text.length(); i++) - cached_width += font->get_char_size(text[i]).width; - } - + update_cached_width(); set_cursor_position(0); _text_changed(); } @@ -1358,18 +1350,10 @@ void LineEdit::set_window_pos(int p_pos) { void LineEdit::append_at_cursor(String p_text) { if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) { - - Ref<Font> font = get_font("font"); - if (font != NULL) { - for (int i = 0; i < p_text.length(); i++) - cached_width += font->get_char_size(p_text[i]).width; - } else { - cached_width = 0; - } - String pre = text.substr(0, cursor_pos); String post = text.substr(cursor_pos, text.length() - cursor_pos); text = pre + p_text + post; + update_cached_width(); set_cursor_position(cursor_pos + p_text.length()); } else { emit_signal("text_change_rejected"); @@ -1499,6 +1483,7 @@ bool LineEdit::is_editable() const { void LineEdit::set_secret(bool p_secret) { pass = p_secret; + update_cached_width(); update(); } @@ -1514,6 +1499,7 @@ void LineEdit::set_secret_character(const String &p_string) { ERR_FAIL_COND_MSG(p_string.length() != 1, "Secret character must be exactly one character long (" + itos(p_string.length()) + " characters given)."); secret_character = p_string; + update_cached_width(); update(); } @@ -1685,6 +1671,17 @@ void LineEdit::_emit_text_change() { text_changed_dirty = false; } +void LineEdit::update_cached_width() { + Ref<Font> font = get_font("font"); + cached_width = 0; + if (font != NULL) { + String text = get_text(); + for (int i = 0; i < text.length(); i++) { + cached_width += font->get_char_size(pass ? secret_character[0] : text[i]).width; + } + } +} + void LineEdit::update_placeholder_width() { if ((max_length <= 0) || (placeholder_translated.length() <= max_length)) { Ref<Font> font = get_font("font"); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index cf597d11b6..037238d682 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -132,6 +132,7 @@ private: void _emit_text_change(); bool expand_to_text_length; + void update_cached_width(); void update_placeholder_width(); bool caret_blink_enabled; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 6c2928c65c..af5d0e2f45 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -33,8 +33,13 @@ #include "core/math/math_defs.h" #include "core/os/keyboard.h" #include "core/os/os.h" -#include "modules/regex/regex.h" #include "scene/scene_string_names.h" + +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_REGEX_ENABLED +#include "modules/regex/regex.h" +#endif + #ifdef TOOLS_ENABLED #include "editor/editor_scale.h" #endif @@ -2864,6 +2869,7 @@ Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressi Vector<String> values = parts[1].split(",", false); +#ifdef MODULE_REGEX_ENABLED RegEx color = RegEx(); color.compile("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"); RegEx nodepath = RegEx(); @@ -2897,6 +2903,7 @@ Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressi a.append(values[j]); } } +#endif if (values.size() > 1) { d[key] = a; diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index bb5260b15e..079907db07 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -266,7 +266,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const { if (dragging) - return (vertical ? CURSOR_VSIZE : CURSOR_HSIZE); + return (vertical ? CURSOR_VSPLIT : CURSOR_HSPLIT); if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) { @@ -275,11 +275,11 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const if (vertical) { if (p_pos.y > middle_sep && p_pos.y < middle_sep + sep) - return CURSOR_VSIZE; + return CURSOR_VSPLIT; } else { if (p_pos.x > middle_sep && p_pos.x < middle_sep + sep) - return CURSOR_HSIZE; + return CURSOR_HSPLIT; } } diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index cc76df62e5..00c56e5eb2 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -647,8 +647,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("title_button_color", "Tree", control_font_color); theme->set_color("font_color", "Tree", control_font_color_low); theme->set_color("font_color_selected", "Tree", control_font_color_pressed); - theme->set_color("selection_color", "Tree", Color(0.1, 0.1, 1, 0.8)); - theme->set_color("cursor_color", "Tree", Color(0, 0, 0)); theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1)); theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2)); theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27)); diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index d19d82d252..451029e93b 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -28,8 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef FREETYPE_ENABLED +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_FREETYPE_ENABLED + #include "dynamic_font.h" + #include "core/os/file_access.h" #include "core/os/os.h" diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 2dafd3ce4f..9170767512 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -31,7 +31,9 @@ #ifndef DYNAMIC_FONT_H #define DYNAMIC_FONT_H -#ifdef FREETYPE_ENABLED +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_FREETYPE_ENABLED + #include "core/io/resource_loader.h" #include "core/os/mutex.h" #include "core/os/thread_safe.h" diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index daf770e92a..8f0e0058ea 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -3039,6 +3039,11 @@ String VisualShaderNodeScalarUniform::get_output_port_name(int p_port) const { } String VisualShaderNodeScalarUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + if (hint == HINT_RANGE) { + return "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ");\n"; + } else if (hint == HINT_RANGE_STEP) { + return "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ", " + rtos(hint_range_step) + ");\n"; + } return "uniform float " + get_uniform_name() + ";\n"; } @@ -3046,7 +3051,83 @@ String VisualShaderNodeScalarUniform::generate_code(Shader::Mode p_mode, VisualS return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; } +void VisualShaderNodeScalarUniform::set_hint(Hint p_hint) { + hint = p_hint; + emit_changed(); +} + +VisualShaderNodeScalarUniform::Hint VisualShaderNodeScalarUniform::get_hint() const { + return hint; +} + +void VisualShaderNodeScalarUniform::set_min(float p_value) { + hint_range_min = p_value; + emit_changed(); +} + +float VisualShaderNodeScalarUniform::get_min() const { + return hint_range_min; +} + +void VisualShaderNodeScalarUniform::set_max(float p_value) { + hint_range_max = p_value; + emit_changed(); +} + +float VisualShaderNodeScalarUniform::get_max() const { + return hint_range_max; +} + +void VisualShaderNodeScalarUniform::set_step(float p_value) { + hint_range_step = p_value; + emit_changed(); +} + +float VisualShaderNodeScalarUniform::get_step() const { + return hint_range_step; +} + +void VisualShaderNodeScalarUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeScalarUniform::set_hint); + ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeScalarUniform::get_hint); + + ClassDB::bind_method(D_METHOD("set_min", "value"), &VisualShaderNodeScalarUniform::set_min); + ClassDB::bind_method(D_METHOD("get_min"), &VisualShaderNodeScalarUniform::get_min); + + ClassDB::bind_method(D_METHOD("set_max", "value"), &VisualShaderNodeScalarUniform::set_max); + ClassDB::bind_method(D_METHOD("get_max"), &VisualShaderNodeScalarUniform::get_max); + + ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeScalarUniform::set_step); + ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeScalarUniform::get_step); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "min"), "set_min", "get_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max"), "set_max", "get_max"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "step"), "set_step", "get_step"); + + BIND_ENUM_CONSTANT(HINT_NONE); + BIND_ENUM_CONSTANT(HINT_RANGE); + BIND_ENUM_CONSTANT(HINT_RANGE_STEP); +} + +Vector<StringName> VisualShaderNodeScalarUniform::get_editable_properties() const { + Vector<StringName> props; + props.push_back("hint"); + if (hint == HINT_RANGE || hint == HINT_RANGE_STEP) { + props.push_back("min"); + props.push_back("max"); + } + if (hint == HINT_RANGE_STEP) { + props.push_back("step"); + } + return props; +} + VisualShaderNodeScalarUniform::VisualShaderNodeScalarUniform() { + hint = HINT_NONE; + hint_range_min = 0.0; + hint_range_max = 1.0; + hint_range_step = 0.1; } ////////////// Boolean Uniform diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index cca37273d9..3d57fd0efc 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -1301,6 +1301,22 @@ class VisualShaderNodeScalarUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeScalarUniform, VisualShaderNodeUniform); public: + enum Hint { + HINT_NONE, + HINT_RANGE, + HINT_RANGE_STEP, + }; + +private: + Hint hint; + float hint_range_min; + float hint_range_max; + float hint_range_step; + +protected: + static void _bind_methods(); + +public: virtual String get_caption() const; virtual int get_input_port_count() const; @@ -1314,9 +1330,25 @@ public: virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + void set_hint(Hint p_hint); + Hint get_hint() const; + + void set_min(float p_value); + float get_min() const; + + void set_max(float p_value); + float get_max() const; + + void set_step(float p_value); + float get_step() const; + + virtual Vector<StringName> get_editable_properties() const; + VisualShaderNodeScalarUniform(); }; +VARIANT_ENUM_CAST(VisualShaderNodeScalarUniform::Hint) + /////////////////////////////////////// class VisualShaderNodeBooleanUniform : public VisualShaderNodeUniform { diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 1c84e97196..2a5a5040b6 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "audio_server.h" + #include "core/io/resource_loader.h" #include "core/os/file_access.h" #include "core/os/os.h" @@ -36,14 +37,11 @@ #include "scene/resources/audio_stream_sample.h" #include "servers/audio/audio_driver_dummy.h" #include "servers/audio/effects/audio_effect_compressor.h" -#ifdef TOOLS_ENABLED +#ifdef TOOLS_ENABLED #define MARK_EDITED set_edited(true); - #else - #define MARK_EDITED - #endif AudioDriver *AudioDriver::singleton = NULL; @@ -1405,8 +1403,6 @@ AudioServer::AudioServer() { mix_frames = 0; channel_count = 0; to_mix = 0; - output_latency = 0; - output_latency_ticks = 0; #ifdef DEBUG_ENABLED prof_time = 0; #endif diff --git a/servers/audio_server.h b/servers/audio_server.h index 815200c811..eff66d4008 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -240,9 +240,6 @@ private: Mutex *audio_data_lock; - float output_latency; - uint64_t output_latency_ticks; - void init_channels_and_buffers(); void _mix_step(); diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 14d2f6d086..98ccfcfc68 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -1969,14 +1969,14 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, @@ -2006,10 +2006,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, @@ -2986,14 +2986,32 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons bool is_const = false; int array_size = 0; - if (!_find_identifier(p_block, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size)) { - _set_error("Unknown identifier in expression: " + String(identifier)); - return NULL; - } + if (p_block && p_block->block_tag != SubClassTag::TAG_GLOBAL) { + int idx = 0; + bool found = false; - if (ident_type == IDENTIFIER_FUNCTION) { - _set_error("Can't use function as identifier: " + String(identifier)); - return NULL; + while (builtin_func_defs[idx].name) { + if (builtin_func_defs[idx].tag == p_block->block_tag && builtin_func_defs[idx].name == identifier) { + found = true; + break; + } + idx++; + } + if (!found) { + _set_error("Unknown identifier in expression: " + String(identifier)); + return NULL; + } + } else { + + if (!_find_identifier(p_block, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size)) { + _set_error("Unknown identifier in expression: " + String(identifier)); + return NULL; + } + + if (ident_type == IDENTIFIER_FUNCTION) { + _set_error("Can't use function as identifier: " + String(identifier)); + return NULL; + } } Node *index_expression = NULL; @@ -3009,7 +3027,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (tk.type == TK_PERIOD) { completion_class = TAG_ARRAY; + p_block->block_tag = SubClassTag::TAG_ARRAY; call_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + p_block->block_tag = SubClassTag::TAG_GLOBAL; if (!call_expression) return NULL; data_type = call_expression->get_datatype(); @@ -3281,9 +3301,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Index out of range (0-1)"); return NULL; } - } else { - _set_error("Only integer constants are allowed as index at the moment"); - return NULL; } switch (expr->get_datatype()) { @@ -3307,9 +3324,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Index out of range (0-2)"); return NULL; } - } else { - _set_error("Only integer constants are allowed as index at the moment"); - return NULL; } switch (expr->get_datatype()) { @@ -3332,9 +3346,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Index out of range (0-3)"); return NULL; } - } else { - _set_error("Only integer constants are allowed as index at the moment"); - return NULL; } switch (expr->get_datatype()) { @@ -4700,10 +4711,8 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) { case TYPE_UVEC4: case TYPE_ISAMPLER2D: case TYPE_USAMPLER2D: - case TYPE_SAMPLER3D: case TYPE_ISAMPLER3D: case TYPE_USAMPLER3D: - case TYPE_SAMPLER2DARRAY: case TYPE_USAMPLER2DARRAY: case TYPE_ISAMPLER2DARRAY: invalid_type = true; diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index e5c3c6852c..f7b02ab70b 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -279,6 +279,11 @@ public: ARGUMENT_QUALIFIER_INOUT, }; + enum SubClassTag { + TAG_GLOBAL, + TAG_ARRAY, + }; + struct Node { Node *next; @@ -431,6 +436,7 @@ public: }; int block_type; + SubClassTag block_tag; struct Variable { DataType type; @@ -449,6 +455,7 @@ public: parent_function(NULL), parent_block(NULL), block_type(BLOCK_TYPE_STANDART), + block_tag(SubClassTag::TAG_GLOBAL), single_statement(false) {} }; @@ -713,11 +720,6 @@ private: bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL); bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL); - enum SubClassTag { - TAG_GLOBAL, - TAG_ARRAY, - }; - struct BuiltinFuncDef { enum { MAX_ARGS = 5 }; const char *name; diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index e07e188ec6..c90e061eb7 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -168,7 +168,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor VisualServerRaster::redraw_request(); } - if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) { + if ((!ci->commands.empty() && p_clip_rect.intersects_touch(global_rect)) || ci->vp_render || ci->copy_back_buffer) { //something to draw? ci->final_transform = xform; ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a); |