diff options
389 files changed, 10589 insertions, 6046 deletions
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index d75680b4b5..04b2452a9a 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -18,16 +18,16 @@ jobs: fail-fast: false matrix: include: - - name: Editor w/ Mono (target=release_debug, tools=yes, tests=yes) - cache-name: linux-editor-mono - target: release_debug - tools: true - tests: false # Disabled due freeze caused by mix Mono build and CI - sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no - doc-test: true - bin: "./bin/godot.linuxbsd.opt.tools.64.mono" - build-mono: true - artifact: true +# - name: Editor w/ Mono (target=release_debug, tools=yes, tests=yes) +# cache-name: linux-editor-mono +# target: release_debug +# tools: true +# tests: false # Disabled due freeze caused by mix Mono build and CI +# sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no +# doc-test: true +# bin: "./bin/godot.linuxbsd.opt.tools.64.mono" +# build-mono: true +# artifact: true - name: Editor with doubles and sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes) cache-name: linux-editor-double-sanitizers @@ -36,22 +36,20 @@ jobs: tests: true sconsflags: float=64 use_asan=yes use_ubsan=yes proj-test: true - # Can be turned off for PRs that intentionally break compat with godot-cpp, - # until both the upstream PR and the matching godot-cpp changes are merged. - godot-cpp-test: false + godot-cpp-test: true bin: "./bin/godot.linuxbsd.double.tools.64.san" build-mono: false # Skip 2GiB artifact speeding up action. artifact: false - - name: Template w/ Mono (target=release, tools=no) - cache-name: linux-template-mono - target: release - tools: false - tests: false - sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no debug_symbols=no - build-mono: false - artifact: true +# - name: Template w/ Mono (target=release, tools=no) +# cache-name: linux-template-mono +# target: release +# tools: false +# tests: false +# sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no debug_symbols=no +# build-mono: false +# artifact: true - name: Minimal Template (target=release, tools=no, everything disabled) cache-name: linux-template-minimal @@ -146,7 +144,7 @@ jobs: - name: Open and close editor if: ${{ matrix.proj-test }} run: | - VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy -e -q --path test_project 2>&1 | tee sanitizers_log.txt || true + VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --editor --quit --path test_project 2>&1 | tee sanitizers_log.txt || true misc/scripts/check_ci_log.py sanitizers_log.txt # Run test project diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 83f58311f1..93c1abe7b5 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -145,7 +145,7 @@ String ProjectSettings::localize_path(const String &p_path) const { return p_path.simplify_path(); } - DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String path = p_path.replace("\\", "/").simplify_path(); @@ -153,8 +153,6 @@ String ProjectSettings::localize_path(const String &p_path) const { String cwd = dir->get_current_dir(); cwd = cwd.replace("\\", "/"); - memdelete(dir); - // Ensure that we end with a '/'. // This is important to ensure that we do not wrongly localize the resource path // in an absolute path that just happens to contain this string but points to a @@ -173,8 +171,6 @@ String ProjectSettings::localize_path(const String &p_path) const { return cwd.replace_first(res_path, "res://"); } else { - memdelete(dir); - int sep = path.rfind("/"); if (sep == -1) { return "res://" + path; @@ -541,7 +537,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b // Nothing was found, try to find a project file in provided path (`p_path`) // or, if requested (`p_upwards`) in parent directories. - DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); ERR_FAIL_COND_V_MSG(!d, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'."); d->change_dir(p_path); @@ -573,8 +569,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b } } - memdelete(d); - if (!found) { return err; } @@ -1199,6 +1193,8 @@ ProjectSettings::ProjectSettings() { singleton = this; GLOBAL_DEF_BASIC("application/config/name", ""); + GLOBAL_DEF_BASIC("application/config/name_localized", Dictionary()); + custom_prop_info["application/config/name_localized"] = PropertyInfo(Variant::DICTIONARY, "application/config/name_localized", PROPERTY_HINT_LOCALIZABLE_STRING); GLOBAL_DEF_BASIC("application/config/description", ""); custom_prop_info["application/config/description"] = PropertyInfo(Variant::STRING, "application/config/description", PROPERTY_HINT_MULTILINE_TEXT); GLOBAL_DEF_BASIC("application/run/main_scene", ""); diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 590d1c12c6..2d0eaadbdf 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1569,10 +1569,8 @@ String Directory::get_current_dir() { Error Directory::make_dir(String p_dir) { ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly."); if (!p_dir.is_relative_path()) { - DirAccess *d = DirAccess::create_for_path(p_dir); - Error err = d->make_dir(p_dir); - memdelete(d); - return err; + DirAccessRef da = DirAccess::create_for_path(p_dir); + return da->make_dir(p_dir); } return d->make_dir(p_dir); } @@ -1580,10 +1578,8 @@ Error Directory::make_dir(String p_dir) { Error Directory::make_dir_recursive(String p_dir) { ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly."); if (!p_dir.is_relative_path()) { - DirAccess *d = DirAccess::create_for_path(p_dir); - Error err = d->make_dir_recursive(p_dir); - memdelete(d); - return err; + DirAccessRef da = DirAccess::create_for_path(p_dir); + return da->make_dir_recursive(p_dir); } return d->make_dir_recursive(p_dir); } @@ -1593,19 +1589,14 @@ bool Directory::file_exists(String p_file) { if (!p_file.is_relative_path()) { return FileAccess::exists(p_file); } - return d->file_exists(p_file); } bool Directory::dir_exists(String p_dir) { ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly."); if (!p_dir.is_relative_path()) { - DirAccess *d = DirAccess::create_for_path(p_dir); - bool exists = d->dir_exists(p_dir); - memdelete(d); - return exists; + return DirAccess::exists(p_dir); } - return d->dir_exists(p_dir); } @@ -1624,11 +1615,9 @@ Error Directory::rename(String p_from, String p_to) { ERR_FAIL_COND_V_MSG(p_from.is_empty() || p_from == "." || p_from == "..", ERR_INVALID_PARAMETER, "Invalid path to rename."); if (!p_from.is_relative_path()) { - DirAccess *d = DirAccess::create_for_path(p_from); - ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist."); - Error err = d->rename(p_from, p_to); - memdelete(d); - return err; + DirAccessRef da = DirAccess::create_for_path(p_from); + ERR_FAIL_COND_V_MSG(!da->file_exists(p_from) && !da->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist."); + return da->rename(p_from, p_to); } ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist."); @@ -1638,10 +1627,8 @@ Error Directory::rename(String p_from, String p_to) { Error Directory::remove(String p_name) { ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use."); if (!p_name.is_relative_path()) { - DirAccess *d = DirAccess::create_for_path(p_name); - Error err = d->remove(p_name); - memdelete(d); - return err; + DirAccessRef da = DirAccess::create_for_path(p_name); + return da->remove(p_name); } return d->remove(p_name); @@ -1664,7 +1651,6 @@ void Directory::_bind_methods() { ClassDB::bind_method(D_METHOD("make_dir_recursive", "path"), &Directory::make_dir_recursive); ClassDB::bind_method(D_METHOD("file_exists", "path"), &Directory::file_exists); ClassDB::bind_method(D_METHOD("dir_exists", "path"), &Directory::dir_exists); - //ClassDB::bind_method(D_METHOD("get_modified_time","file"),&Directory::get_modified_time); ClassDB::bind_method(D_METHOD("get_space_left"), &Directory::get_space_left); ClassDB::bind_method(D_METHOD("copy", "from", "to"), &Directory::copy); ClassDB::bind_method(D_METHOD("rename", "from", "to"), &Directory::rename); diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 89926ee81b..98b720ab65 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -591,6 +591,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE); diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index 3687e4f7e5..31af28b783 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -841,27 +841,16 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { { Array native_structures; - // AudioStream structures - { - Dictionary d; - d["name"] = "AudioFrame"; - d["format"] = "float left,float right"; + List<StringName> native_structs; + ClassDB::get_native_struct_list(&native_structs); + native_structs.sort_custom<StringName::AlphCompare>(); - native_structures.push_back(d); - } + for (const StringName &E : native_structs) { + String code = ClassDB::get_native_struct_code(E); - // TextServer structures - { - Dictionary d; - d["name"] = "Glyph"; - d["format"] = "int start,int end,uint8_t count,uint8_t repeat,uint16_t flags,float x_off,float y_off,float advance,RID font_rid,int font_size,int32_t index"; - - native_structures.push_back(d); - } - { Dictionary d; - d["name"] = "CaretInfo"; - d["format"] = "Rect2 leading_caret,Rect2 trailing_caret,TextServer::Direction leading_direction,TextServer::Direction trailing_direction"; + d["name"] = String(E); + d["format"] = code; native_structures.push_back(d); } diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index d9ec42dc9d..d0461611ec 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -60,6 +60,10 @@ static void gdnative_print_script_error(const char *p_description, const char *p _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT); } +uint64_t gdnative_get_native_struct_size(const char *p_name) { + return ClassDB::get_native_struct_size(p_name); +} + // Variant functions static void gdnative_variant_new_copy(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src) { @@ -902,6 +906,8 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) { gdni.print_warning = gdnative_print_warning; gdni.print_script_error = gdnative_print_script_error; + gdni.get_native_struct_size = gdnative_get_native_struct_size; + /* GODOT VARIANT */ // variant general diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 76e87eaf23..cc2957ec56 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -306,6 +306,8 @@ typedef struct { void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); + uint64_t (*get_native_struct_size)(const char *p_name); + /* GODOT VARIANT */ /* variant general */ diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp index 86d8dea3d9..73efdeb38e 100644 --- a/core/io/dir_access.cpp +++ b/core/io/dir_access.cpp @@ -250,6 +250,14 @@ DirAccess *DirAccess::create(AccessType p_access) { DirAccess *da = create_func[p_access] ? create_func[p_access]() : nullptr; if (da) { da->_access_type = p_access; + + // for ACCESS_RESOURCES and ACCESS_FILESYSTEM, current_dir already defaults to where game was started + // in case current directory is force changed elsewhere for ACCESS_RESOURCES + if (p_access == ACCESS_RESOURCES) { + da->change_dir("res://"); + } else if (p_access == ACCESS_USERDATA) { + da->change_dir("user://"); + } } return da; @@ -414,8 +422,6 @@ Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_ } bool DirAccess::exists(String p_dir) { - DirAccess *da = DirAccess::create_for_path(p_dir); - bool valid = da->change_dir(p_dir) == OK; - memdelete(da); - return valid; + DirAccessRef da = DirAccess::create_for_path(p_dir); + return da->change_dir(p_dir) == OK; } diff --git a/core/io/dir_access.h b/core/io/dir_access.h index 8154f5366c..d63453e947 100644 --- a/core/io/dir_access.h +++ b/core/io/dir_access.h @@ -134,7 +134,7 @@ struct DirAccessRef { operator bool() const { return f != nullptr; } - DirAccess *f; + DirAccess *f = nullptr; DirAccessRef(DirAccess *fa) { f = fa; } ~DirAccessRef() { diff --git a/core/io/image.cpp b/core/io/image.cpp index 577fc59807..766c84bdbe 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -1465,8 +1465,8 @@ template <class Component, int CC, bool renormalize, void (*renormalize_func)(Component *)> static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint32_t p_width, uint32_t p_height) { //fast power of 2 mipmap generation - uint32_t dst_w = MAX(p_width >> 1, 1); - uint32_t dst_h = MAX(p_height >> 1, 1); + uint32_t dst_w = MAX(p_width >> 1, 1u); + uint32_t dst_h = MAX(p_height >> 1, 1u); int right_step = (p_width == 1) ? 0 : CC; int down_step = (p_height == 1) ? 0 : (p_width * CC); diff --git a/core/io/logger.cpp b/core/io/logger.cpp index cb6369ae3d..2b6f230434 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -128,7 +128,7 @@ void RotatedFileLogger::clear_old_backups() { String basename = base_path.get_file().get_basename(); String extension = base_path.get_extension(); - DirAccess *da = DirAccess::open(base_path.get_base_dir()); + DirAccessRef da = DirAccess::open(base_path.get_base_dir()); if (!da) { return; } @@ -152,8 +152,6 @@ void RotatedFileLogger::clear_old_backups() { da->remove(E->get()); } } - - memdelete(da); } void RotatedFileLogger::rotate_file() { @@ -167,18 +165,16 @@ void RotatedFileLogger::rotate_file() { backup_name += "." + base_path.get_extension(); } - DirAccess *da = DirAccess::open(base_path.get_base_dir()); + DirAccessRef da = DirAccess::open(base_path.get_base_dir()); if (da) { da->copy(base_path, backup_name); - memdelete(da); } clear_old_backups(); } } else { - DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_USERDATA); if (da) { da->make_dir_recursive(base_path.get_base_dir()); - memdelete(da); } } diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index ee59a916f1..b65993e3dd 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1032,7 +1032,6 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi String path = !p_original_path.is_empty() ? p_original_path : p_path; loader.local_path = ProjectSettings::get_singleton()->localize_path(path); loader.res_path = loader.local_path; - //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) ); loader.open(f); err = loader.load(); @@ -1086,17 +1085,14 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str ResourceLoaderBinary loader; loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); loader.res_path = loader.local_path; - //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) ); loader.get_dependencies(f, p_dependencies, p_add_types); } Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { - //Error error=OK; - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_path + "'."); - FileAccess *fw = nullptr; //=FileAccess::open(p_path+".depren"); + FileAccess *fw = nullptr; String local_path = p_path.get_base_dir(); @@ -1158,10 +1154,12 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons if (ver_format < FORMAT_VERSION_CAN_RENAME_DEPS) { memdelete(f); memdelete(fw); - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - da->remove(p_path + ".depren"); - memdelete(da); - //use the old approach + { + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + da->remove(p_path + ".depren"); + } + + // Use the old approach. WARN_PRINT("This file is old, so it can't refactor dependencies, opening and resaving '" + p_path + "'."); @@ -1174,7 +1172,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); loader.res_path = loader.local_path; loader.remaps = p_map; - //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) ); loader.open(f); err = loader.load(); @@ -1304,10 +1301,9 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons return ERR_CANT_CREATE; } - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); da->remove(p_path); da->rename(p_path + ".depren", p_path); - memdelete(da); return OK; } @@ -1320,7 +1316,6 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const ResourceLoaderBinary loader; loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); loader.res_path = loader.local_path; - //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) ); String r = loader.recognize(f); return ClassDB::get_compatibility_remapped_class(r); } @@ -1339,7 +1334,6 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat ResourceLoaderBinary loader; loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); loader.res_path = loader.local_path; - //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) ); loader.open(f, true); if (loader.error != OK) { return ResourceUID::INVALID_ID; //could not read diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 08e12dfcaa..e09c6cb97c 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -1606,7 +1606,7 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con if (Engine::get_singleton()->has_singleton(p_class)) { c = Engine::get_singleton()->get_singleton_object(p_class); cleanup_c = false; - } else if (ClassDB::can_instantiate(p_class)) { + } else if (ClassDB::can_instantiate(p_class) && !ClassDB::is_virtual(p_class)) { c = ClassDB::instantiate(p_class); cleanup_c = true; } @@ -1694,6 +1694,30 @@ void ClassDB::unregister_extension_class(const StringName &p_class) { classes.erase(p_class); } +Map<StringName, ClassDB::NativeStruct> ClassDB::native_structs; +void ClassDB::register_native_struct(const StringName &p_name, const String &p_code, uint64_t p_current_size) { + NativeStruct ns; + ns.ccode = p_code; + ns.struct_size = p_current_size; + native_structs[p_name] = ns; +} + +void ClassDB::get_native_struct_list(List<StringName> *r_names) { + for (const KeyValue<StringName, NativeStruct> &E : native_structs) { + r_names->push_back(E.key); + } +} + +String ClassDB::get_native_struct_code(const StringName &p_name) { + ERR_FAIL_COND_V(!native_structs.has(p_name), String()); + return native_structs[p_name].ccode; +} + +uint64_t ClassDB::get_native_struct_size(const StringName &p_name) { + ERR_FAIL_COND_V(!native_structs.has(p_name), 0); + return native_structs[p_name].struct_size; +} + RWLock ClassDB::lock; void ClassDB::cleanup_defaults() { @@ -1717,6 +1741,7 @@ void ClassDB::cleanup() { classes.clear(); resource_base_extensions.clear(); compat_classes.clear(); + native_structs.clear(); } // diff --git a/core/object/class_db.h b/core/object/class_db.h index 580ae3582f..32e4bf7644 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -144,6 +144,13 @@ public: static HashMap<StringName, HashMap<StringName, Variant>> default_values; static Set<StringName> default_values_cached; + // Native structs, used by binder + struct NativeStruct { + String ccode; // C code to create the native struct, fields separated by ; Arrays accepted (even containing other structs), also function pointers. All types must be Godot types. + uint64_t struct_size; // local size of struct, for comparison + }; + static Map<StringName, NativeStruct> native_structs; + private: // Non-locking variants of get_parent_class and is_parent_class. static StringName _get_parent_class(const StringName &p_class); @@ -390,6 +397,11 @@ public: static APIType get_current_api(); static void cleanup_defaults(); static void cleanup(); + + static void register_native_struct(const StringName &p_name, const String &p_code, uint64_t p_current_size); + static void get_native_struct_list(List<StringName> *r_names); + static String get_native_struct_code(const StringName &p_name); + static uint64_t get_native_struct_size(const StringName &p_name); // Used for asserting }; #ifdef DEBUG_METHODS_ENABLED @@ -448,6 +460,8 @@ _FORCE_INLINE_ Vector<Error> errarray(P... p_args) { ::ClassDB::register_abstract_class<m_class>(); \ } +#define GDREGISTER_NATIVE_STRUCT(m_class, m_code) ClassDB::register_native_struct(#m_class, m_code, sizeof(m_class)) + #include "core/disabled_classes.gen.h" #endif // CLASS_DB_H diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index 2e909b8042..64ee5940b0 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -28,7 +28,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\ }\\ \\ if (required) {\\ - WARN_PRINT_ONCE("Required virtual method: "+get_class()+"::" + #m_name + " must be overriden before calling.");\\ + ERR_PRINT_ONCE("Required virtual method: "+get_class()+"::" + #m_name + " must be overriden before calling.");\\ + $RVOID\\ }\\ \\ return false;\\ @@ -66,10 +67,12 @@ def generate_version(argcount, const=False, returns=False): if returns: sproto += "R" s = s.replace("$RET", "m_ret, ") + s = s.replace("$RVOID", "(void)r_ret;") # If required, may lead to uninitialized errors s = s.replace("$CALLPTRRETDEF", "PtrToArg<m_ret>::EncodeT ret;") method_info += "\tmethod_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n" else: s = s.replace("$RET", "") + s = s.replace("$RVOID", "") s = s.replace("$CALLPTRRETDEF", "") if const: diff --git a/core/object/object.h b/core/object/object.h index 3aa7e3f9f2..6b4f1c81e6 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -88,6 +88,7 @@ enum PropertyHint { PROPERTY_HINT_ARRAY_TYPE, PROPERTY_HINT_INT_IS_POINTER, PROPERTY_HINT_LOCALE_ID, + PROPERTY_HINT_LOCALIZABLE_STRING, PROPERTY_HINT_MAX, // When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit }; diff --git a/core/os/os.cpp b/core/os/os.cpp index 9837b6e0aa..2e5db145a4 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -328,17 +328,13 @@ void OS::yield() { void OS::ensure_user_data_dir() { String dd = get_user_data_dir(); - DirAccess *da = DirAccess::open(dd); - if (da) { - memdelete(da); + if (DirAccess::exists(dd)) { return; } - da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Error err = da->make_dir_recursive(dd); ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + "."); - - memdelete(da); } String OS::get_model_name() const { diff --git a/core/os/thread.cpp b/core/os/thread.cpp index f80e8f4bb3..c8072b7280 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -28,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "platform_config.h" #ifndef PLATFORM_THREAD_OVERRIDE // See details in thread.h #include "thread.h" diff --git a/core/os/thread.h b/core/os/thread.h index f4e46059ad..3382dd81f9 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -28,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "platform_config.h" // Define PLATFORM_THREAD_OVERRIDE in your platform's `platform_config.h` // to use a custom Thread implementation defined in `platform/[your_platform]/platform_thread.h` // Overriding the platform implementation is required in some proprietary platforms diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 2aa47c6c96..d05280f6a5 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -261,6 +261,8 @@ void register_core_types() { _classdb = memnew(core_bind::special::ClassDB); _marshalls = memnew(core_bind::Marshalls); _engine_debugger = memnew(core_bind::EngineDebugger); + + GDREGISTER_NATIVE_STRUCT(AudioFrame, "float left;float right"); } void register_core_settings() { diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index 11674629fc..2e941b8037 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -73,11 +73,23 @@ void StringName::cleanup() { d = d->next; } } - print_line("\nStringName Reference Ranking:\n"); + + print_line("\nStringName reference ranking (from most to least referenced):\n"); + data.sort_custom<DebugSortReferences>(); - for (int i = 0; i < MIN(100, data.size()); i++) { + int unreferenced_stringnames = 0; + int rarely_referenced_stringnames = 0; + for (int i = 0; i < data.size(); i++) { print_line(itos(i + 1) + ": " + data[i]->get_name() + " - " + itos(data[i]->debug_references)); + if (data[i]->debug_references == 0) { + unreferenced_stringnames += 1; + } else if (data[i]->debug_references < 5) { + rarely_referenced_stringnames += 1; + } } + + print_line(vformat("\nOut of %d StringNames, %d StringNames were never referenced during this run (0 times) (%.2f%%).", data.size(), unreferenced_stringnames, unreferenced_stringnames / float(data.size()) * 100)); + print_line(vformat("Out of %d StringNames, %d StringNames were rarely referenced during this run (1-4 times) (%.2f%%).", data.size(), rarely_referenced_stringnames, rarely_referenced_stringnames / float(data.size()) * 100)); } #endif int lost_strings = 0; diff --git a/core/templates/oa_hash_map.h b/core/templates/oa_hash_map.h index c91d27ebe1..4e712fccf2 100644 --- a/core/templates/oa_hash_map.h +++ b/core/templates/oa_hash_map.h @@ -145,7 +145,7 @@ private: uint32_t old_capacity = capacity; // Capacity can't be 0. - capacity = MAX(1, p_new_capacity); + capacity = MAX(1u, p_new_capacity); TKey *old_keys = keys; TValue *old_values = values; @@ -367,7 +367,7 @@ public: OAHashMap(uint32_t p_initial_capacity = 64) { // Capacity can't be 0. - capacity = MAX(1, p_initial_capacity); + capacity = MAX(1u, p_initial_capacity); keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity)); values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity)); diff --git a/core/typedefs.h b/core/typedefs.h index 2c32d102da..510b39177c 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -89,34 +89,43 @@ #undef ERROR // override (really stupid) wingdi.h standard definition #undef DELETE // override (another really stupid) winnt.h standard definition #undef MessageBox // override winuser.h standard definition -#undef MIN // override standard definition -#undef MAX // override standard definition -#undef CLAMP // override standard definition #undef Error #undef OK #undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum #endif +// Make room for our constexpr's below by overriding potential system-specific macros. +#undef ABS +#undef SIGN +#undef MIN +#undef MAX +#undef CLAMP + // Generic ABS function, for math uses please use Math::abs. -#ifndef ABS -#define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v)) -#endif +template <typename T> +constexpr T ABS(T m_v) { + return m_v < 0 ? -m_v : m_v; +} -#ifndef SIGN -#define SIGN(m_v) (((m_v) == 0) ? (0.0f) : (((m_v) < 0) ? (-1.0f) : (+1.0f))) -#endif +template <typename T> +constexpr const T SIGN(const T m_v) { + return m_v == 0 ? 0.0f : (m_v < 0 ? -1.0f : +1.0f); +} -#ifndef MIN -#define MIN(m_a, m_b) (((m_a) < (m_b)) ? (m_a) : (m_b)) -#endif +template <typename T, typename T2> +constexpr auto MIN(const T m_a, const T2 m_b) { + return m_a < m_b ? m_a : m_b; +} -#ifndef MAX -#define MAX(m_a, m_b) (((m_a) > (m_b)) ? (m_a) : (m_b)) -#endif +template <typename T, typename T2> +constexpr auto MAX(const T m_a, const T2 m_b) { + return m_a > m_b ? m_a : m_b; +} -#ifndef CLAMP -#define CLAMP(m_a, m_min, m_max) (((m_a) < (m_min)) ? (m_min) : (((m_a) > (m_max)) ? m_max : m_a)) -#endif +template <typename T, typename T2, typename T3> +constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) { + return m_a < m_min ? m_min : (m_a > m_max ? m_max : m_a); +} // Generic swap template. #ifndef SWAP diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index f31191e8a3..22a13b0fab 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -100,6 +100,10 @@ struct VariantCaster<const T &> { _FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \ *(int64_t *)p_ptr = (int64_t)p_val; \ } \ + }; \ + template <> \ + struct ZeroInitializer<m_enum> { \ + static void initialize(m_enum &value) { value = (m_enum)0; } \ }; // Object enum casts must go here diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h index 8e9fbbc0a4..ed68e0f6c9 100644 --- a/core/variant/native_ptr.h +++ b/core/variant/native_ptr.h @@ -124,6 +124,7 @@ struct PtrToArg<GDNativePtr<T>> { } }; +GDVIRTUAL_NATIVE_PTR(void) GDVIRTUAL_NATIVE_PTR(AudioFrame) GDVIRTUAL_NATIVE_PTR(bool) GDVIRTUAL_NATIVE_PTR(char) diff --git a/core/variant/type_info.h b/core/variant/type_info.h index ee050cff4f..bacd0d19ce 100644 --- a/core/variant/type_info.h +++ b/core/variant/type_info.h @@ -281,4 +281,38 @@ inline StringName __constant_get_enum_name(T param, const String &p_constant) { #define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info()) +template <typename T> +struct ZeroInitializer { + static void initialize(T &value) {} //no initialization by default +}; + +template <> +struct ZeroInitializer<bool> { + static void initialize(bool &value) { value = false; } +}; + +template <typename T> +struct ZeroInitializer<T *> { + static void initialize(T *&value) { value = nullptr; } +}; + +#define ZERO_INITIALIZER_NUMBER(m_type) \ + template <> \ + struct ZeroInitializer<m_type> { \ + static void initialize(m_type &value) { value = 0; } \ + }; + +ZERO_INITIALIZER_NUMBER(uint8_t) +ZERO_INITIALIZER_NUMBER(int8_t) +ZERO_INITIALIZER_NUMBER(uint16_t) +ZERO_INITIALIZER_NUMBER(int16_t) +ZERO_INITIALIZER_NUMBER(uint32_t) +ZERO_INITIALIZER_NUMBER(int32_t) +ZERO_INITIALIZER_NUMBER(uint64_t) +ZERO_INITIALIZER_NUMBER(int64_t) +ZERO_INITIALIZER_NUMBER(char16_t) +ZERO_INITIALIZER_NUMBER(char32_t) +ZERO_INITIALIZER_NUMBER(float) +ZERO_INITIALIZER_NUMBER(double) + #endif // TYPE_INFO_H diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 1228cd771c..f692a49ba1 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -2516,7 +2516,10 @@ <constant name="PROPERTY_HINT_LOCALE_ID" value="41" enum="PropertyHint"> Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country. </constant> - <constant name="PROPERTY_HINT_MAX" value="42" enum="PropertyHint"> + <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="42" enum="PropertyHint"> + Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings. + </constant> + <constant name="PROPERTY_HINT_MAX" value="43" enum="PropertyHint"> </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags"> </constant> diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index 6e4a4a2145..db880efaf2 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -228,11 +228,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="AABB" /> <description> Returns [code]true[/code] if the vectors are not equal. @@ -248,11 +243,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="AABB" /> <description> Returns [code]true[/code] if the AABBs are exactly equal. diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 6852fb5228..68cb615209 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -511,11 +511,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Array" /> <description> </description> @@ -540,11 +535,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Array" /> <description> </description> diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 8e73a0dd91..13fe75a3e3 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -44,25 +44,24 @@ </method> </methods> <members> - <member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="BaseButton.ActionMode" default="1"> + <member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="BaseButton.ActionMode"> Determines when the button is considered clicked, one of the [enum ActionMode] constants. </member> <member name="button_group" type="ButtonGroup" setter="set_button_group" getter="get_button_group"> The [ButtonGroup] associated with the button. Not to be confused with node groups. </member> - <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButton" default="1"> + <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButton"> Binary mask to choose which mouse buttons this button will respond to. To allow both left-click and right-click, use [code]MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT[/code]. </member> - <member name="button_pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false"> + <member name="button_pressed" type="bool" setter="set_pressed" getter="is_pressed"> If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active). Only works if [member toggle_mode] is [code]true[/code]. [b]Note:[/b] Setting [member button_pressed] will result in [signal toggled] to be emitted. If you want to change the pressed state without emitting that signal, use [method set_pressed_no_signal]. </member> - <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false"> + <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled"> If [code]true[/code], the button is in disabled state and can't be clicked or toggled. </member> - <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" /> - <member name="keep_pressed_outside" type="bool" setter="set_keep_pressed_outside" getter="is_keep_pressed_outside" default="false"> + <member name="keep_pressed_outside" type="bool" setter="set_keep_pressed_outside" getter="is_keep_pressed_outside"> If [code]true[/code], the button stays pressed when moving the cursor outside the button while pressing it. [b]Note:[/b] This property only affects the button's visual appearance. Signals will be emitted at the same moment regardless of this property's value. </member> @@ -72,10 +71,10 @@ <member name="shortcut_context" type="Node" setter="set_shortcut_context" getter="get_shortcut_context"> The [Node] which must be a parent of the focused GUI [Control] for the shortcut to be activated. If [code]null[/code], the shortcut can be activated when any control is focused (a global shortcut). This allows shortcuts to be accepted only when the user has a certain area of the GUI focused. </member> - <member name="shortcut_in_tooltip" type="bool" setter="set_shortcut_in_tooltip" getter="is_shortcut_in_tooltip_enabled" default="true"> + <member name="shortcut_in_tooltip" type="bool" setter="set_shortcut_in_tooltip" getter="is_shortcut_in_tooltip_enabled"> If [code]true[/code], the button will add information about its shortcut in the tooltip. </member> - <member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode" default="false"> + <member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode"> If [code]true[/code], the button is in toggle mode. Makes the button flip state between pressed and unpressed each time its area is clicked. </member> </members> diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index f31e962632..3b703884a5 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -225,11 +225,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Basis" /> <description> Returns [code]true[/code] if the [Basis] matrices are not equal. @@ -266,11 +261,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Basis" /> <description> Returns [code]true[/code] if the [Basis] matrices are exactly equal. diff --git a/doc/classes/BoxShape3D.xml b/doc/classes/BoxShape3D.xml index 154af1221f..c198dd3405 100644 --- a/doc/classes/BoxShape3D.xml +++ b/doc/classes/BoxShape3D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="BoxShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Box shape resource. + Box shape resource for 3D collisions. </brief_description> <description> - 3D box shape that can be a child of a [PhysicsBody3D] or [Area3D]. + 3D box shape to be added as a [i]direct[/i] child of a [PhysicsBody3D] or [Area3D] using a [CollisionShape3D] node. + [b]Performance:[/b] Being a primitive collision shape, [BoxShape3D] is fast to check collisions against (though not as fast as [SphereShape3D]). </description> <tutorials> <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link> diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml index 7c7e37d0a5..efe3e3d091 100644 --- a/doc/classes/Callable.xml +++ b/doc/classes/Callable.xml @@ -150,11 +150,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Callable" /> <description> Returns [code]true[/code] if both [Callable]s invoke different targets. @@ -162,11 +157,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Callable" /> <description> Returns [code]true[/code] if both [Callable]s invoke the same custom target. diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml index 3350735ca2..b9373676e2 100644 --- a/doc/classes/Camera2D.xml +++ b/doc/classes/Camera2D.xml @@ -157,7 +157,7 @@ Speed in pixels per second of the camera's smoothing effect when [member smoothing_enabled] is [code]true[/code]. </member> <member name="zoom" type="Vector2" setter="set_zoom" getter="get_zoom" default="Vector2(1, 1)"> - The camera's zoom relative to the viewport. Values larger than [code]Vector2(1, 1)[/code] zoom out and smaller values zoom in. For an example, use [code]Vector2(0.5, 0.5)[/code] for a 2× zoom-in, and [code]Vector2(4, 4)[/code] for a 4× zoom-out. + The camera's zoom. A zoom of [code]Vector(2, 2)[/code] doubles the size seen in the viewport. A zoom of [code]Vector(0.5, 0.5)[/code] halves the size seen in the viewport. </member> </members> <constants> diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index d71762801c..c7451509f3 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -355,6 +355,13 @@ Returns the mouse's position in this [CanvasItem] using the local coordinate system of this [CanvasItem]. </description> </method> + <method name="get_screen_transform" qualifiers="const"> + <return type="Transform2D" /> + <description> + Returns the transform of this [CanvasItem] in global screen coordinates (i.e. taking window position into account). Mostly useful for editor plugins. + Equals to [method get_global_transform] if the window is embedded (see [member Viewport.gui_embed_subwindows]). + </description> + </method> <method name="get_transform" qualifiers="const"> <return type="Transform2D" /> <description> diff --git a/doc/classes/CapsuleShape2D.xml b/doc/classes/CapsuleShape2D.xml index ae8e1ca001..2236d8035f 100644 --- a/doc/classes/CapsuleShape2D.xml +++ b/doc/classes/CapsuleShape2D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CapsuleShape2D" inherits="Shape2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Capsule shape for 2D collisions. + Capsule shape resource for 2D physics. </brief_description> <description> - Capsule shape for 2D collisions. + 2D capsule shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. In 2D, a capsule is a rectangle shape with half-circles at both ends. + [b]Performance:[/b] Being a primitive collision shape, [CapsuleShape2D] is fast to check collisions against (though not as fast as [CircleShape2D]). </description> <tutorials> </tutorials> diff --git a/doc/classes/CapsuleShape3D.xml b/doc/classes/CapsuleShape3D.xml index 5f15aaafad..cdcfab76ce 100644 --- a/doc/classes/CapsuleShape3D.xml +++ b/doc/classes/CapsuleShape3D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CapsuleShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Capsule shape for collisions. + Capsule shape resource for 3D collisions. </brief_description> <description> - Capsule shape for collisions. + 3D capsule shape to be added as a [i]direct[/i] child of a [PhysicsBody3D] or [Area3D] using a [CollisionShape3D] node. In 3D, a capsule is a cylinder shape with hemispheres at both ends. + [b]Performance:[/b] Being a primitive collision shape, [CapsuleShape3D] is fast to check collisions against (though not as fast as [SphereShape3D]). [CapsuleShape3D] is cheaper to check collisions against compared to [CylinderShape3D]. </description> <tutorials> <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link> diff --git a/doc/classes/CircleShape2D.xml b/doc/classes/CircleShape2D.xml index b0336086dc..6f4989daa3 100644 --- a/doc/classes/CircleShape2D.xml +++ b/doc/classes/CircleShape2D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CircleShape2D" inherits="Shape2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Circular shape for 2D collisions. + Circular shape resource for 2D physics. </brief_description> <description> - Circular shape for 2D collisions. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast. + 2D circular shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast. + [b]Performance:[/b] Being a primitive collision shape, [CircleShape2D] is the fastest collision shape to check collisions against, as it only requires a distance check with the shape's origin. </description> <tutorials> </tutorials> diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml index 48fd7c19dc..a9d8a85226 100644 --- a/doc/classes/CollisionPolygon2D.xml +++ b/doc/classes/CollisionPolygon2D.xml @@ -4,7 +4,8 @@ Defines a 2D collision polygon. </brief_description> <description> - Provides a 2D collision polygon to a [CollisionObject2D] parent. Polygons can be drawn in the editor or specified by a list of vertices. + Provides a concave or convex 2D collision polygon to a [CollisionObject2D] parent. Polygons can be drawn in the editor or specified by a list of vertices. See also [ConvexPolygonShape2D]. + In the editor, a [CollisionPolygon2D] can be generated from a [Sprite2D]'s outline by selecting a [Sprite2D] node, going to the [b]Sprite2D[/b] menu at the top of the 2D editor viewport then choosing [b]Create CollisionPolygon2D Sibling[/b]. </description> <tutorials> </tutorials> diff --git a/doc/classes/CollisionPolygon3D.xml b/doc/classes/CollisionPolygon3D.xml index c8c3752254..7d718cff27 100644 --- a/doc/classes/CollisionPolygon3D.xml +++ b/doc/classes/CollisionPolygon3D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CollisionPolygon3D" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Editor-only class for defining a collision polygon in 3D space. + Editor-only node for defining a collision polygon in 3D space. </brief_description> <description> - Allows editing a collision polygon's vertices on a selected plane. Can also set a depth perpendicular to that plane. This class is only available in the editor. It will not appear in the scene tree at run-time. Creates a [Shape3D] for gameplay. Properties modified during gameplay will have no effect. + Allows editing a concave or convex collision polygon's vertices on a selected plane. Can also set a depth perpendicular to that plane. This class is only available in the editor. It will not appear in the scene tree at run-time. Creates several [ConvexPolygonShape3D]s at run-time to represent the original polygon using convex decomposition. + [b]Note:[/b] Since this is an editor-only helper, properties modified during gameplay will have no effect. </description> <tutorials> </tutorials> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index bc0baf42c9..7083157081 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -915,11 +915,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Color" /> <description> Returns [code]true[/code] if the colors are not equal. @@ -984,11 +979,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Color" /> <description> Returns [code]true[/code] if the colors are exactly equal. diff --git a/doc/classes/CompressedTexture2D.xml b/doc/classes/CompressedTexture2D.xml index c99fcf2280..5f73b55f69 100644 --- a/doc/classes/CompressedTexture2D.xml +++ b/doc/classes/CompressedTexture2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CompressedTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - A [code].stex[/code] texture. + A [code].ctex[/code] texture. </brief_description> <description> - A texture that is loaded from a [code].stex[/code] file. + A texture that is loaded from a [code].ctex[/code] file. </description> <tutorials> </tutorials> @@ -19,7 +19,7 @@ </methods> <members> <member name="load_path" type="String" setter="load" getter="get_load_path" default=""""> - The CompressedTexture's file path to a [code].stex[/code] file. + The CompressedTexture's file path to a [code].ctex[/code] file. </member> </members> </class> diff --git a/doc/classes/ConcavePolygonShape2D.xml b/doc/classes/ConcavePolygonShape2D.xml index 924178f9bf..f3c245c229 100644 --- a/doc/classes/ConcavePolygonShape2D.xml +++ b/doc/classes/ConcavePolygonShape2D.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ConcavePolygonShape2D" inherits="Shape2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Concave polygon 2D shape resource for physics. + Concave polygon shape resource for 2D physics. </brief_description> <description> - Concave polygon 2D shape resource for physics. It is made out of segments and is optimal for complex polygonal concave collisions. However, it is not advised to use for [RigidDynamicBody2D] nodes. A CollisionPolygon2D in convex decomposition mode (solids) or several convex objects are advised for that instead. Otherwise, a concave polygon 2D shape is better for static collisions. - The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex in order to speed up collision detection. + 2D concave polygon shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. It is made out of segments and is optimal for complex polygonal concave collisions. However, it is not advised to use for [RigidDynamicBody2D] nodes. A CollisionPolygon2D in convex decomposition mode (solids) or several convex objects are advised for that instead. Otherwise, a concave polygon 2D shape is better for static collisions. + The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex to speed up collision detection. + [b]Performance:[/b] Due to its complexity, [ConcavePolygonShape2D] is the slowest collision shape to check collisions against. Its use should generally be limited to level geometry. For convex geometry, using [ConvexPolygonShape2D] will perform better. For dynamic physics bodies that need concave collision, several [ConvexPolygonShape2D]s can be used to represent its collision by using convex decomposition; see [ConvexPolygonShape2D]'s documentation for instructions. However, consider using primitive collision shapes such as [CircleShape2D] or [RectangleShape2D] first. </description> <tutorials> </tutorials> diff --git a/doc/classes/ConcavePolygonShape3D.xml b/doc/classes/ConcavePolygonShape3D.xml index 4e67f91db8..60d7e32492 100644 --- a/doc/classes/ConcavePolygonShape3D.xml +++ b/doc/classes/ConcavePolygonShape3D.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ConcavePolygonShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Concave polygon shape. + Concave polygon shape resource (also called "trimesh") for 3D physics. </brief_description> <description> - Concave polygon shape resource, which can be set into a [PhysicsBody3D] or area. This shape is created by feeding a list of triangles. + 3D concave polygon shape resource (also called "trimesh") to be added as a [i]direct[/i] child of a [PhysicsBody3D] or [Area3D] using a [CollisionShape3D] node. This shape is created by feeding a list of triangles. Despite its name, [ConcavePolygonShape3D] can also store convex polygon shapes. However, unlike [ConvexPolygonShape3D], [ConcavePolygonShape3D] is [i]not[/i] limited to storing convex shapes exclusively. [b]Note:[/b] When used for collision, [ConcavePolygonShape3D] is intended to work with static [PhysicsBody3D] nodes like [StaticBody3D] and will not work with [CharacterBody3D] or [RigidDynamicBody3D] with a mode other than Static. + [b]Performance:[/b] Due to its complexity, [ConcavePolygonShape3D] is the slowest collision shape to check collisions against. Its use should generally be limited to level geometry. For convex geometry, using [ConvexPolygonShape3D] will perform better. For dynamic physics bodies that need concave collision, several [ConvexPolygonShape3D]s can be used to represent its collision by using convex decomposition; see [ConvexPolygonShape3D]'s documentation for instructions. However, consider using primitive collision shapes such as [SphereShape3D] or [BoxShape3D] first. </description> <tutorials> <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 97fd584ed1..3163ac5610 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -417,6 +417,19 @@ Returns the position and size of the control relative to the top-left corner of the parent Control. See [member position] and [member size]. </description> </method> + <method name="get_screen_position" qualifiers="const"> + <return type="Vector2" /> + <description> + Returns the position of this [Control] in global screen coordinates (i.e. taking window position into account). Mostly useful for editor plugins. + Equals to [member global_position] if the window is embedded (see [member Viewport.gui_embed_subwindows]). + Example usage for showing a popup: + [codeblock] + popup_menu.position = get_screen_position() + get_local_mouse_position() + popup_menu.reset_size() + popup_menu.popup() + [/codeblock] + </description> + </method> <method name="get_theme_color" qualifiers="const"> <return type="Color" /> <argument index="0" name="name" type="StringName" /> diff --git a/doc/classes/ConvexPolygonShape2D.xml b/doc/classes/ConvexPolygonShape2D.xml index 449c3132c7..df96b50fc1 100644 --- a/doc/classes/ConvexPolygonShape2D.xml +++ b/doc/classes/ConvexPolygonShape2D.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ConvexPolygonShape2D" inherits="Shape2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Convex polygon shape for 2D physics. + Convex polygon shape resource for 2D physics. </brief_description> <description> - Convex polygon shape for 2D physics. A convex polygon, whatever its shape, is internally decomposed into as many convex polygons as needed to ensure all collision checks against it are always done on convex polygons (which are faster to check). - The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex in order to speed up collision detection. + 2D convex polygon shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. A convex polygon, whatever its shape, is internally decomposed into as many convex polygons as needed to ensure all collision checks against it are always done on convex polygons (which are faster to check). See also [CollisionPolygon2D]. + The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex to speed up collision detection. + [b]Performance:[/b] [ConvexPolygonShape2D] is faster to check collisions against compared to [ConcavePolygonShape2D], but it is slower than primitive collision shapes such as [CircleShape2D] or [RectangleShape2D]. Its use should generally be limited to medium-sized objects that cannot have their collision accurately represented by a primitive shape. </description> <tutorials> </tutorials> diff --git a/doc/classes/ConvexPolygonShape3D.xml b/doc/classes/ConvexPolygonShape3D.xml index d2f110d187..32dc8f673b 100644 --- a/doc/classes/ConvexPolygonShape3D.xml +++ b/doc/classes/ConvexPolygonShape3D.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ConvexPolygonShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Convex polygon shape for 3D physics. + Convex polygon shape resource for 3D physics. </brief_description> <description> - Convex polygon shape resource, which can be added to a [PhysicsBody3D] or area. + 3D convex polygon shape resource to be added as a [i]direct[/i] child of a [PhysicsBody3D] or [Area3D] using a [CollisionShape3D] node. Unlike [ConcavePolygonShape3D], [ConvexPolygonShape3D] cannot store concave polygon shapes. [ConvexPolygonShape2D]s can be manually drawn in the editor using the [CollisionPolygon3D] node. + [b]Convex decomposition:[/b] Concave objects' collisions can be represented accurately using [i]several[/i] [ConvexPolygonShape3D]s. This allows dynamic physics bodies to have complex concave collisions (at a performance cost). This is available in the editor by selecting the [MeshInstance3D], going to the [b]Mesh[/b] menu and choosing [b]Create Multiple Convex Collision Siblings[/b]. Alternatively, [method MeshInstance3D.create_multiple_convex_collisions] can be called in a script to perform this decomposition at run-time. + [b]Performance:[/b] [ConvexPolygonShape3D] is faster to check collisions against compared to [ConcavePolygonShape3D], but it is slower than primitive collision shapes such as [SphereShape3D] or [BoxShape3D]. Its use should generally be limited to medium-sized objects that cannot have their collision accurately represented by a primitive shape. </description> <tutorials> <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link> diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml index f040d292e9..94e52912a1 100644 --- a/doc/classes/Curve2D.xml +++ b/doc/classes/Curve2D.xml @@ -17,7 +17,7 @@ <argument index="2" name="out" type="Vector2" default="Vector2(0, 0)" /> <argument index="3" name="at_position" type="int" default="-1" /> <description> - Adds a point to a curve at [code]position[/code], with control points [code]in[/code] and [code]out[/code]. + Adds a point to a curve at [code]position[/code] relative to the [Curve2D]'s position, with control points [code]in[/code] and [code]out[/code]. If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position <0[/code] or [code]at_position >= [method get_point_count][/code]), the point will be appended at the end of the point list. </description> </method> diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml index 27856f2564..ed642e0ddc 100644 --- a/doc/classes/Curve3D.xml +++ b/doc/classes/Curve3D.xml @@ -17,7 +17,7 @@ <argument index="2" name="out" type="Vector3" default="Vector3(0, 0, 0)" /> <argument index="3" name="at_position" type="int" default="-1" /> <description> - Adds a point to a curve at [code]position[/code], with control points [code]in[/code] and [code]out[/code]. + Adds a point to a curve at [code]position[/code] relative to the [Curve3D]'s position, with control points [code]in[/code] and [code]out[/code]. If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position <0[/code] or [code]at_position >= [method get_point_count][/code]), the point will be appended at the end of the point list. </description> </method> diff --git a/doc/classes/CylinderShape3D.xml b/doc/classes/CylinderShape3D.xml index 06ad590bb3..6ff142da59 100644 --- a/doc/classes/CylinderShape3D.xml +++ b/doc/classes/CylinderShape3D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CylinderShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Cylinder shape for collisions. + Cylinder shape for 3D collisions. </brief_description> <description> - Cylinder shape for collisions. + Cylinder shape for collisions. Like [CapsuleShape3D], but without hemispheres at the cylinder's ends. + [b]Performance:[/b] Being a primitive collision shape, [CylinderShape3D] is fast to check collisions against (though not as fast as [SphereShape3D]). [CylinderShape3D] is also more demanding compared to [CapsuleShape3D]. </description> <tutorials> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml index ab04366eb7..8ee09ba8f8 100644 --- a/doc/classes/Dictionary.xml +++ b/doc/classes/Dictionary.xml @@ -307,22 +307,12 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Dictionary" /> <description> </description> </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Dictionary" /> <description> </description> diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml index 698d3bfcce..8aa2db2cf8 100644 --- a/doc/classes/EditorExportPlugin.xml +++ b/doc/classes/EditorExportPlugin.xml @@ -108,6 +108,7 @@ <return type="void" /> <argument index="0" name="path" type="String" /> <argument index="1" name="tags" type="PackedStringArray" /> + <argument index="2" name="target" type="String" /> <description> Adds a shared object or a directory containing only shared objects with the given [code]tags[/code] and destination [code]path[/code]. [b]Note:[/b] In case of macOS exports, those shared objects will be added to [code]Frameworks[/code] directory of app bundle. diff --git a/doc/classes/EditorFileDialog.xml b/doc/classes/EditorFileDialog.xml index 0474cbd387..b1fd7b4e76 100644 --- a/doc/classes/EditorFileDialog.xml +++ b/doc/classes/EditorFileDialog.xml @@ -40,13 +40,13 @@ <member name="access" type="int" setter="set_access" getter="get_access" enum="EditorFileDialog.Access" default="0"> The location from which the user may select a file, including [code]res://[/code], [code]user://[/code], and the local file system. </member> - <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir" default=""res://""> + <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir"> The currently occupied directory. </member> - <member name="current_file" type="String" setter="set_current_file" getter="get_current_file" default=""""> + <member name="current_file" type="String" setter="set_current_file" getter="get_current_file"> The currently selected file. </member> - <member name="current_path" type="String" setter="set_current_path" getter="get_current_path" default=""res://""> + <member name="current_path" type="String" setter="set_current_path" getter="get_current_path"> The file system path in the address bar. </member> <member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" /> diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml index a45882b063..96dea1edce 100644 --- a/doc/classes/EditorSpinSlider.xml +++ b/doc/classes/EditorSpinSlider.xml @@ -11,7 +11,6 @@ <members> <member name="flat" type="bool" setter="set_flat" getter="is_flat" default="false"> </member> - <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" /> <member name="label" type="String" setter="set_label" getter="get_label" default=""""> </member> <member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false"> diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml index 05d90390f8..db536a738a 100644 --- a/doc/classes/FileDialog.xml +++ b/doc/classes/FileDialog.xml @@ -56,13 +56,13 @@ The file system access scope. See enum [code]Access[/code] constants. [b]Warning:[/b] Currently, in sandboxed environments such as HTML5 builds or sandboxed macOS apps, FileDialog cannot access the host file system. See [url=https://github.com/godotengine/godot-proposals/issues/1123]godot-proposals#1123[/url]. </member> - <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir" default=""res://""> + <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir"> The current working directory of the file dialog. </member> - <member name="current_file" type="String" setter="set_current_file" getter="get_current_file" default=""""> + <member name="current_file" type="String" setter="set_current_file" getter="get_current_file"> The currently selected file of the file dialog. </member> - <member name="current_path" type="String" setter="set_current_path" getter="get_current_path" default=""res://""> + <member name="current_path" type="String" setter="set_current_path" getter="get_current_path"> The currently selected file path of the file dialog. </member> <member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" /> diff --git a/doc/classes/FontData.xml b/doc/classes/FontData.xml index ccaefc60ee..9344a1fe80 100644 --- a/doc/classes/FontData.xml +++ b/doc/classes/FontData.xml @@ -567,6 +567,9 @@ <member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()"> Contents of the dynamic font source file. </member> + <member name="embolden" type="float" setter="set_embolden" getter="get_embolden" default="0.0"> + If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness. + </member> <member name="fixed_size" type="int" setter="set_fixed_size" getter="get_fixed_size" default="0"> Font size, used only for the bitmap fonts. </member> @@ -603,5 +606,9 @@ <member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1"> Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size. </member> + <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)"> + 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs. + For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code]. + </member> </members> </class> diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index 77afb98225..c803f43fb0 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -31,22 +31,22 @@ </method> </methods> <members> - <member name="cast_shadow" type="int" setter="set_cast_shadows_setting" getter="get_cast_shadows_setting" enum="GeometryInstance3D.ShadowCastingSetting" default="1"> + <member name="cast_shadow" type="int" setter="set_cast_shadows_setting" getter="get_cast_shadows_setting" enum="GeometryInstance3D.ShadowCastingSetting"> The selected shadow casting flag. See [enum ShadowCastingSetting] for possible values. </member> - <member name="extra_cull_margin" type="float" setter="set_extra_cull_margin" getter="get_extra_cull_margin" default="0.0"> + <member name="extra_cull_margin" type="float" setter="set_extra_cull_margin" getter="get_extra_cull_margin"> The extra distance added to the GeometryInstance3D's bounding box ([AABB]) to increase its cull box. </member> - <member name="gi_lightmap_scale" type="int" setter="set_lightmap_scale" getter="get_lightmap_scale" enum="GeometryInstance3D.LightmapScale" default="0"> + <member name="gi_lightmap_scale" type="int" setter="set_lightmap_scale" getter="get_lightmap_scale" enum="GeometryInstance3D.LightmapScale"> The texel density to use for lightmapping in [LightmapGI]. Greater scale values provide higher resolution in the lightmap, which can result in sharper shadows for lights that have both direct and indirect light baked. However, greater scale values will also increase the space taken by the mesh in the lightmap texture, which increases the memory, storage, and bake time requirements. When using a single mesh at different scales, consider adjusting this value to keep the lightmap texel density consistent across meshes. </member> - <member name="gi_mode" type="int" setter="set_gi_mode" getter="get_gi_mode" enum="GeometryInstance3D.GIMode" default="0"> + <member name="gi_mode" type="int" setter="set_gi_mode" getter="get_gi_mode" enum="GeometryInstance3D.GIMode"> The global illumination mode to use for the whole geometry. To avoid inconsistent results, use a mode that matches the purpose of the mesh during gameplay (static/dynamic). [b]Note:[/b] Lights' bake mode will also affect the global illumination rendering. See [member Light3D.light_bake_mode]. </member> - <member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling" default="false"> + <member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling"> </member> - <member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias" default="1.0"> + <member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias"> </member> <member name="material_overlay" type="Material" setter="set_material_overlay" getter="get_material_overlay"> The material overlay for the whole geometry. @@ -56,26 +56,26 @@ The material override for the whole geometry. If a material is assigned to this property, it will be used instead of any material set in any material slot of the mesh. </member> - <member name="transparency" type="float" setter="set_transparency" getter="get_transparency" default="0.0"> + <member name="transparency" type="float" setter="set_transparency" getter="get_transparency"> The transparency applied to the whole geometry (as a multiplier of the materials' existing transparency). [code]0.0[/code] is fully opaque, while [code]1.0[/code] is fully transparent. Values greater than [code]0.0[/code] (exclusive) will force the geometry's materials to go through the transparent pipeline, which is slower to render and can exhibit rendering issues due to incorrect transparency sorting. However, unlike using a transparent material, setting [member transparency] to a value greater than [code]0.0[/code] (exclusive) will [i]not[/i] disable shadow rendering. In spatial shaders, [code]1.0 - transparency[/code] is set as the default value of the [code]ALPHA[/code] built-in. [b]Note:[/b] [member transparency] is clamped between [code]0.0[/code] and [code]1.0[/code], so this property cannot be used to make transparent materials more opaque than they originally are. </member> - <member name="visibility_range_begin" type="float" setter="set_visibility_range_begin" getter="get_visibility_range_begin" default="0.0"> + <member name="visibility_range_begin" type="float" setter="set_visibility_range_begin" getter="get_visibility_range_begin"> Starting distance from which the GeometryInstance3D will be visible, taking [member visibility_range_begin_margin] into account as well. The default value of 0 is used to disable the range check. </member> - <member name="visibility_range_begin_margin" type="float" setter="set_visibility_range_begin_margin" getter="get_visibility_range_begin_margin" default="0.0"> + <member name="visibility_range_begin_margin" type="float" setter="set_visibility_range_begin_margin" getter="get_visibility_range_begin_margin"> Margin for the [member visibility_range_begin] threshold. The GeometryInstance3D will only change its visibility state when it goes over or under the [member visibility_range_begin] threshold by this amount. If [member visibility_range_fade_mode] is [constant VISIBILITY_RANGE_FADE_DISABLED], this acts as an hysteresis distance. If [member visibility_range_fade_mode] is [constant VISIBILITY_RANGE_FADE_SELF] or [constant VISIBILITY_RANGE_FADE_DEPENDENCIES], this acts as a fade transition distance and must be set to a value greater than [code]0.0[/code] for the effect to be noticeable. </member> - <member name="visibility_range_end" type="float" setter="set_visibility_range_end" getter="get_visibility_range_end" default="0.0"> + <member name="visibility_range_end" type="float" setter="set_visibility_range_end" getter="get_visibility_range_end"> Distance from which the GeometryInstance3D will be hidden, taking [member visibility_range_end_margin] into account as well. The default value of 0 is used to disable the range check. </member> - <member name="visibility_range_end_margin" type="float" setter="set_visibility_range_end_margin" getter="get_visibility_range_end_margin" default="0.0"> + <member name="visibility_range_end_margin" type="float" setter="set_visibility_range_end_margin" getter="get_visibility_range_end_margin"> Margin for the [member visibility_range_end] threshold. The GeometryInstance3D will only change its visibility state when it goes over or under the [member visibility_range_end] threshold by this amount. If [member visibility_range_fade_mode] is [constant VISIBILITY_RANGE_FADE_DISABLED], this acts as an hysteresis distance. If [member visibility_range_fade_mode] is [constant VISIBILITY_RANGE_FADE_SELF] or [constant VISIBILITY_RANGE_FADE_DEPENDENCIES], this acts as a fade transition distance and must be set to a value greater than [code]0.0[/code] for the effect to be noticeable. </member> - <member name="visibility_range_fade_mode" type="int" setter="set_visibility_range_fade_mode" getter="get_visibility_range_fade_mode" enum="GeometryInstance3D.VisibilityRangeFadeMode" default="0"> + <member name="visibility_range_fade_mode" type="int" setter="set_visibility_range_fade_mode" getter="get_visibility_range_fade_mode" enum="GeometryInstance3D.VisibilityRangeFadeMode"> Controls which instances will be faded when approaching the limits of the visibility range. See [enum VisibilityRangeFadeMode] for possible values. </member> </members> diff --git a/doc/classes/HeightMapShape3D.xml b/doc/classes/HeightMapShape3D.xml index b8fe094490..206981e547 100644 --- a/doc/classes/HeightMapShape3D.xml +++ b/doc/classes/HeightMapShape3D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="HeightMapShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Height map shape for 3D physics. + Height map shape resource for 3D physics. </brief_description> <description> - Height map shape resource, which can be added to a [PhysicsBody3D] or [Area3D]. + Height map shape resource, which can be added to a [PhysicsBody3D] or [Area3D]. Heightmap collision is typically used for colliding with terrains. However, since heightmaps cannot store overhangs, collisions with other structures (such as buildings) must be done with other collision shapes such as [ConcavePolygonShape3D]. If needed, "holes" can be created in an [HeightMapShape3D] by assigning very low points (like [code]-100000[/code]) in the desired area. + [b]Performance:[/b] [HeightMapShape3D] is faster to check collisions against compared to [ConcavePolygonShape3D], but it is slower than primitive collision shapes such as [SphereShape3D] or [BoxShape3D]. </description> <tutorials> </tutorials> diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index 48fa009300..06bd64577b 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -7,6 +7,7 @@ This control provides a selectable list of items that may be in a single (or multiple columns) with option of text, icons, or both text and icon. Tooltips are supported and may be different for every item in the list. Selectable items in the list may be selected or deselected and multiple selection may be enabled. Selection with right mouse button may also be enabled to allow use of popup context menus. Items may also be "activated" by double-clicking them or by pressing [kbd]Enter[/kbd]. Item text only supports single-line strings, newline characters (e.g. [code]\n[/code]) in the string won't produce a newline. Text wrapping is enabled in [constant ICON_MODE_TOP] mode, but column's width is adjusted to fully fit its content by default. You need to set [member fixed_column_width] greater than zero to wrap the text. + All [code]set_*[/code] methods allow negative item index, which makes the item accessed from the last one. </description> <tutorials> </tutorials> diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml index ad5a5a5518..3b03d86644 100644 --- a/doc/classes/LinkButton.xml +++ b/doc/classes/LinkButton.xml @@ -33,11 +33,9 @@ </method> </methods> <members> - <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="0" /> <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. </member> - <member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" overrides="Control" enum="Control.CursorShape" default="2" /> <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. </member> diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml index e4116cddfe..2b24901fe2 100644 --- a/doc/classes/Mesh.xml +++ b/doc/classes/Mesh.xml @@ -176,7 +176,7 @@ </method> </methods> <members> - <member name="lightmap_size_hint" type="Vector2i" setter="set_lightmap_size_hint" getter="get_lightmap_size_hint" default="Vector2i(0, 0)"> + <member name="lightmap_size_hint" type="Vector2i" setter="set_lightmap_size_hint" getter="get_lightmap_size_hint"> Sets a hint to be used for lightmap resolution. </member> </members> diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml index 3d3e139781..3319e5d822 100644 --- a/doc/classes/NodePath.xml +++ b/doc/classes/NodePath.xml @@ -5,21 +5,22 @@ </brief_description> <description> A pre-parsed relative or absolute path in a scene tree, for use with [method Node.get_node] and similar functions. It can reference a node, a resource within a node, or a property of a node or resource. For instance, [code]"Path2D/PathFollow2D/Sprite2D:texture:size"[/code] would refer to the [code]size[/code] property of the [code]texture[/code] resource on the node named [code]"Sprite2D"[/code] which is a child of the other named nodes in the path. - You will usually just pass a string to [method Node.get_node] and it will be automatically converted, but you may occasionally want to parse a path ahead of time with [NodePath] or the literal syntax [code]@"path"[/code]. Exporting a [NodePath] variable will give you a node selection widget in the properties panel of the editor, which can often be useful. + You will usually just pass a string to [method Node.get_node] and it will be automatically converted, but you may occasionally want to parse a path ahead of time with [NodePath] or the literal syntax [code]^"path"[/code]. Exporting a [NodePath] variable will give you a node selection widget in the properties panel of the editor, which can often be useful. A [NodePath] is composed of a list of slash-separated node names (like a filesystem path) and an optional colon-separated list of "subnames" which can be resources or properties. Some examples of NodePaths include the following: [codeblock] # No leading slash means it is relative to the current node. - @"A" # Immediate child A - @"A/B" # A's child B - @"." # The current node. - @".." # The parent node. - @"../C" # A sibling node C. + ^"A" # Immediate child A + ^"A/B" # A's child B + ^"." # The current node. + ^".." # The parent node. + ^"../C" # A sibling node C. # A leading slash means it is absolute from the SceneTree. - @"/root" # Equivalent to get_tree().get_root(). - @"/root/Main" # If your main scene's root node were named "Main". - @"/root/MyAutoload" # If you have an autoloaded node or scene. + ^"/root" # Equivalent to get_tree().get_root(). + ^"/root/Main" # If your main scene's root node were named "Main". + ^"/root/MyAutoload" # If you have an autoloaded node or scene. [/codeblock] + See also [StringName], which is a similar concept for general-purpose string interning. [b]Note:[/b] In the editor, [NodePath] properties are automatically updated when moving, renaming or deleting a node in the scene tree, but they are never updated at runtime. </description> <tutorials> @@ -36,7 +37,7 @@ <return type="NodePath" /> <argument index="0" name="from" type="NodePath" /> <description> - Constructs a [NodePath] as a copy of the given [NodePath]. + Constructs a [NodePath] as a copy of the given [NodePath]. [code]NodePath("example")[/code] is equivalent to [code]^"example"[/code]. </description> </constructor> <constructor name="NodePath"> @@ -172,22 +173,12 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="NodePath" /> <description> </description> </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="NodePath" /> <description> </description> diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml index f65925f0f6..69e6d4b74c 100644 --- a/doc/classes/OptionButton.xml +++ b/doc/classes/OptionButton.xml @@ -74,6 +74,13 @@ Returns the text of the item at index [code]idx[/code]. </description> </method> + <method name="get_item_tooltip" qualifiers="const"> + <return type="String" /> + <argument index="0" name="idx" type="int" /> + <description> + Returns the tooltip of the item at index [code]idx[/code]. + </description> + </method> <method name="get_popup" qualifiers="const"> <return type="PopupMenu" /> <description> @@ -156,6 +163,14 @@ Sets the text of the item at index [code]idx[/code]. </description> </method> + <method name="set_item_tooltip"> + <return type="void" /> + <argument index="0" name="idx" type="int" /> + <argument index="1" name="tooltip" type="String" /> + <description> + Sets the tooltip of the item at index [code]idx[/code]. + </description> + </method> </methods> <members> <member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" overrides="BaseButton" enum="BaseButton.ActionMode" default="0" /> diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index be51b1dcf8..a0e67bfa63 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -418,11 +418,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedByteArray" /> <description> </description> @@ -435,11 +430,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedByteArray" /> <description> </description> diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml index f98c5c37e4..d1a00b32b1 100644 --- a/doc/classes/PackedColorArray.xml +++ b/doc/classes/PackedColorArray.xml @@ -154,11 +154,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedColorArray" /> <description> </description> @@ -171,11 +166,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedColorArray" /> <description> </description> diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml index 393af5f6c4..b351058346 100644 --- a/doc/classes/PackedFloat32Array.xml +++ b/doc/classes/PackedFloat32Array.xml @@ -157,11 +157,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedFloat32Array" /> <description> </description> @@ -174,11 +169,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedFloat32Array" /> <description> </description> diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml index 5a80d7b2e9..b4ffa295bd 100644 --- a/doc/classes/PackedFloat64Array.xml +++ b/doc/classes/PackedFloat64Array.xml @@ -157,11 +157,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedFloat64Array" /> <description> </description> @@ -174,11 +169,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedFloat64Array" /> <description> </description> diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml index 17085a9626..b34deb518a 100644 --- a/doc/classes/PackedInt32Array.xml +++ b/doc/classes/PackedInt32Array.xml @@ -157,11 +157,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedInt32Array" /> <description> </description> @@ -174,11 +169,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedInt32Array" /> <description> </description> diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml index 066bc05f54..6a99db778c 100644 --- a/doc/classes/PackedInt64Array.xml +++ b/doc/classes/PackedInt64Array.xml @@ -157,11 +157,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedInt64Array" /> <description> </description> @@ -174,11 +169,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedInt64Array" /> <description> </description> diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml index 3cf43ecb28..29c72f62de 100644 --- a/doc/classes/PackedStringArray.xml +++ b/doc/classes/PackedStringArray.xml @@ -155,11 +155,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedStringArray" /> <description> </description> @@ -172,11 +167,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedStringArray" /> <description> </description> diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml index 9abc366702..cd78f29595 100644 --- a/doc/classes/PackedVector2Array.xml +++ b/doc/classes/PackedVector2Array.xml @@ -155,11 +155,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedVector2Array" /> <description> </description> @@ -178,11 +173,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedVector2Array" /> <description> </description> diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml index ff9fc6a757..9ae4073fdf 100644 --- a/doc/classes/PackedVector3Array.xml +++ b/doc/classes/PackedVector3Array.xml @@ -154,11 +154,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="PackedVector3Array" /> <description> </description> @@ -177,11 +172,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="PackedVector3Array" /> <description> </description> diff --git a/doc/classes/PhysicsDirectBodyState3DExtension.xml b/doc/classes/PhysicsDirectBodyState3DExtension.xml new file mode 100644 index 0000000000..f0659f8f1b --- /dev/null +++ b/doc/classes/PhysicsDirectBodyState3DExtension.xml @@ -0,0 +1,260 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsDirectBodyState3DExtension" inherits="PhysicsDirectBodyState3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="_add_constant_central_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="force" type="Vector3" /> + <description> + </description> + </method> + <method name="_add_constant_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="force" type="Vector3" /> + <argument index="1" name="position" type="Vector3" /> + <description> + </description> + </method> + <method name="_add_constant_torque" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="torque" type="Vector3" /> + <description> + </description> + </method> + <method name="_apply_central_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="force" type="Vector3" /> + <description> + </description> + </method> + <method name="_apply_central_impulse" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="impulse" type="Vector3" /> + <description> + </description> + </method> + <method name="_apply_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="force" type="Vector3" /> + <argument index="1" name="position" type="Vector3" /> + <description> + </description> + </method> + <method name="_apply_impulse" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="impulse" type="Vector3" /> + <argument index="1" name="position" type="Vector3" /> + <description> + </description> + </method> + <method name="_apply_torque" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="torque" type="Vector3" /> + <description> + </description> + </method> + <method name="_apply_torque_impulse" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="impulse" type="Vector3" /> + <description> + </description> + </method> + <method name="_get_angular_velocity" qualifiers="virtual const"> + <return type="Vector3" /> + <description> + </description> + </method> + <method name="_get_center_of_mass" qualifiers="virtual const"> + <return type="Vector3" /> + <description> + </description> + </method> + <method name="_get_center_of_mass_local" qualifiers="virtual const"> + <return type="Vector3" /> + <description> + </description> + </method> + <method name="_get_constant_force" qualifiers="virtual const"> + <return type="Vector3" /> + <description> + </description> + </method> + <method name="_get_constant_torque" qualifiers="virtual const"> + <return type="Vector3" /> + <description> + </description> + </method> + <method name="_get_contact_collider" qualifiers="virtual const"> + <return type="RID" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_collider_id" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_collider_object" qualifiers="virtual const"> + <return type="Object" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_collider_position" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_collider_shape" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_collider_velocity_at_position" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_count" qualifiers="virtual const"> + <return type="int" /> + <description> + </description> + </method> + <method name="_get_contact_impulse" qualifiers="virtual const"> + <return type="float" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_local_normal" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_local_position" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_contact_local_shape" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="contact_idx" type="int" /> + <description> + </description> + </method> + <method name="_get_inverse_inertia" qualifiers="virtual const"> + <return type="Vector3" /> + <description> + </description> + </method> + <method name="_get_inverse_mass" qualifiers="virtual const"> + <return type="float" /> + <description> + </description> + </method> + <method name="_get_linear_velocity" qualifiers="virtual const"> + <return type="Vector3" /> + <description> + </description> + </method> + <method name="_get_principal_inertia_axes" qualifiers="virtual const"> + <return type="Basis" /> + <description> + </description> + </method> + <method name="_get_space_state" qualifiers="virtual"> + <return type="PhysicsDirectSpaceState3D" /> + <description> + </description> + </method> + <method name="_get_step" qualifiers="virtual const"> + <return type="float" /> + <description> + </description> + </method> + <method name="_get_total_angular_damp" qualifiers="virtual const"> + <return type="float" /> + <description> + </description> + </method> + <method name="_get_total_gravity" qualifiers="virtual const"> + <return type="Vector3" /> + <description> + </description> + </method> + <method name="_get_total_linear_damp" qualifiers="virtual const"> + <return type="float" /> + <description> + </description> + </method> + <method name="_get_transform" qualifiers="virtual const"> + <return type="Transform3D" /> + <description> + </description> + </method> + <method name="_get_velocity_at_local_position" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="local_position" type="Vector3" /> + <description> + </description> + </method> + <method name="_integrate_forces" qualifiers="virtual"> + <return type="void" /> + <description> + </description> + </method> + <method name="_is_sleeping" qualifiers="virtual const"> + <return type="bool" /> + <description> + </description> + </method> + <method name="_set_angular_velocity" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="velocity" type="Vector3" /> + <description> + </description> + </method> + <method name="_set_constant_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="force" type="Vector3" /> + <description> + </description> + </method> + <method name="_set_constant_torque" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="torque" type="Vector3" /> + <description> + </description> + </method> + <method name="_set_linear_velocity" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="velocity" type="Vector3" /> + <description> + </description> + </method> + <method name="_set_sleep_state" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="enabled" type="bool" /> + <description> + </description> + </method> + <method name="_set_transform" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="transform" type="Transform3D" /> + <description> + </description> + </method> + </methods> +</class> diff --git a/doc/classes/PhysicsDirectSpaceState3DExtension.xml b/doc/classes/PhysicsDirectSpaceState3DExtension.xml new file mode 100644 index 0000000000..f150907963 --- /dev/null +++ b/doc/classes/PhysicsDirectSpaceState3DExtension.xml @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsDirectSpaceState3DExtension" inherits="PhysicsDirectSpaceState3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="_cast_motion" qualifiers="virtual"> + <return type="bool" /> + <argument index="0" name="shape_rid" type="RID" /> + <argument index="1" name="transform" type="Transform3D" /> + <argument index="2" name="motion" type="Vector3" /> + <argument index="3" name="margin" type="float" /> + <argument index="4" name="collision_mask" type="int" /> + <argument index="5" name="collide_with_bodies" type="bool" /> + <argument index="6" name="collide_with_areas" type="bool" /> + <argument index="7" name="closest_safe" type="float*" /> + <argument index="8" name="closest_unsafe" type="float*" /> + <argument index="9" name="info" type="PhysicsServer3DExtensionShapeRestInfo*" /> + <description> + </description> + </method> + <method name="_collide_shape" qualifiers="virtual"> + <return type="bool" /> + <argument index="0" name="shape_rid" type="RID" /> + <argument index="1" name="transform" type="Transform3D" /> + <argument index="2" name="motion" type="Vector3" /> + <argument index="3" name="margin" type="float" /> + <argument index="4" name="collision_mask" type="int" /> + <argument index="5" name="collide_with_bodies" type="bool" /> + <argument index="6" name="collide_with_areas" type="bool" /> + <argument index="7" name="results" type="void*" /> + <argument index="8" name="max_results" type="int" /> + <argument index="9" name="result_count" type="int32_t*" /> + <description> + </description> + </method> + <method name="_get_closest_point_to_object_volume" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="object" type="RID" /> + <argument index="1" name="point" type="Vector3" /> + <description> + </description> + </method> + <method name="_intersect_point" qualifiers="virtual"> + <return type="int" /> + <argument index="0" name="position" type="Vector3" /> + <argument index="1" name="collision_mask" type="int" /> + <argument index="2" name="collide_with_bodies" type="bool" /> + <argument index="3" name="collide_with_areas" type="bool" /> + <argument index="4" name="results" type="PhysicsServer3DExtensionShapeResult*" /> + <argument index="5" name="max_results" type="int" /> + <description> + </description> + </method> + <method name="_intersect_ray" qualifiers="virtual"> + <return type="bool" /> + <argument index="0" name="from" type="Vector3" /> + <argument index="1" name="to" type="Vector3" /> + <argument index="2" name="collision_mask" type="int" /> + <argument index="3" name="collide_with_bodies" type="bool" /> + <argument index="4" name="collide_with_areas" type="bool" /> + <argument index="5" name="hit_from_inside" type="bool" /> + <argument index="6" name="hit_back_faces" type="bool" /> + <argument index="7" name="result" type="PhysicsServer3DExtensionRayResult*" /> + <description> + </description> + </method> + <method name="_intersect_shape" qualifiers="virtual"> + <return type="int" /> + <argument index="0" name="shape_rid" type="RID" /> + <argument index="1" name="transform" type="Transform3D" /> + <argument index="2" name="motion" type="Vector3" /> + <argument index="3" name="margin" type="float" /> + <argument index="4" name="collision_mask" type="int" /> + <argument index="5" name="collide_with_bodies" type="bool" /> + <argument index="6" name="collide_with_areas" type="bool" /> + <argument index="7" name="result_count" type="PhysicsServer3DExtensionShapeResult*" /> + <argument index="8" name="max_results" type="int" /> + <description> + </description> + </method> + <method name="_rest_info" qualifiers="virtual"> + <return type="bool" /> + <argument index="0" name="shape_rid" type="RID" /> + <argument index="1" name="transform" type="Transform3D" /> + <argument index="2" name="motion" type="Vector3" /> + <argument index="3" name="margin" type="float" /> + <argument index="4" name="collision_mask" type="int" /> + <argument index="5" name="collide_with_bodies" type="bool" /> + <argument index="6" name="collide_with_areas" type="bool" /> + <argument index="7" name="rest_info" type="PhysicsServer3DExtensionShapeRestInfo*" /> + <description> + </description> + </method> + </methods> +</class> diff --git a/doc/classes/PhysicsServer3DExtension.xml b/doc/classes/PhysicsServer3DExtension.xml new file mode 100644 index 0000000000..795f5b86dd --- /dev/null +++ b/doc/classes/PhysicsServer3DExtension.xml @@ -0,0 +1,897 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsServer3DExtension" inherits="PhysicsServer3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="_area_add_shape" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="shape" type="RID" /> + <argument index="2" name="transform" type="Transform3D" /> + <argument index="3" name="disabled" type="bool" /> + <description> + </description> + </method> + <method name="_area_attach_object_instance_id" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="id" type="int" /> + <description> + </description> + </method> + <method name="_area_clear_shapes" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <description> + </description> + </method> + <method name="_area_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_area_get_object_instance_id" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="area" type="RID" /> + <description> + </description> + </method> + <method name="_area_get_param" qualifiers="virtual const"> + <return type="Variant" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.AreaParameter" /> + <description> + </description> + </method> + <method name="_area_get_shape" qualifiers="virtual const"> + <return type="RID" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <description> + </description> + </method> + <method name="_area_get_shape_count" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="area" type="RID" /> + <description> + </description> + </method> + <method name="_area_get_shape_transform" qualifiers="virtual const"> + <return type="Transform3D" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <description> + </description> + </method> + <method name="_area_get_space" qualifiers="virtual const"> + <return type="RID" /> + <argument index="0" name="area" type="RID" /> + <description> + </description> + </method> + <method name="_area_get_transform" qualifiers="virtual const"> + <return type="Transform3D" /> + <argument index="0" name="area" type="RID" /> + <description> + </description> + </method> + <method name="_area_remove_shape" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <description> + </description> + </method> + <method name="_area_set_area_monitor_callback" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="callback" type="Callable" /> + <description> + </description> + </method> + <method name="_area_set_collision_layer" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="layer" type="int" /> + <description> + </description> + </method> + <method name="_area_set_collision_mask" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="mask" type="int" /> + <description> + </description> + </method> + <method name="_area_set_monitor_callback" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="callback" type="Callable" /> + <description> + </description> + </method> + <method name="_area_set_monitorable" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="monitorable" type="bool" /> + <description> + </description> + </method> + <method name="_area_set_param" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.AreaParameter" /> + <argument index="2" name="value" type="Variant" /> + <description> + </description> + </method> + <method name="_area_set_ray_pickable" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="enable" type="bool" /> + <description> + </description> + </method> + <method name="_area_set_shape" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <argument index="2" name="shape" type="RID" /> + <description> + </description> + </method> + <method name="_area_set_shape_disabled" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <argument index="2" name="disabled" type="bool" /> + <description> + </description> + </method> + <method name="_area_set_shape_transform" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <argument index="2" name="transform" type="Transform3D" /> + <description> + </description> + </method> + <method name="_area_set_space" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="space" type="RID" /> + <description> + </description> + </method> + <method name="_area_set_transform" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="area" type="RID" /> + <argument index="1" name="transform" type="Transform3D" /> + <description> + </description> + </method> + <method name="_body_add_collision_exception" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="excepted_body" type="RID" /> + <description> + </description> + </method> + <method name="_body_add_constant_central_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="force" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_add_constant_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="force" type="Vector3" /> + <argument index="2" name="position" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_add_constant_torque" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="torque" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_add_shape" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="shape" type="RID" /> + <argument index="2" name="transform" type="Transform3D" /> + <argument index="3" name="disabled" type="bool" /> + <description> + </description> + </method> + <method name="_body_apply_central_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="force" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_apply_central_impulse" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="impulse" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_apply_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="force" type="Vector3" /> + <argument index="2" name="position" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_apply_impulse" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="impulse" type="Vector3" /> + <argument index="2" name="position" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_apply_torque" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="torque" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_apply_torque_impulse" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="impulse" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_attach_object_instance_id" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="id" type="int" /> + <description> + </description> + </method> + <method name="_body_clear_shapes" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_body_get_collision_layer" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_collision_mask" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_constant_force" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_constant_torque" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_direct_state" qualifiers="virtual"> + <return type="PhysicsDirectBodyState3D" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_max_contacts_reported" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_mode" qualifiers="virtual const"> + <return type="int" enum="PhysicsServer3D.BodyMode" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_object_instance_id" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_param" qualifiers="virtual const"> + <return type="Variant" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.BodyParameter" /> + <description> + </description> + </method> + <method name="_body_get_shape" qualifiers="virtual const"> + <return type="RID" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <description> + </description> + </method> + <method name="_body_get_shape_count" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_shape_transform" qualifiers="virtual const"> + <return type="Transform3D" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <description> + </description> + </method> + <method name="_body_get_space" qualifiers="virtual const"> + <return type="RID" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_get_state" qualifiers="virtual const"> + <return type="Variant" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="state" type="int" enum="PhysicsServer3D.BodyState" /> + <description> + </description> + </method> + <method name="_body_is_axis_locked" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="axis" type="int" enum="PhysicsServer3D.BodyAxis" /> + <description> + </description> + </method> + <method name="_body_is_continuous_collision_detection_enabled" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_is_omitting_force_integration" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_remove_collision_exception" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="excepted_body" type="RID" /> + <description> + </description> + </method> + <method name="_body_remove_shape" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <description> + </description> + </method> + <method name="_body_reset_mass_properties" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_body_set_axis_lock" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="axis" type="int" enum="PhysicsServer3D.BodyAxis" /> + <argument index="2" name="lock" type="bool" /> + <description> + </description> + </method> + <method name="_body_set_axis_velocity" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="axis_velocity" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_set_collision_layer" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="layer" type="int" /> + <description> + </description> + </method> + <method name="_body_set_collision_mask" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="mask" type="int" /> + <description> + </description> + </method> + <method name="_body_set_constant_force" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="force" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_set_constant_torque" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="torque" type="Vector3" /> + <description> + </description> + </method> + <method name="_body_set_enable_continuous_collision_detection" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="enable" type="bool" /> + <description> + </description> + </method> + <method name="_body_set_force_integration_callback" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="callable" type="Callable" /> + <argument index="2" name="userdata" type="Variant" /> + <description> + </description> + </method> + <method name="_body_set_max_contacts_reported" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="amount" type="int" /> + <description> + </description> + </method> + <method name="_body_set_mode" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="mode" type="int" enum="PhysicsServer3D.BodyMode" /> + <description> + </description> + </method> + <method name="_body_set_omit_force_integration" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="enable" type="bool" /> + <description> + </description> + </method> + <method name="_body_set_param" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.BodyParameter" /> + <argument index="2" name="value" type="Variant" /> + <description> + </description> + </method> + <method name="_body_set_ray_pickable" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="enable" type="bool" /> + <description> + </description> + </method> + <method name="_body_set_shape" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <argument index="2" name="shape" type="RID" /> + <description> + </description> + </method> + <method name="_body_set_shape_disabled" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <argument index="2" name="disabled" type="bool" /> + <description> + </description> + </method> + <method name="_body_set_shape_transform" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="shape_idx" type="int" /> + <argument index="2" name="transform" type="Transform3D" /> + <description> + </description> + </method> + <method name="_body_set_space" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="space" type="RID" /> + <description> + </description> + </method> + <method name="_body_set_state" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="state" type="int" enum="PhysicsServer3D.BodyState" /> + <argument index="2" name="value" type="Variant" /> + <description> + </description> + </method> + <method name="_body_test_motion" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="body" type="RID" /> + <argument index="1" name="from" type="Transform3D" /> + <argument index="2" name="motion" type="Vector3" /> + <argument index="3" name="margin" type="float" /> + <argument index="4" name="max_collisions" type="int" /> + <argument index="5" name="collide_separation_ray" type="bool" /> + <argument index="6" name="result" type="PhysicsServer3DExtensionMotionResult*" /> + <description> + </description> + </method> + <method name="_box_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_capsule_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_concave_polygon_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_cone_twist_joint_get_param" qualifiers="virtual const"> + <return type="float" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.ConeTwistJointParam" /> + <description> + </description> + </method> + <method name="_cone_twist_joint_set_param" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.ConeTwistJointParam" /> + <argument index="2" name="value" type="float" /> + <description> + </description> + </method> + <method name="_convex_polygon_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_custom_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_cylinder_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_free_rid" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="rid" type="RID" /> + <description> + </description> + </method> + <method name="_generic_6dof_joint_get_flag" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="axis" type="int" enum="Vector3.Axis" /> + <argument index="2" name="flag" type="int" enum="PhysicsServer3D.G6DOFJointAxisFlag" /> + <description> + </description> + </method> + <method name="_generic_6dof_joint_get_param" qualifiers="virtual const"> + <return type="float" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="axis" type="int" enum="Vector3.Axis" /> + <argument index="2" name="param" type="int" enum="PhysicsServer3D.G6DOFJointAxisParam" /> + <description> + </description> + </method> + <method name="_generic_6dof_joint_set_flag" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="axis" type="int" enum="Vector3.Axis" /> + <argument index="2" name="flag" type="int" enum="PhysicsServer3D.G6DOFJointAxisFlag" /> + <argument index="3" name="enable" type="bool" /> + <description> + </description> + </method> + <method name="_generic_6dof_joint_set_param" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="axis" type="int" enum="Vector3.Axis" /> + <argument index="2" name="param" type="int" enum="PhysicsServer3D.G6DOFJointAxisParam" /> + <argument index="3" name="value" type="float" /> + <description> + </description> + </method> + <method name="_get_process_info" qualifiers="virtual"> + <return type="int" /> + <argument index="0" name="process_info" type="int" enum="PhysicsServer3D.ProcessInfo" /> + <description> + </description> + </method> + <method name="_heightmap_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_hinge_joint_get_flag" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="flag" type="int" enum="PhysicsServer3D.HingeJointFlag" /> + <description> + </description> + </method> + <method name="_hinge_joint_get_param" qualifiers="virtual const"> + <return type="float" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.HingeJointParam" /> + <description> + </description> + </method> + <method name="_hinge_joint_set_flag" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="flag" type="int" enum="PhysicsServer3D.HingeJointFlag" /> + <argument index="2" name="enabled" type="bool" /> + <description> + </description> + </method> + <method name="_hinge_joint_set_param" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.HingeJointParam" /> + <argument index="2" name="value" type="float" /> + <description> + </description> + </method> + <method name="_joint_clear" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <description> + </description> + </method> + <method name="_joint_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_joint_get_solver_priority" qualifiers="virtual const"> + <return type="int" /> + <argument index="0" name="joint" type="RID" /> + <description> + </description> + </method> + <method name="_joint_get_type" qualifiers="virtual const"> + <return type="int" enum="PhysicsServer3D.JointType" /> + <argument index="0" name="joint" type="RID" /> + <description> + </description> + </method> + <method name="_joint_make_cone_twist" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="body_A" type="RID" /> + <argument index="2" name="local_ref_A" type="Transform3D" /> + <argument index="3" name="body_B" type="RID" /> + <argument index="4" name="local_ref_B" type="Transform3D" /> + <description> + </description> + </method> + <method name="_joint_make_generic_6dof" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="body_A" type="RID" /> + <argument index="2" name="local_ref_A" type="Transform3D" /> + <argument index="3" name="body_B" type="RID" /> + <argument index="4" name="local_ref_B" type="Transform3D" /> + <description> + </description> + </method> + <method name="_joint_make_hinge" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="body_A" type="RID" /> + <argument index="2" name="hinge_A" type="Transform3D" /> + <argument index="3" name="body_B" type="RID" /> + <argument index="4" name="hinge_B" type="Transform3D" /> + <description> + </description> + </method> + <method name="_joint_make_pin" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="body_A" type="RID" /> + <argument index="2" name="local_A" type="Vector3" /> + <argument index="3" name="body_B" type="RID" /> + <argument index="4" name="local_B" type="Vector3" /> + <description> + </description> + </method> + <method name="_joint_make_slider" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="body_A" type="RID" /> + <argument index="2" name="local_ref_A" type="Transform3D" /> + <argument index="3" name="body_B" type="RID" /> + <argument index="4" name="local_ref_B" type="Transform3D" /> + <description> + </description> + </method> + <method name="_joint_set_solver_priority" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="priority" type="int" /> + <description> + </description> + </method> + <method name="_pin_joint_get_local_a" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="joint" type="RID" /> + <description> + </description> + </method> + <method name="_pin_joint_get_local_b" qualifiers="virtual const"> + <return type="Vector3" /> + <argument index="0" name="joint" type="RID" /> + <description> + </description> + </method> + <method name="_pin_joint_get_param" qualifiers="virtual const"> + <return type="float" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.PinJointParam" /> + <description> + </description> + </method> + <method name="_pin_joint_set_local_a" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="local_A" type="Vector3" /> + <description> + </description> + </method> + <method name="_pin_joint_set_local_b" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="local_B" type="Vector3" /> + <description> + </description> + </method> + <method name="_pin_joint_set_param" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.PinJointParam" /> + <argument index="2" name="value" type="float" /> + <description> + </description> + </method> + <method name="_separation_ray_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_set_active" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="active" type="bool" /> + <description> + </description> + </method> + <method name="_shape_get_data" qualifiers="virtual const"> + <return type="Variant" /> + <argument index="0" name="shape" type="RID" /> + <description> + </description> + </method> + <method name="_shape_get_type" qualifiers="virtual const"> + <return type="int" enum="PhysicsServer3D.ShapeType" /> + <argument index="0" name="shape" type="RID" /> + <description> + </description> + </method> + <method name="_shape_set_data" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="shape" type="RID" /> + <argument index="1" name="data" type="Variant" /> + <description> + </description> + </method> + <method name="_slider_joint_get_param" qualifiers="virtual const"> + <return type="float" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.SliderJointParam" /> + <description> + </description> + </method> + <method name="_slider_joint_set_param" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="joint" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.SliderJointParam" /> + <argument index="2" name="value" type="float" /> + <description> + </description> + </method> + <method name="_soft_body_get_bounds" qualifiers="virtual const"> + <return type="AABB" /> + <argument index="0" name="body" type="RID" /> + <description> + </description> + </method> + <method name="_space_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_space_get_direct_state" qualifiers="virtual"> + <return type="PhysicsDirectSpaceState3D" /> + <argument index="0" name="space" type="RID" /> + <description> + </description> + </method> + <method name="_space_get_param" qualifiers="virtual const"> + <return type="float" /> + <argument index="0" name="space" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.SpaceParameter" /> + <description> + </description> + </method> + <method name="_space_is_active" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="space" type="RID" /> + <description> + </description> + </method> + <method name="_space_set_active" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="space" type="RID" /> + <argument index="1" name="active" type="bool" /> + <description> + </description> + </method> + <method name="_space_set_param" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="space" type="RID" /> + <argument index="1" name="param" type="int" enum="PhysicsServer3D.SpaceParameter" /> + <argument index="2" name="value" type="float" /> + <description> + </description> + </method> + <method name="_sphere_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + <method name="_world_boundary_shape_create" qualifiers="virtual"> + <return type="RID" /> + <description> + </description> + </method> + </methods> +</class> diff --git a/doc/classes/PhysicsServer3DRenderingServerHandler.xml b/doc/classes/PhysicsServer3DRenderingServerHandler.xml new file mode 100644 index 0000000000..a40a2dd1c6 --- /dev/null +++ b/doc/classes/PhysicsServer3DRenderingServerHandler.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PhysicsServer3DRenderingServerHandler" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="_set_aabb" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="aabb" type="AABB" /> + <description> + </description> + </method> + <method name="_set_normal" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="vertex_id" type="int" /> + <argument index="1" name="normals" type="const void*" /> + <description> + </description> + </method> + <method name="_set_vertex" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="vertex_id" type="int" /> + <argument index="1" name="vertices" type="const void*" /> + <description> + </description> + </method> + </methods> +</class> diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml index f037b0bf1e..a42ceba777 100644 --- a/doc/classes/Plane.xml +++ b/doc/classes/Plane.xml @@ -173,11 +173,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Plane" /> <description> Returns [code]true[/code] if the planes are not equal. @@ -186,11 +181,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Plane" /> <description> Returns [code]true[/code] if the planes are exactly equal. diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index b64c392357..4bcfc3c726 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -7,6 +7,7 @@ [PopupMenu] is a modal window used to display a list of options. They are popular in toolbars or context menus. The size of a [PopupMenu] can be limited by using [member Window.max_size]. If the height of the list of items is larger than the maximum height of the [PopupMenu], a [ScrollContainer] within the popup will allow the user to scroll the contents. If no maximum size is set, or if it is set to 0, the [PopupMenu] height will be limited by its parent rect. + All [code]set_*[/code] methods allow negative item index, which makes the item accessed from the last one. </description> <tutorials> </tutorials> diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml index 329d81342b..7046a21f68 100644 --- a/doc/classes/PrimitiveMesh.xml +++ b/doc/classes/PrimitiveMesh.xml @@ -34,10 +34,10 @@ </method> </methods> <members> - <member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB(0, 0, 0, 0, 0, 0)"> + <member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb"> Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices. </member> - <member name="flip_faces" type="bool" setter="set_flip_faces" getter="get_flip_faces" default="false"> + <member name="flip_faces" type="bool" setter="set_flip_faces" getter="get_flip_faces"> If set, the order of the vertices in each triangle are reversed resulting in the backside of the mesh being drawn. This gives the same result as using [constant BaseMaterial3D.CULL_FRONT] in [member BaseMaterial3D.cull_mode]. </member> diff --git a/doc/classes/ProceduralSkyMaterial.xml b/doc/classes/ProceduralSkyMaterial.xml index 2b15508119..bf33232406 100644 --- a/doc/classes/ProceduralSkyMaterial.xml +++ b/doc/classes/ProceduralSkyMaterial.xml @@ -23,6 +23,12 @@ <member name="ground_horizon_color" type="Color" setter="set_ground_horizon_color" getter="get_ground_horizon_color" default="Color(0.6463, 0.6558, 0.6708, 1)"> Color of the ground at the horizon. Blends with [member ground_bottom_color]. </member> + <member name="sky_cover" type="Texture2D" setter="set_sky_cover" getter="get_sky_cover"> + The sky cover texture to use. This texture must use an equirectangular projection (similar to [PanoramaSkyMaterial]). The texture's colors will be [i]added[/i] to the existing sky color, and will be multiplied by [member sky_energy] and [member sky_cover_modulate]. This is mainly suited to displaying stars at night, but it can also be used to display clouds at day or night (with a non-physically-accurate look). + </member> + <member name="sky_cover_modulate" type="Color" setter="set_sky_cover_modulate" getter="get_sky_cover_modulate" default="Color(1, 1, 1, 1)"> + The tint to apply to the [member sky_cover] texture. This can be used to change the sky cover's colors or opacity independently of the sky energy, which is useful for day/night or weather transitions. Only effective if a texture is defined in [member sky_cover]. + </member> <member name="sky_curve" type="float" setter="set_sky_curve" getter="get_sky_curve" default="0.15"> How quickly the [member sky_horizon_color] fades into the [member sky_top_color]. </member> diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml index 60b66a2493..1e9ab7c375 100644 --- a/doc/classes/ProgressBar.xml +++ b/doc/classes/ProgressBar.xml @@ -12,8 +12,6 @@ <member name="percent_visible" type="bool" setter="set_percent_visible" getter="is_percent_visible" default="true"> If [code]true[/code], the fill percentage is displayed on the bar. </member> - <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" /> - <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="0.01" /> </members> <theme_items> <theme_item name="font_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 701e947fd1..068b2c7757 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -226,6 +226,9 @@ The project's name. It is used both by the Project Manager and by exporters. The project name can be translated by translating its value in localization files. The window title will be set to match the project name automatically on startup. [b]Note:[/b] Changing this value will also change the user data folder's path if [member application/config/use_custom_user_dir] is [code]false[/code]. After renaming the project, you will no longer be able to access existing data in [code]user://[/code] unless you rename the old folder to match the new project name. See [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] in the documentation for more information. </member> + <member name="application/config/name_localized" type="Dictionary" setter="" getter="" default="{}"> + Translations of the project's name. This setting is used by OS tools to translate application name on Android, iOS and macOS. + </member> <member name="application/config/project_settings_override" type="String" setter="" getter="" default=""""> Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code]. See "Overriding" in the [ProjectSettings] class description at the top for more information. [b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings. diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml index b962cf35cb..48e6317b11 100644 --- a/doc/classes/Quaternion.xml +++ b/doc/classes/Quaternion.xml @@ -198,11 +198,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Quaternion" /> <description> Returns [code]true[/code] if the quaternions are not equal. @@ -267,11 +262,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Quaternion" /> <description> Returns [code]true[/code] if the quaternions are exactly equal. diff --git a/doc/classes/RID.xml b/doc/classes/RID.xml index 6888c1f56c..39be605e1b 100644 --- a/doc/classes/RID.xml +++ b/doc/classes/RID.xml @@ -40,11 +40,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="RID" /> <description> </description> @@ -63,11 +58,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="RID" /> <description> </description> diff --git a/doc/classes/Range.xml b/doc/classes/Range.xml index c150198eb1..9743d969ca 100644 --- a/doc/classes/Range.xml +++ b/doc/classes/Range.xml @@ -13,51 +13,52 @@ <return type="void" /> <argument index="0" name="" type="float" /> <description> + Called when the [Range]'s value is changed (following the same conditions as [signal value_changed]). </description> </method> <method name="share"> <return type="void" /> <argument index="0" name="with" type="Node" /> <description> - Binds two ranges together along with any ranges previously grouped with either of them. When any of range's member variables change, it will share the new value with all other ranges in its group. + Binds two [Range]s together along with any ranges previously grouped with either of them. When any of range's member variables change, it will share the new value with all other ranges in its group. </description> </method> <method name="unshare"> <return type="void" /> <description> - Stops range from sharing its member variables with any other. + Stops the [Range] from sharing its member variables with any other. </description> </method> </methods> <members> - <member name="allow_greater" type="bool" setter="set_allow_greater" getter="is_greater_allowed" default="false"> + <member name="allow_greater" type="bool" setter="set_allow_greater" getter="is_greater_allowed"> If [code]true[/code], [member value] may be greater than [member max_value]. </member> - <member name="allow_lesser" type="bool" setter="set_allow_lesser" getter="is_lesser_allowed" default="false"> + <member name="allow_lesser" type="bool" setter="set_allow_lesser" getter="is_lesser_allowed"> If [code]true[/code], [member value] may be less than [member min_value]. </member> - <member name="exp_edit" type="bool" setter="set_exp_ratio" getter="is_ratio_exp" default="false"> + <member name="exp_edit" type="bool" setter="set_exp_ratio" getter="is_ratio_exp"> If [code]true[/code], and [code]min_value[/code] is greater than 0, [code]value[/code] will be represented exponentially rather than linearly. </member> - <member name="max_value" type="float" setter="set_max" getter="get_max" default="100.0"> + <member name="max_value" type="float" setter="set_max" getter="get_max"> Maximum value. Range is clamped if [code]value[/code] is greater than [code]max_value[/code]. </member> - <member name="min_value" type="float" setter="set_min" getter="get_min" default="0.0"> + <member name="min_value" type="float" setter="set_min" getter="get_min"> Minimum value. Range is clamped if [code]value[/code] is less than [code]min_value[/code]. </member> - <member name="page" type="float" setter="set_page" getter="get_page" default="0.0"> + <member name="page" type="float" setter="set_page" getter="get_page"> Page size. Used mainly for [ScrollBar]. ScrollBar's length is its size multiplied by [code]page[/code] over the difference between [code]min_value[/code] and [code]max_value[/code]. </member> <member name="ratio" type="float" setter="set_as_ratio" getter="get_as_ratio"> The value mapped between 0 and 1. </member> - <member name="rounded" type="bool" setter="set_use_rounded_values" getter="is_using_rounded_values" default="false"> + <member name="rounded" type="bool" setter="set_use_rounded_values" getter="is_using_rounded_values"> If [code]true[/code], [code]value[/code] will always be rounded to the nearest integer. </member> - <member name="step" type="float" setter="set_step" getter="get_step" default="1.0"> + <member name="step" type="float" setter="set_step" getter="get_step"> If greater than 0, [code]value[/code] will always be rounded to a multiple of [code]step[/code]. If [code]rounded[/code] is also [code]true[/code], [code]value[/code] will first be rounded to a multiple of [code]step[/code] then rounded to the nearest integer. </member> - <member name="value" type="float" setter="set_value" getter="get_value" default="0.0"> + <member name="value" type="float" setter="set_value" getter="get_value"> Range's current value. </member> </members> @@ -70,7 +71,8 @@ <signal name="value_changed"> <argument index="0" name="value" type="float" /> <description> - Emitted when [member value] changes. + Emitted when [member value] changes. When used on a [Slider], this is called continuously while dragging (potentially every frame). If you are performing an expensive operation in a function connected to [signal value_changed], consider using a [i]debouncing[/i] [Timer] to call the function less often. + [b]Note:[/b] Unlike signals such as [signal LineEdit.text_changed], [signal value_changed] is also emitted when [code]value[/code] is set directly via code. </description> </signal> </signals> diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml index a975382bfa..e4b66a9d53 100644 --- a/doc/classes/Rect2.xml +++ b/doc/classes/Rect2.xml @@ -189,11 +189,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Rect2" /> <description> Returns [code]true[/code] if the rectangles are not equal. @@ -209,11 +204,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Rect2" /> <description> Returns [code]true[/code] if the rectangles are exactly equal. diff --git a/doc/classes/Rect2i.xml b/doc/classes/Rect2i.xml index 49fdd8e7e8..c9ae685a15 100644 --- a/doc/classes/Rect2i.xml +++ b/doc/classes/Rect2i.xml @@ -178,11 +178,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Rect2i" /> <description> Returns [code]true[/code] if the rectangles are not equal. @@ -190,11 +185,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Rect2i" /> <description> Returns [code]true[/code] if the rectangles are equal. diff --git a/doc/classes/RectangleShape2D.xml b/doc/classes/RectangleShape2D.xml index cc3da8a789..124d752ae0 100644 --- a/doc/classes/RectangleShape2D.xml +++ b/doc/classes/RectangleShape2D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RectangleShape2D" inherits="Shape2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Rectangle shape for 2D collisions. + Rectangle shape resource for 2D physics. </brief_description> <description> - Rectangle shape for 2D collisions. This shape is useful for modeling box-like 2D objects. + 2D rectangle shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. This shape is useful for modeling box-like 2D objects. + [b]Performance:[/b] Being a primitive collision shape, [RectangleShape2D] is fast to check collisions against (though not as fast as [CircleShape2D]). </description> <tutorials> <link title="2D Pong Demo">https://godotengine.org/asset-library/asset/121</link> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 50990b5320..213dafa074 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -149,6 +149,17 @@ Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method. </description> </method> + <method name="canvas_item_add_animation_slice"> + <return type="void" /> + <argument index="0" name="item" type="RID" /> + <argument index="1" name="animation_length" type="float" /> + <argument index="2" name="slice_begin" type="float" /> + <argument index="3" name="slice_end" type="float" /> + <argument index="4" name="offset" type="float" default="0.0" /> + <description> + Subsequent drawing commands will be ignored unless they fall within the specified animation slice. This is a faster way to implement animations that loop on background rather than redrawing constantly. + </description> + </method> <method name="canvas_item_add_circle"> <return type="void" /> <argument index="0" name="item" type="RID" /> diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml index 983a05800f..36b64f5a86 100644 --- a/doc/classes/ResourceFormatLoader.xml +++ b/doc/classes/ResourceFormatLoader.xml @@ -6,7 +6,7 @@ <description> Godot loads resources in the editor or in exported games using ResourceFormatLoaders. They are queried automatically via the [ResourceLoader] singleton, or when a resource with internal dependencies is loaded. Each file type may load as a different resource type, so multiple ResourceFormatLoaders are registered in the engine. Extending this class allows you to define your own loader. Be sure to respect the documented return types and values. You should give it a global class name with [code]class_name[/code] for it to be registered. Like built-in ResourceFormatLoaders, it will be called automatically when loading resources of its handled type(s). You may also implement a [ResourceFormatSaver]. - [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([CompressedTexture2D]) first, so they can be loaded with better efficiency on the graphics card. + [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].ctex[/code] ([CompressedTexture2D]) first, so they can be loaded with better efficiency on the graphics card. </description> <tutorials> </tutorials> diff --git a/doc/classes/ScrollBar.xml b/doc/classes/ScrollBar.xml index 266787c9c8..d0dd69408e 100644 --- a/doc/classes/ScrollBar.xml +++ b/doc/classes/ScrollBar.xml @@ -12,8 +12,6 @@ <member name="custom_step" type="float" setter="set_custom_step" getter="get_custom_step" default="-1.0"> Overrides the step used when clicking increment and decrement buttons or when using arrow keys when the [ScrollBar] is focused. </member> - <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" /> - <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="0.0" /> </members> <signals> <signal name="scrolling"> diff --git a/doc/classes/SegmentShape2D.xml b/doc/classes/SegmentShape2D.xml index 8109886262..a1809301e5 100644 --- a/doc/classes/SegmentShape2D.xml +++ b/doc/classes/SegmentShape2D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SegmentShape2D" inherits="Shape2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Segment shape for 2D collisions. + Segment shape resource for 2D physics. </brief_description> <description> - Segment shape for 2D collisions. Consists of two points, [code]a[/code] and [code]b[/code]. + 2D segment shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. Consists of two points, [code]a[/code] and [code]b[/code]. + [b]Performance:[/b] Being a primitive collision shape, [SegmentShape2D] is fast to check collisions against (though not as fast as [CircleShape2D]). </description> <tutorials> </tutorials> diff --git a/doc/classes/SeparationRayShape2D.xml b/doc/classes/SeparationRayShape2D.xml index 3e7a2857bf..d67c7b4cd9 100644 --- a/doc/classes/SeparationRayShape2D.xml +++ b/doc/classes/SeparationRayShape2D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SeparationRayShape2D" inherits="Shape2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Separation ray shape for 2D collisions. + Separation ray shape resource for 2D physics. </brief_description> <description> - Separation ray shape for 2D collisions. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + 2D separation ray shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + [b]Performance:[/b] Being a primitive collision shape, [SeparationRayShape2D] is fast to check collisions against. </description> <tutorials> </tutorials> diff --git a/doc/classes/SeparationRayShape3D.xml b/doc/classes/SeparationRayShape3D.xml index 028c3ba511..0fb4a07457 100644 --- a/doc/classes/SeparationRayShape3D.xml +++ b/doc/classes/SeparationRayShape3D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SeparationRayShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Separation ray shape for 3D collisions. + Separation ray shape resource for 3D physics. </brief_description> <description> - Separation ray shape for 3D collisions, which can be set into a [PhysicsBody3D] or [Area3D]. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + 3D separation ray shape to be added as a [i]direct[/i] child of a [PhysicsBody3D] or [Area3D] using a [CollisionShape3D] node. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + [b]Performance:[/b] Being a primitive collision shape, [SeparationRayShape3D] is fast to check collisions against. </description> <tutorials> </tutorials> diff --git a/doc/classes/Signal.xml b/doc/classes/Signal.xml index 1b67900607..c5855e30a4 100644 --- a/doc/classes/Signal.xml +++ b/doc/classes/Signal.xml @@ -99,22 +99,12 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Signal" /> <description> </description> </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Signal" /> <description> </description> diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml index 03f20b0aab..4139530db1 100644 --- a/doc/classes/Slider.xml +++ b/doc/classes/Slider.xml @@ -13,11 +13,9 @@ <member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true"> If [code]true[/code], the slider can be interacted with. If [code]false[/code], the value can be changed only by code. </member> - <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" /> <member name="scrollable" type="bool" setter="set_scrollable" getter="is_scrollable" default="true"> If [code]true[/code], the value can be changed using the mouse wheel. </member> - <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" /> <member name="tick_count" type="int" setter="set_ticks" getter="get_ticks" default="0"> Number of ticks displayed on the slider, including border ticks. Ticks are uniformly-distributed value markers. </member> diff --git a/doc/classes/SphereShape3D.xml b/doc/classes/SphereShape3D.xml index b5e9c9069b..63084f024e 100644 --- a/doc/classes/SphereShape3D.xml +++ b/doc/classes/SphereShape3D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SphereShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Sphere shape for 3D collisions. + Sphere shape resource for 3D collisions. </brief_description> <description> - Sphere shape for 3D collisions, which can be set into a [PhysicsBody3D] or [Area3D]. This shape is useful for modeling sphere-like 3D objects. + 3D sphere shape to be added as a [i]direct[/i] child of a [PhysicsBody3D] or [Area3D] using a [CollisionShape3D] node. This shape is useful for modeling sphere-like 3D objects. + [b]Performance:[/b] Being a primitive collision shape, [SphereShape3D] is the fastest collision shape to check collisions against, as it only requires a distance check with the shape's origin. </description> <tutorials> <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index d85e521f08..ea0bd2adb1 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -865,11 +865,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="String" /> <description> </description> @@ -906,11 +901,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="String" /> <description> </description> diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml index c19fce9944..ffa1227500 100644 --- a/doc/classes/StringName.xml +++ b/doc/classes/StringName.xml @@ -4,7 +4,9 @@ An optimized string type for unique names. </brief_description> <description> - [StringName]s are immutable strings designed for general-purpose representation of unique names. [StringName] ensures that only one instance of a given name exists (so two [StringName]s with the same value are the same object). Comparing them is much faster than with regular [String]s, because only the pointers are compared, not the whole strings. + [StringName]s are immutable strings designed for general-purpose representation of unique names (also called "string interning"). [StringName] ensures that only one instance of a given name exists (so two [StringName]s with the same value are the same object). Comparing them is much faster than with regular [String]s, because only the pointers are compared, not the whole strings. + You will usually just pass a [String] to methods expecting a [StringName] and it will be automatically converted, but you may occasionally want to construct a [StringName] ahead of time with [StringName] or the literal syntax [code]&"example"[/code]. + See also [NodePath], which is a similar concept specifically designed to store pre-parsed node paths. </description> <tutorials> </tutorials> @@ -26,18 +28,13 @@ <return type="StringName" /> <argument index="0" name="from" type="String" /> <description> - Creates a new [StringName] from the given [String]. + Creates a new [StringName] from the given [String]. [code]StringName("example")[/code] is equivalent to [code]&"example"[/code]. </description> </constructor> </constructors> <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="String" /> <description> </description> @@ -62,11 +59,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="String" /> <description> </description> diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml index bc2333f26a..74d02a84fd 100644 --- a/doc/classes/StyleBox.xml +++ b/doc/classes/StyleBox.xml @@ -107,21 +107,21 @@ </method> </methods> <members> - <member name="content_margin_bottom" type="float" setter="set_default_margin" getter="get_default_margin" default="-1.0"> + <member name="content_margin_bottom" type="float" setter="set_default_margin" getter="get_default_margin"> The bottom margin for the contents of this style box. Increasing this value reduces the space available to the contents from the bottom. If this value is negative, it is ignored and a child-specific margin is used instead. For example for [StyleBoxFlat] the border thickness (if any) is used instead. It is up to the code using this style box to decide what these contents are: for example, a [Button] respects this content margin for the textual contents of the button. [method get_margin] should be used to fetch this value as consumer instead of reading these properties directly. This is because it correctly respects negative values and the fallback mentioned above. </member> - <member name="content_margin_left" type="float" setter="set_default_margin" getter="get_default_margin" default="-1.0"> + <member name="content_margin_left" type="float" setter="set_default_margin" getter="get_default_margin"> The left margin for the contents of this style box. Increasing this value reduces the space available to the contents from the left. Refer to [member content_margin_bottom] for extra considerations. </member> - <member name="content_margin_right" type="float" setter="set_default_margin" getter="get_default_margin" default="-1.0"> + <member name="content_margin_right" type="float" setter="set_default_margin" getter="get_default_margin"> The right margin for the contents of this style box. Increasing this value reduces the space available to the contents from the right. Refer to [member content_margin_bottom] for extra considerations. </member> - <member name="content_margin_top" type="float" setter="set_default_margin" getter="get_default_margin" default="-1.0"> + <member name="content_margin_top" type="float" setter="set_default_margin" getter="get_default_margin"> The top margin for the contents of this style box. Increasing this value reduces the space available to the contents from the top. Refer to [member content_margin_bottom] for extra considerations. </member> diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 3157eea436..020c30b9cd 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -112,6 +112,13 @@ Returns the font descent (number of pixels below the baseline). </description> </method> + <method name="font_get_embolden" qualifiers="const"> + <return type="float" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns font embolden strength. + </description> + </method> <method name="font_get_fixed_size" qualifiers="const"> <return type="int" /> <argument index="0" name="font_rid" type="RID" /> @@ -368,6 +375,13 @@ Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. </description> </method> + <method name="font_get_transform" qualifiers="const"> + <return type="Transform2D" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns 2D transform applied to the font outlines. + </description> + </method> <method name="font_get_underline_position" qualifiers="const"> <return type="float" /> <argument index="0" name="font_rid" type="RID" /> @@ -542,6 +556,14 @@ Sets the font descent (number of pixels below the baseline). </description> </method> + <method name="font_set_embolden"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="strength" type="float" /> + <description> + Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness. + </description> + </method> <method name="font_set_fixed_size"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> @@ -765,6 +787,15 @@ Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. </description> </method> + <method name="font_set_transform"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="transform" type="Transform2D" /> + <description> + Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs. + For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code]. + </description> + </method> <method name="font_set_underline_position"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index f730f28e79..5ffd80bf63 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -112,6 +112,13 @@ Returns the font descent (number of pixels below the baseline). </description> </method> + <method name="_font_get_embolden" qualifiers="virtual const"> + <return type="float" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns font embolden strength. + </description> + </method> <method name="_font_get_fixed_size" qualifiers="virtual const"> <return type="int" /> <argument index="0" name="font_rid" type="RID" /> @@ -368,6 +375,13 @@ Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. </description> </method> + <method name="_font_get_transform" qualifiers="virtual const"> + <return type="Transform2D" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Retruns 2D transform applied to the font outlines. + </description> + </method> <method name="_font_get_underline_position" qualifiers="virtual const"> <return type="float" /> <argument index="0" name="font_rid" type="RID" /> @@ -551,6 +565,14 @@ Sets bitmap font fixed size. If set to value greater than zero, same cache entry will be used for all font sizes. </description> </method> + <method name="_font_set_embolden" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="strength" type="float" /> + <description> + Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness. + </description> + </method> <method name="_font_set_fixed_size" qualifiers="virtual"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> @@ -773,6 +795,15 @@ Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. </description> </method> + <method name="_font_set_transform" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="transform" type="Transform2D" /> + <description> + Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs. + For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code]. + </description> + </method> <method name="_font_set_underline_position" qualifiers="virtual"> <return type="void" /> <argument index="0" name="font_rid" type="RID" /> diff --git a/doc/classes/TextureProgressBar.xml b/doc/classes/TextureProgressBar.xml index a97e3a0cdc..4ea072a25f 100644 --- a/doc/classes/TextureProgressBar.xml +++ b/doc/classes/TextureProgressBar.xml @@ -27,7 +27,6 @@ <member name="fill_mode" type="int" setter="set_fill_mode" getter="get_fill_mode" default="0"> The fill direction. See [enum FillMode] for possible values. </member> - <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" overrides="Control" enum="Control.MouseFilter" default="1" /> <member name="nine_patch_stretch" type="bool" setter="set_nine_patch_stretch" getter="get_nine_patch_stretch" default="false"> If [code]true[/code], Godot treats the bar's textures like in [NinePatchRect]. Use the [code]stretch_margin_*[/code] properties like [member stretch_margin_bottom] to set up the nine patch's 3×3 grid. When using a radial [member fill_mode], this setting will enable stretching. </member> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index 6c0c3032ec..3ad21ee809 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -206,11 +206,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Transform2D" /> <description> Returns [code]true[/code] if the transforms are not equal. @@ -261,11 +256,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Transform2D" /> <description> Returns [code]true[/code] if the transforms are exactly equal. diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml index 67e70f30e4..5a72dc223c 100644 --- a/doc/classes/Transform3D.xml +++ b/doc/classes/Transform3D.xml @@ -148,11 +148,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Transform3D" /> <description> Returns [code]true[/code] if the transforms are not equal. @@ -203,11 +198,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Transform3D" /> <description> Returns [code]true[/code] if the transforms are exactly equal. diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index a39ddb8187..f9ef126658 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -359,11 +359,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Vector2" /> <description> Returns [code]true[/code] if the vectors are not equal. @@ -461,11 +456,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Vector2" /> <description> Returns [code]true[/code] if the vectors are exactly equal. diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml index 9b41e01c25..28d68b6e44 100644 --- a/doc/classes/Vector2i.xml +++ b/doc/classes/Vector2i.xml @@ -133,11 +133,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Vector2i" /> <description> Returns [code]true[/code] if the vectors are not equal. @@ -253,11 +248,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Vector2i" /> <description> Returns [code]true[/code] if the vectors are equal. diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index ec695f41c1..1653b66003 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -360,11 +360,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Vector3" /> <description> Returns [code]true[/code] if the vectors are not equal. @@ -476,11 +471,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Vector3" /> <description> Returns [code]true[/code] if the vectors are exactly equal. diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml index e486d7cfec..4c7f3badc5 100644 --- a/doc/classes/Vector3i.xml +++ b/doc/classes/Vector3i.xml @@ -140,11 +140,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="Vector3i" /> <description> Returns [code]true[/code] if the vectors are not equal. @@ -260,11 +255,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="Vector3i" /> <description> Returns [code]true[/code] if the vectors are equal. diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index ce61f51b9a..a72e7f1eb0 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -130,11 +130,6 @@ Removes the focus from the currently focused [Control] within this viewport. If no [Control] has the focus, does nothing. </description> </method> - <method name="is_embedding_subwindows" qualifiers="const"> - <return type="bool" /> - <description> - </description> - </method> <method name="is_input_handled" qualifiers="const"> <return type="bool" /> <description> @@ -219,7 +214,8 @@ <member name="gui_disable_input" type="bool" setter="set_disable_input" getter="is_input_disabled" default="false"> If [code]true[/code], the viewport will not receive input events. </member> - <member name="gui_embed_subwindows" type="bool" setter="set_embed_subwindows_hint" getter="get_embed_subwindows_hint" default="false"> + <member name="gui_embed_subwindows" type="bool" setter="set_embedding_subwindows" getter="is_embedding_subwindows" default="false"> + If [code]true[/code], sub-windows (popups and dialogs) will be embedded inside application window as control-like nodes. If [code]false[/code], they will appear as separate windows handled by the operating system. </member> <member name="gui_snap_controls_to_pixels" type="bool" setter="set_snap_controls_to_pixels" getter="is_snap_controls_to_pixels_enabled" default="true"> If [code]true[/code], the GUI controls on the viewport will lay pixel perfectly. diff --git a/doc/classes/ViewportTexture.xml b/doc/classes/ViewportTexture.xml index e5b7a68a51..87de664aad 100644 --- a/doc/classes/ViewportTexture.xml +++ b/doc/classes/ViewportTexture.xml @@ -14,7 +14,6 @@ <link title="3D Viewport Scaling Demo">https://godotengine.org/asset-library/asset/586</link> </tutorials> <members> - <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="true" /> <member name="viewport_path" type="NodePath" setter="set_viewport_path_in_scene" getter="get_viewport_path_in_scene" default="NodePath("")"> The path to the [Viewport] node to display. This is relative to the scene root, not to the node which uses the texture. </member> diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml index 7efa1f4df8..78a681d92a 100644 --- a/doc/classes/VisualInstance3D.xml +++ b/doc/classes/VisualInstance3D.xml @@ -63,7 +63,7 @@ </method> </methods> <members> - <member name="layers" type="int" setter="set_layer_mask" getter="get_layer_mask" default="1"> + <member name="layers" type="int" setter="set_layer_mask" getter="get_layer_mask"> The render layer(s) this [VisualInstance3D] is drawn on. This object will only be visible for [Camera3D]s whose cull mask includes the render object this [VisualInstance3D] is set to. </member> diff --git a/doc/classes/WorldBoundaryShape2D.xml b/doc/classes/WorldBoundaryShape2D.xml index cfcaede4a6..5a655520c3 100644 --- a/doc/classes/WorldBoundaryShape2D.xml +++ b/doc/classes/WorldBoundaryShape2D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="WorldBoundaryShape2D" inherits="Shape2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - World boundary shape for 2D collisions. + World boundary (infinite plane) shape resource for 2D physics. </brief_description> <description> - World boundary shape for 2D collisions. It works like a 2D plane and will not allow any physics body to go to the negative side. Not recommended for rigid bodies, and usually not recommended for static bodies either because it forces checks against it on every frame. + 2D world boundary shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. [WorldBoundaryShape2D] works like an infinite plane and will not allow any physics body to go to the negative side. Note that the [member normal] matters; anything "below" the plane will collide with it. If the [WorldBoundaryShape2D] is used in a [PhysicsBody2D], it will cause colliding objects placed "below" it to teleport "above" the plane. + [b]Performance:[/b] Being a primitive collision shape, [WorldBoundaryShape2D] is fast to check collisions against. </description> <tutorials> </tutorials> diff --git a/doc/classes/WorldBoundaryShape3D.xml b/doc/classes/WorldBoundaryShape3D.xml index a05c404125..4f6b987a8e 100644 --- a/doc/classes/WorldBoundaryShape3D.xml +++ b/doc/classes/WorldBoundaryShape3D.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="WorldBoundaryShape3D" inherits="Shape3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - World boundary shape for 3D collisions. + World boundary (infinite plane) shape resource for 3D physics. </brief_description> <description> - World boundary shape for 3D collisions. It works like an infinite plane and will not allow any physics body to go to the negative side. Note that the [Plane]'s normal matters; anything "below" the plane will collide with it. If the [WorldBoundaryShape3D] is used in a [PhysicsBody3D], it will cause colliding objects placed "below" it to teleport "above" the plane. + 3D world boundary shape to be added as a [i]direct[/i] child of a [PhysicsBody3D] or [Area3D] using a [CollisionShape3D] node. [WorldBoundaryShape3D] works like an infinite plane and will not allow any physics body to go to the negative side. Note that the [Plane]'s normal matters; anything "below" the plane will collide with it. If the [WorldBoundaryShape3D] is used in a [PhysicsBody3D], it will cause colliding objects placed "below" it to teleport "above" the plane. + [b]Performance:[/b] Being a primitive collision shape, [WorldBoundaryShape3D] is fast to check collisions against. </description> <tutorials> </tutorials> diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml index 6b1243b8c0..374b703636 100644 --- a/doc/classes/bool.xml +++ b/doc/classes/bool.xml @@ -123,11 +123,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="bool" /> <description> Returns [code]true[/code] if two bools are different, i.e. one is [code]true[/code] and the other is [code]false[/code]. @@ -142,12 +137,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - Returns [code]true[/code] if two bools are equal, i.e. both are [code]true[/code] or both are [code]false[/code]. - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="bool" /> <description> Returns [code]true[/code] if two bools are equal, i.e. both are [code]true[/code] or both are [code]false[/code]. diff --git a/doc/classes/float.xml b/doc/classes/float.xml index 1fe234c567..50961f9c7f 100644 --- a/doc/classes/float.xml +++ b/doc/classes/float.xml @@ -44,11 +44,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="float" /> <description> Returns [code]true[/code] if two floats are different from each other. @@ -201,11 +196,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="float" /> <description> Returns [code]true[/code] if both floats are exactly equal. diff --git a/doc/classes/int.xml b/doc/classes/int.xml index eac7ee8dfd..609291b69c 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -70,11 +70,6 @@ <operators> <operator name="operator !="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator !="> - <return type="bool" /> <argument index="0" name="right" type="float" /> <description> Returns [code]true[/code] if operands are different from each other. @@ -273,11 +268,6 @@ </operator> <operator name="operator =="> <return type="bool" /> - <description> - </description> - </operator> - <operator name="operator =="> - <return type="bool" /> <argument index="0" name="right" type="float" /> <description> Returns [code]true[/code] if the integer is equal to the given [float]. diff --git a/drivers/gles3/SCsub b/drivers/gles3/SCsub index 987ddcd16e..fcb05a988d 100644 --- a/drivers/gles3/SCsub +++ b/drivers/gles3/SCsub @@ -5,3 +5,4 @@ Import("env") env.add_source_files(env.drivers_sources, "*.cpp") SConscript("shaders/SCsub") +SConscript("storage/SCsub") diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 451960d772..b47d2e08f1 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -38,6 +38,8 @@ #include "core/config/project_settings.h" #include "servers/rendering/rendering_server_default.h" +#include "storage/canvas_texture_storage.h" +#include "storage/config.h" #ifndef GLES_OVER_GL #define glClearDepth glClearDepthf @@ -260,7 +262,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou for (int ti = 0; ti < tc; i++) { glActiveTexture(GL_TEXTURE0 + ti); - RasterizerStorageGLES3::Texture *t = storage->texture_owner.get_or_null(textures[ti].second); + GLES3::Texture *t = texture_storage->get_texture(textures[ti].second); if (!t) { switch (texture_uniforms[i].hint) { @@ -605,7 +607,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item _bind_canvas_texture(RID(), current_filter, current_repeat, r_index, last_texture, texpixel_size); state.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_PRIMITIVE); - for (uint32_t j = 0; j < MIN(3, primitive->point_count); j++) { + for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) { state.instance_data_array[r_index].points[j * 2 + 0] = primitive->points[j].x; state.instance_data_array[r_index].points[j * 2 + 1] = primitive->points[j].y; state.instance_data_array[r_index].uvs[j * 2 + 0] = primitive->uvs[j].x; @@ -915,20 +917,20 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe state.end_batch = true; _render_batch(r_index); - RasterizerStorageGLES3::CanvasTexture *ct = nullptr; + GLES3::CanvasTexture *ct = nullptr; - RasterizerStorageGLES3::Texture *t = storage->texture_owner.get_or_null(p_texture); + GLES3::Texture *t = texture_storage->get_texture(p_texture); if (t) { //regular texture if (!t->canvas_texture) { - t->canvas_texture = memnew(RasterizerStorageGLES3::CanvasTexture); + t->canvas_texture = memnew(GLES3::CanvasTexture); t->canvas_texture->diffuse = p_texture; } ct = t->canvas_texture; } else { - ct = storage->canvas_texture_owner.get_or_null(p_texture); + ct = GLES3::CanvasTextureStorage::get_singleton()->get_canvas_texture(p_texture); } if (!ct) { @@ -943,7 +945,7 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; ERR_FAIL_COND(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - RasterizerStorageGLES3::Texture *texture = storage->texture_owner.get_or_null(ct->diffuse); + GLES3::Texture *texture = texture_storage->get_texture(ct->diffuse); if (!texture) { state.current_tex = RID(); @@ -967,18 +969,18 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe texture->GLSetRepeat(GL_TEXTURE_2D, repeat); } - RasterizerStorageGLES3::Texture *normal_map = storage->texture_owner.get_or_null(ct->normal_map); + GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map); if (!normal_map) { state.current_normal = RID(); ct->use_normal_cache = false; - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); + glActiveTexture(GL_TEXTURE0 + GLES3::Config::get_singleton()->max_texture_image_units - 6); glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); } else { normal_map = normal_map->get_ptr(); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); + glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 6); glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); state.current_normal = ct->normal_map; ct->use_normal_cache = true; @@ -986,18 +988,18 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe texture->GLSetRepeat(GL_TEXTURE_2D, repeat); } - RasterizerStorageGLES3::Texture *specular_map = storage->texture_owner.get_or_null(ct->specular); + GLES3::Texture *specular_map = texture_storage->get_texture(ct->specular); if (!specular_map) { state.current_specular = RID(); ct->use_specular_cache = false; - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7); + glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); } else { specular_map = specular_map->get_ptr(); - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7); + glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7); glBindTexture(GL_TEXTURE_2D, specular_map->tex_id); state.current_specular = ct->specular; ct->use_specular_cache = true; @@ -1249,6 +1251,10 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() { } void RasterizerCanvasGLES3::initialize() { + // !BAS! shouldn't we be obtaining storage here as well? + canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton(); + texture_storage = GLES3::TextureStorage::get_singleton(); + // quad buffer { glGenBuffers(1, &data.canvas_quad_vertices); @@ -1408,7 +1414,7 @@ void RasterizerCanvasGLES3::initialize() { state.canvas_shader_default_version = state.canvas_shader.version_create(); state.canvas_shader.version_bind_shader(state.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD); - //state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); + //state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config->use_rgba_2d_shadows); //state.canvas_shader.bind(); @@ -1441,8 +1447,8 @@ void fragment() { storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader); } - default_canvas_texture = storage->canvas_texture_allocate(); - storage->canvas_texture_initialize(default_canvas_texture); + default_canvas_texture = canvas_texture_storage->canvas_texture_allocate(); + canvas_texture_storage->canvas_texture_initialize(default_canvas_texture); state.using_light = nullptr; state.using_transparent_rt = false; @@ -1456,7 +1462,7 @@ RasterizerCanvasGLES3::~RasterizerCanvasGLES3() { state.canvas_shader.version_free(state.canvas_shader_default_version); storage->free(default_canvas_group_material); storage->free(default_canvas_group_shader); - storage->free(default_canvas_texture); + canvas_texture_storage->canvas_texture_free(default_canvas_texture); } void RasterizerCanvasGLES3::finalize() { diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 908d79f9f8..1f57c2b5ea 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -37,6 +37,8 @@ #include "rasterizer_storage_gles3.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" +#include "storage/canvas_texture_storage.h" +#include "storage/texture_storage.h" #include "shaders/canvas.glsl.gen.h" @@ -184,7 +186,7 @@ public: RID current_tex = RID(); RID current_normal = RID(); RID current_specular = RID(); - RasterizerStorageGLES3::Texture *current_tex_ptr; + GLES3::Texture *current_tex_ptr; RID current_shader_version = RID(); RS::PrimitiveType current_primitive = RS::PRIMITIVE_MAX; uint32_t current_primitive_points = 0; @@ -217,6 +219,8 @@ public: RasterizerSceneGLES3 *scene_render; + GLES3::CanvasTextureStorage *canvas_texture_storage; + GLES3::TextureStorage *texture_storage; RasterizerStorageGLES3 *storage; void _set_uniforms(); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 087bf36473..faadb2a4ed 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -195,7 +195,7 @@ typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userP void RasterizerGLES3::initialize() { print_verbose("Using OpenGL video driver"); - storage._main_thread_id = Thread::get_caller_id(); + texture_storage.set_main_thread_id(Thread::get_caller_id()); #ifdef GLAD_ENABLED if (!gladLoadGL()) { @@ -271,7 +271,7 @@ void RasterizerGLES3::prepare_for_blitting_render_targets() { void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect) { ERR_FAIL_COND(storage.frame.current_rt); - RasterizerStorageGLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); // TODO: do we need a keep 3d linear option? @@ -324,10 +324,10 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c canvas.canvas_begin(); - RID texture = storage.texture_create(); - //storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0); - storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D); - storage.texture_set_data(texture, p_image); + RID texture = texture_storage.texture_create(); + //texture_storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0); + texture_storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D); + texture_storage.texture_set_data(texture, p_image); Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height()); Rect2 screenrect; @@ -349,13 +349,13 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor(); } - RasterizerStorageGLES3::Texture *t = storage.texture_owner.get_or_null(texture); - glActiveTexture(GL_TEXTURE0 + storage.config.max_texture_image_units - 1); + GLES3::Texture *t = texture_storage.get_texture(texture); + glActiveTexture(GL_TEXTURE0 + config.max_texture_image_units - 1); glBindTexture(GL_TEXTURE_2D, t->tex_id); glBindTexture(GL_TEXTURE_2D, 0); canvas.canvas_end(); - storage.free(texture); + texture_storage.texture_free(texture); end_frame(true); } diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index a641e189c5..93c58a8d9d 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -37,6 +37,10 @@ #include "rasterizer_scene_gles3.h" #include "rasterizer_storage_gles3.h" #include "servers/rendering/renderer_compositor.h" +#include "storage/canvas_texture_storage.h" +#include "storage/config.h" +#include "storage/render_target_storage.h" +#include "storage/texture_storage.h" class RasterizerGLES3 : public RendererCompositor { private: @@ -46,6 +50,9 @@ private: double time_total = 0.0; protected: + GLES3::Config config; + GLES3::CanvasTextureStorage canvas_texture_storage; + GLES3::TextureStorage texture_storage; RasterizerStorageGLES3 storage; RasterizerCanvasGLES3 canvas; RasterizerSceneGLES3 scene; @@ -53,6 +60,8 @@ protected: void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect); public: + RendererCanvasTextureStorage *get_canvas_texture_storage() { return &canvas_texture_storage; } + RendererTextureStorage *get_texture_storage() { return &texture_storage; } RendererStorage *get_storage() { return &storage; } RendererCanvasRender *get_canvas() { return &canvas; } RendererSceneRender *get_scene() { return &scene; } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index dce515a96d..11d4af126c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -40,45 +40,6 @@ GLuint RasterizerStorageGLES3::system_fbo = 0; -/* TEXTURE API */ - -#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 - -#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB -#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC -#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC -#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE -#define _EXT_ETC1_RGB8_OES 0x8D64 - -#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C -#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D -#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E -#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F - -#define _GL_TEXTURE_EXTERNAL_OES 0x8D65 - -#ifdef GLES_OVER_GL -#define _GL_HALF_FLOAT_OES 0x140B -#else -#define _GL_HALF_FLOAT_OES 0x8D61 -#endif - -#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F - -#define _RED_OES 0x1903 - -#define _DEPTH_COMPONENT24_OES 0x81A6 - -#ifndef GLES_OVER_GL -#define glClearDepth glClearDepthf -#endif //!GLES_OVER_GL - void RasterizerStorageGLES3::bind_quad_array() const { //glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); //glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); @@ -88,1180 +49,6 @@ void RasterizerStorageGLES3::bind_quad_array() const { //glEnableVertexAttribArray(RS::ARRAY_TEX_UV); } -bool RasterizerStorageGLES3::can_create_resources_async() const { - return false; -} - -Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { - r_gl_format = 0; - Ref<Image> image = p_image; - r_compressed = false; - r_real_format = p_format; - - bool need_decompress = false; - - switch (p_format) { - case Image::FORMAT_L8: { -#ifdef GLES_OVER_GL - r_gl_internal_format = GL_R8; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; -#else - r_gl_internal_format = GL_LUMINANCE; - r_gl_format = GL_LUMINANCE; - r_gl_type = GL_UNSIGNED_BYTE; -#endif - } break; - case Image::FORMAT_LA8: { -#ifdef GLES_OVER_GL - r_gl_internal_format = GL_RG8; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; -#else - r_gl_internal_format = GL_LUMINANCE_ALPHA; - r_gl_format = GL_LUMINANCE_ALPHA; - r_gl_type = GL_UNSIGNED_BYTE; -#endif - } break; - case Image::FORMAT_R8: { - r_gl_internal_format = GL_R8; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RG8: { - r_gl_internal_format = GL_RG8; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - - } break; - case Image::FORMAT_RGB8: { - r_gl_internal_format = GL_RGB8; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - //r_srgb = true; - - } break; - case Image::FORMAT_RGBA8: { - r_gl_format = GL_RGBA; - r_gl_internal_format = GL_RGBA8; - r_gl_type = GL_UNSIGNED_BYTE; - //r_srgb = true; - - } break; - case Image::FORMAT_RGBA4444: { - r_gl_internal_format = GL_RGBA4; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4; - - } break; - //case Image::FORMAT_RGBA5551: { - // r_gl_internal_format = GL_RGB5_A1; - // r_gl_format = GL_RGBA; - // r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1; - // - //} break; - case Image::FORMAT_RF: { - r_gl_internal_format = GL_R32F; - r_gl_format = GL_RED; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGF: { - r_gl_internal_format = GL_RG32F; - r_gl_format = GL_RG; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGBF: { - r_gl_internal_format = GL_RGB32F; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RGBAF: { - r_gl_internal_format = GL_RGBA32F; - r_gl_format = GL_RGBA; - r_gl_type = GL_FLOAT; - - } break; - case Image::FORMAT_RH: { - r_gl_internal_format = GL_R16F; - r_gl_format = GL_RED; - r_gl_type = GL_HALF_FLOAT; - } break; - case Image::FORMAT_RGH: { - r_gl_internal_format = GL_RG16F; - r_gl_format = GL_RG; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBH: { - r_gl_internal_format = GL_RGB16F; - r_gl_format = GL_RGB; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBAH: { - r_gl_internal_format = GL_RGBA16F; - r_gl_format = GL_RGBA; - r_gl_type = GL_HALF_FLOAT; - - } break; - case Image::FORMAT_RGBE9995: { - r_gl_internal_format = GL_RGB9_E5; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV; - - } break; - case Image::FORMAT_DXT1: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_DXT3: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_DXT5: { - if (config.s3tc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_RGTC_R: { - if (config.rgtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_RGTC_RG: { - if (config.rgtc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_BPTC_RGBA: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_BPTC_RGBF: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - r_compressed = true; - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_BPTC_RGBFU: { - if (config.bptc_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; - r_compressed = true; - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC: { - if (config.etc_supported) { - r_gl_internal_format = _EXT_ETC1_RGB8_OES; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - - } break; - /* - case Image::FORMAT_ETC2_R11: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_R11_EAC; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_R11S: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC; - r_gl_format = GL_RED; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RG11: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RG11S: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC; - r_gl_format = GL_RG; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RGB8: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB8_ETC2; - r_gl_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RGBA8: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGBA8_ETC2_EAC; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - case Image::FORMAT_ETC2_RGB8A1: { - if (config.etc2_supported) { - r_gl_internal_format = _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; - r_gl_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_compressed = true; - //r_srgb = true; - - } else { - need_decompress = true; - } - } break; - */ - default: { - ERR_FAIL_V(Ref<Image>()); - } - } - - if (need_decompress || p_force_decompress) { - if (!image.is_null()) { - image = image->duplicate(); - image->decompress(); - ERR_FAIL_COND_V(image->is_compressed(), image); - switch (image->get_format()) { - case Image::FORMAT_RGB8: { - r_gl_format = GL_RGB; - r_gl_internal_format = GL_RGB; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGB8; - r_compressed = false; - } break; - case Image::FORMAT_RGBA8: { - r_gl_format = GL_RGBA; - r_gl_internal_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGBA8; - r_compressed = false; - } break; - default: { - image->convert(Image::FORMAT_RGBA8); - r_gl_format = GL_RGBA; - r_gl_internal_format = GL_RGBA; - r_gl_type = GL_UNSIGNED_BYTE; - r_real_format = Image::FORMAT_RGBA8; - r_compressed = false; - - } break; - } - } - - return image; - } - - return p_image; -} - -static const GLenum _cube_side_enum[6] = { - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, -}; - -RID RasterizerStorageGLES3::texture_allocate() { - RID id = texture_create(); - ERR_FAIL_COND_V(id == RID(), id); - return id; -} - -void RasterizerStorageGLES3::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - - int w = p_image->get_width(); - int h = p_image->get_height(); - - _texture_allocate_internal(p_texture, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0); - texture_set_data(p_texture, p_image); -} - -void RasterizerStorageGLES3::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { -} - -void RasterizerStorageGLES3::texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { -} - -void RasterizerStorageGLES3::texture_proxy_initialize(RID p_texture, RID p_base) { - texture_set_proxy(p_texture, p_base); -} - -//RID RasterizerStorageGLES3::texture_2d_create(const Ref<Image> &p_image) { -// RID id = texture_create(); -// ERR_FAIL_COND_V(id == RID(), id); - -// int w = p_image->get_width(); -// int h = p_image->get_height(); - -// texture_allocate(id, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0); - -// texture_set_data(id, p_image); - -// return id; -//} - -//RID RasterizerStorageGLES3::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { -// return RID(); -//} - -//void RasterizerStorageGLES3::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) { -// // only 1 layer so far -// texture_set_data(p_texture, p_image); -//} -void RasterizerStorageGLES3::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { - // only 1 layer so far - texture_set_data(p_texture, p_image); -} - -void RasterizerStorageGLES3::texture_2d_placeholder_initialize(RID p_texture) { -} - -void RasterizerStorageGLES3::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) { -} - -void RasterizerStorageGLES3::texture_3d_placeholder_initialize(RID p_texture) { -} - -Ref<Image> RasterizerStorageGLES3::texture_2d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - - /* -#ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid()) { - return tex->image_cache_2d; - } -#endif - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instance(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - tex->image_cache_2d = image; - } -#endif -*/ - ERR_FAIL_COND_V(!tex->images.size(), Ref<Image>()); - - return tex->images[0]; - - // return image; - - // return Ref<Image>(); -} - -void RasterizerStorageGLES3::texture_replace(RID p_texture, RID p_by_texture) { - Texture *tex_to = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex_to); - Texture *tex_from = texture_owner.get_or_null(p_by_texture); - ERR_FAIL_COND(!tex_from); - - tex_to->destroy(); - tex_to->copy_from(*tex_from); - - // copy image data and upload to GL - tex_to->images.resize(tex_from->images.size()); - - for (int n = 0; n < tex_from->images.size(); n++) { - texture_set_data(p_texture, tex_from->images[n], n); - } - - free(p_by_texture); -} - -bool RasterizerStorageGLES3::_is_main_thread() { - //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED - // must be called from main thread in OpenGL - bool is_main_thread = _main_thread_id == Thread::get_caller_id(); - //#endif - return is_main_thread; -} - -RID RasterizerStorageGLES3::texture_create() { - ERR_FAIL_COND_V(!_is_main_thread(), RID()); - - Texture *texture = memnew(Texture); - ERR_FAIL_COND_V(!texture, RID()); - glGenTextures(1, &texture->tex_id); - texture->active = false; - texture->total_data_size = 0; - - return texture_owner.make_rid(texture); -} - -void RasterizerStorageGLES3::_texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags) { - // GLenum format; - // GLenum internal_format; - // GLenum type; - - // bool compressed = false; - - if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - p_flags &= ~TEXTURE_FLAG_MIPMAPS; // no mipies for video - } - - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - texture->width = p_width; - texture->height = p_height; - texture->format = p_format; - texture->flags = p_flags; - texture->stored_cube_sides = 0; - texture->type = p_type; - - switch (p_type) { - case RenderingDevice::TEXTURE_TYPE_2D: { - texture->target = GL_TEXTURE_2D; - texture->images.resize(1); - } break; - // case RenderingDevice::TEXTURE_TYPE_EXTERNAL: { - //#ifdef ANDROID_ENABLED - // texture->target = _GL_TEXTURE_EXTERNAL_OES; - //#else - // texture->target = GL_TEXTURE_2D; - //#endif - // texture->images.resize(0); - // } break; - case RenderingDevice::TEXTURE_TYPE_CUBE: { - texture->target = GL_TEXTURE_CUBE_MAP; - texture->images.resize(6); - } break; - case RenderingDevice::TEXTURE_TYPE_2D_ARRAY: - case RenderingDevice::TEXTURE_TYPE_3D: { - texture->target = GL_TEXTURE_3D; - ERR_PRINT("3D textures and Texture Arrays are not supported in OpenGL. Please switch to the Vulkan backend."); - return; - } break; - default: { - ERR_PRINT("Unknown texture type!"); - return; - } - } - -#if 0 - // if (p_type != RS::TEXTURE_TYPE_EXTERNAL) { - if (p_type == RenderingDevice::TEXTURE_TYPE_2D) { - texture->alloc_width = texture->width; - texture->alloc_height = texture->height; - texture->resize_to_po2 = false; - if (!config.support_npot_repeat_mipmap) { - int po2_width = next_power_of_2(p_width); - int po2_height = next_power_of_2(p_height); - - bool is_po2 = p_width == po2_width && p_height == po2_height; - - if (!is_po2 && (p_flags & TEXTURE_FLAG_REPEAT || p_flags & TEXTURE_FLAG_MIPMAPS)) { - if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - //not supported - ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled."); - texture->flags &= ~(TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS); - } else { - texture->alloc_height = po2_height; - texture->alloc_width = po2_width; - texture->resize_to_po2 = true; - } - } - } - - GLenum format; - GLenum internal_format; - GLenum type; - bool compressed = false; - - Image::Format real_format; - _get_gl_image_and_format(Ref<Image>(), - texture->format, - texture->flags, - real_format, - format, - internal_format, - type, - compressed, - texture->resize_to_po2); - - texture->gl_format_cache = format; - texture->gl_type_cache = type; - texture->gl_internal_format_cache = internal_format; - texture->data_size = 0; - texture->mipmaps = 1; - - texture->compressed = compressed; - } -#endif - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - // if (p_type == RS::TEXTURE_TYPE_EXTERNAL) { - // glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - // glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // } else if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { - // //prealloc if video - // glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL); - // } - - texture->active = true; -} - -void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND(!_is_main_thread()); - - 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 - return; - } - ERR_FAIL_COND(!texture->active); - ERR_FAIL_COND(texture->render_target); - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(texture->format != p_image->get_format()); - - ERR_FAIL_COND(!p_image->get_width()); - ERR_FAIL_COND(!p_image->get_height()); - - // ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL); - - GLenum type; - GLenum format; - GLenum internal_format; - bool compressed = false; - - if (config.keep_original_textures && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->images.write[p_layer] = p_image; - } - - // print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height())); - - Image::Format real_format; - Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2); - - if (texture->resize_to_po2) { - if (p_image->is_compressed()) { - ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage."); - } - - if (img == p_image) { - img = img->duplicate(); - } - img->resize_to_po2(false); - } - - if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->alloc_height = MAX(1, texture->alloc_height / 2); - texture->alloc_width = MAX(1, texture->alloc_width / 2); - - if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) { - img->shrink_x2(); - } else if (img->get_format() <= Image::FORMAT_RGBA8) { - img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); - } - } - - GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D; - - texture->data_size = img->get_data().size(); - Vector<uint8_t> read = img->get_data(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - texture->ignore_mipmaps = compressed && !img->has_mipmaps(); - - // set filtering and repeat state - _texture_set_state_from_flags(texture); - - //set swizle for older format compatibility -#ifdef GLES_OVER_GL - switch (texture->format) { - case Image::FORMAT_L8: { - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE); - - } break; - case Image::FORMAT_LA8: { - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN); - } break; - default: { - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE); - glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); - - } break; - } -#endif - - int mipmaps = ((texture->flags & TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; - - int w = img->get_width(); - int h = img->get_height(); - - int tsize = 0; - - for (int i = 0; i < mipmaps; i++) { - int size, ofs; - img->get_mipmap_offset_and_size(i, ofs, size); - - if (compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - - int bw = w; - int bh = h; - - glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]); - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - if (texture->flags & 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]); - } - } - - tsize += size; - - w = MAX(1, w >> 1); - h = MAX(1, h >> 1); - } - - info.texture_mem -= texture->total_data_size; - texture->total_data_size = tsize; - info.texture_mem += texture->total_data_size; - - // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem); - - texture->stored_cube_sides |= (1 << p_layer); - - if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RenderingDevice::TEXTURE_TYPE_CUBE || texture->stored_cube_sides == (1 << 6) - 1)) { - //generate mipmaps if they were requested and the image does not contain them - glGenerateMipmap(texture->target); - } - - texture->mipmaps = mipmaps; -} - -void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) { - // TODO - ERR_PRINT("Not implemented (ask Karroffel to do it :p)"); -} - -/* -Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, Ref<Image>()); - ERR_FAIL_COND_V(!texture->active, Ref<Image>()); - ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>()); - - if (texture->type == RS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) { - return texture->images[p_layer]; - } - -#ifdef GLES_OVER_GL - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, false); - - PoolVector<uint8_t> data; - - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1); - - data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - glActiveTexture(GL_TEXTURE0); - - glBindTexture(texture->target, texture->tex_id); - - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - for (int i = 0; i < texture->mipmaps; i++) { - int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i); - - if (texture->compressed) { - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glGetCompressedTexImage(texture->target, i, &wb[ofs]); - } else { - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]); - } - } - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, real_format, data)); - - return Ref<Image>(img); -#else - - Image::Format real_format; - GLenum gl_format; - GLenum gl_internal_format; - GLenum gl_type; - bool compressed; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, texture->resize_to_po2); - - PoolVector<uint8_t> data; - - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); - - data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers - PoolVector<uint8_t>::Write wb = data.write(); - - GLuint temp_framebuffer; - glGenFramebuffers(1, &temp_framebuffer); - - GLuint temp_color_texture; - glGenTextures(1, &temp_color_texture); - - glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); - - glBindTexture(GL_TEXTURE_2D, temp_color_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glColorMask(1, 1, 1, 1); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - - glViewport(0, 0, texture->alloc_width, texture->alloc_height); - - shaders.copy.bind(); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - bind_quad_array(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); - - glDeleteTextures(1, &temp_color_texture); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &temp_framebuffer); - - wb.release(); - - data.resize(data_size); - - Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); - if (!texture->compressed) { - img->convert(real_format); - } - - return Ref<Image>(img); - -#endif -} -*/ - -void RasterizerStorageGLES3::_texture_set_state_from_flags(Texture *p_tex) { - if ((p_tex->flags & TEXTURE_FLAG_MIPMAPS) && !p_tex->ignore_mipmaps) { - if (p_tex->flags & TEXTURE_FLAG_FILTER) { - // these do not exactly correspond ... - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); - //texture->glTexParam_MinFilter(texture->target, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); - } else { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); - //texture->glTexParam_MinFilter(texture->target, config.use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR); - } - } else { - if (p_tex->flags & TEXTURE_FLAG_FILTER) { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR); - //texture->glTexParam_MinFilter(texture->target, GL_LINEAR); - } else { - p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST); - // texture->glTexParam_MinFilter(texture->target, GL_NEAREST); - } - } - - if (((p_tex->flags & TEXTURE_FLAG_REPEAT) || (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT)) && p_tex->target != GL_TEXTURE_CUBE_MAP) { - if (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT) { - p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); - } else { - p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - } - } else { - p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - } -} - -void RasterizerStorageGLES3::texture_set_flags(RID p_texture, uint32_t p_flags) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - bool had_mipmaps = texture->flags & TEXTURE_FLAG_MIPMAPS; - - texture->flags = p_flags; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - // set filtering and repeat state - _texture_set_state_from_flags(texture); - - if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { - if (!had_mipmaps && texture->mipmaps == 1) { - glGenerateMipmap(texture->target); - } - } -} - -uint32_t RasterizerStorageGLES3::texture_get_flags(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->flags; -} - -Image::Format RasterizerStorageGLES3::texture_get_format(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, Image::FORMAT_L8); - - return texture->format; -} - -RenderingDevice::TextureType RasterizerStorageGLES3::texture_get_type(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, RenderingDevice::TEXTURE_TYPE_2D); - - return texture->type; -} - -uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->tex_id; -} - -void RasterizerStorageGLES3::texture_bind(RID p_texture, uint32_t p_texture_no) { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND(!texture); - - glActiveTexture(GL_TEXTURE0 + p_texture_no); - glBindTexture(texture->target, texture->tex_id); -} - -uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->width; -} - -uint32_t RasterizerStorageGLES3::texture_get_height(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->height; -} - -uint32_t RasterizerStorageGLES3::texture_get_depth(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND_V(!texture, 0); - - return texture->depth; -} - -void RasterizerStorageGLES3::texture_set_size_override(RID p_texture, int p_width, int p_height) { - Texture *texture = texture_owner.get_or_null(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(texture->render_target); - - ERR_FAIL_COND(p_width <= 0 || p_width > 16384); - ERR_FAIL_COND(p_height <= 0 || p_height > 16384); - //real texture size is in alloc width and height - texture->width = p_width; - texture->height = p_height; -} - -void RasterizerStorageGLES3::texture_set_path(RID p_texture, const String &p_path) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->path = p_path; -} - -String RasterizerStorageGLES3::texture_get_path(RID p_texture) const { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!texture, ""); - - return texture->path; -} - -void RasterizerStorageGLES3::texture_debug_usage(List<RS::TextureInfo> *r_info) { - List<RID> textures; - texture_owner.get_owned_list(&textures); - - for (List<RID>::Element *E = textures.front(); E; E = E->next()) { - Texture *t = texture_owner.get_or_null(E->get()); - if (!t) { - continue; - } - RS::TextureInfo tinfo; - tinfo.path = t->path; - tinfo.format = t->format; - tinfo.width = t->alloc_width; - tinfo.height = t->alloc_height; - tinfo.depth = 0; - tinfo.bytes = t->total_data_size; - r_info->push_back(tinfo); - } -} - -void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable) { - config.shrink_textures_x2 = p_enable; -} - -void RasterizerStorageGLES3::textures_keep_original(bool p_enable) { - config.keep_original_textures = p_enable; -} - -Size2 RasterizerStorageGLES3::texture_size_with_proxy(RID p_texture) { - const Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!texture, Size2()); - if (texture->proxy) { - return Size2(texture->proxy->width, texture->proxy->height); - } else { - return Size2(texture->width, texture->height); - } -} - -// example use in 3.2 -// VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid); - -// p_proxy is the source (pre-existing) texture? -// and p_texture is the one that is being made into a proxy? -//This naming is confusing. Comments!!! - -// The naming of the parameters seemed to be reversed? -// The p_proxy is the source texture -// and p_texture is actually the proxy???? - -void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - if (texture->proxy) { - texture->proxy->proxy_owners.erase(texture); - texture->proxy = nullptr; - } - - if (p_proxy.is_valid()) { - Texture *proxy = texture_owner.get_or_null(p_proxy); - ERR_FAIL_COND(!proxy); - ERR_FAIL_COND(proxy == texture); - proxy->proxy_owners.insert(texture); - texture->proxy = proxy; - } -} - -void RasterizerStorageGLES3::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->redraw_if_visible = p_enable; -} - -void RasterizerStorageGLES3::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->detect_3d = p_callback; - texture->detect_3d_ud = p_userdata; -} - -void RasterizerStorageGLES3::texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->detect_srgb = p_callback; - texture->detect_srgb_ud = p_userdata; -} - -void RasterizerStorageGLES3::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *texture = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!texture); - - texture->detect_normal = p_callback; - texture->detect_normal_ud = p_userdata; -} - -RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_resolution) const { - return RID(); -} - -RID RasterizerStorageGLES3::canvas_texture_allocate() { - return canvas_texture_owner.allocate_rid(); -} - -void RasterizerStorageGLES3::canvas_texture_initialize(RID p_rid) { - canvas_texture_owner.initialize_rid(p_rid); -} - -void RasterizerStorageGLES3::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - switch (p_channel) { - case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { - ct->diffuse = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { - ct->normal_map = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { - ct->specular = p_texture; - } break; - } -} - -void RasterizerStorageGLES3::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->specular_color.r = p_specular_color.r; - ct->specular_color.g = p_specular_color.g; - ct->specular_color.b = p_specular_color.b; - ct->specular_color.a = p_shininess; -} - -void RasterizerStorageGLES3::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_filter = p_filter; -} -void RasterizerStorageGLES3::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_repeat = p_repeat; -} - RID RasterizerStorageGLES3::sky_create() { Sky *sky = memnew(Sky); sky->radiance = 0; @@ -1666,7 +453,7 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); - ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); + ERR_FAIL_COND(p_texture.is_valid() && !GLES3::TextureStorage::get_singleton()->owns_texture(p_texture)); if (!p_texture.is_valid()) { if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) { @@ -2897,7 +1684,7 @@ bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const { /* RENDER TARGET */ void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); if (rt) { if (rt->allocate_is_dirty) { @@ -2923,7 +1710,7 @@ void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) { } } -void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { +void RasterizerStorageGLES3::_render_target_allocate(GLES3::RenderTarget *rt) { // do not allocate a render target with no size if (rt->width <= 0 || rt->height <= 0) { return; @@ -2964,7 +1751,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { { /* Front FBO */ - Texture *texture = texture_owner.get_or_null(rt->texture); + GLES3::Texture *texture = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture); ERR_FAIL_COND(!texture); // framebuffer @@ -2977,7 +1764,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, nullptr); - if (texture->flags & TEXTURE_FLAG_FILTER) { + if (texture->flags & GLES3::TEXTURE_FLAG_FILTER) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { @@ -2992,10 +1779,10 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { // depth - if (config.support_depth_texture) { + if (config->support_depth_texture) { glGenTextures(1, &rt->depth); glBindTexture(GL_TEXTURE_2D, rt->depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -3007,7 +1794,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenRenderbuffers(1, &rt->depth); glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); - glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, rt->width, rt->height); + glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, rt->width, rt->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); } @@ -3016,7 +1803,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { if (status != GL_FRAMEBUFFER_COMPLETE) { glDeleteFramebuffers(1, &rt->fbo); - if (config.support_depth_texture) { + if (config->support_depth_texture) { glDeleteTextures(1, &rt->depth); } else { glDeleteRenderbuffers(1, &rt->depth); @@ -3045,7 +1832,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { texture->alloc_height = rt->height; texture->active = true; - texture_set_flags(rt->texture, texture->flags); + GLES3::TextureStorage::get_singleton()->texture_set_flags(rt->texture, texture->flags); } /* BACK FBO */ @@ -3071,7 +1858,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenRenderbuffers(1, &rt->multisample_depth); glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->width, rt->height); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config->depth_buffer_internalformat, rt->width, rt->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth); @@ -3160,7 +1947,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { int fb_h = h; while (true) { - RenderTarget::MipMaps::Size mm; + GLES3::RenderTarget::MipMaps::Size mm; mm.width = w; mm.height = h; rt->mip_maps[i].sizes.push_back(mm); @@ -3178,7 +1965,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { GLsizei width = fb_w; GLsizei height = fb_h; - if (config.render_to_mipmap_supported) { + if (config->render_to_mipmap_supported) { glGenTextures(1, &rt->mip_maps[i].color); glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color); @@ -3211,12 +1998,12 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glDepthMask(GL_TRUE); for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) { - RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j]; + GLES3::RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j]; glGenFramebuffers(1, &mm.fbo); bind_framebuffer(mm.fbo); - if (config.render_to_mipmap_supported) { + if (config->render_to_mipmap_supported) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j); } else { glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color); @@ -3225,7 +2012,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { bool used_depth = false; if (j == 0 && i == 0) { //use always - if (config.support_depth_texture) { + if (config->support_depth_texture) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); } else { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); @@ -3250,7 +2037,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { rt->mip_maps[i].levels = level; - if (config.render_to_mipmap_supported) { + if (config->render_to_mipmap_supported) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -3263,7 +2050,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { bind_framebuffer_system(); } -void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { +void RasterizerStorageGLES3::_render_target_clear(GLES3::RenderTarget *rt) { // there is nothing to clear when DIRECT_TO_SCREEN is used if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) { return; @@ -3280,20 +2067,20 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { glDeleteFramebuffers(1, &rt->external.fbo); // clean up our texture - Texture *t = texture_owner.get_or_null(rt->external.texture); + GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture); t->alloc_height = 0; t->alloc_width = 0; t->width = 0; t->height = 0; t->active = false; - texture_owner.free(rt->external.texture); + GLES3::TextureStorage::get_singleton()->texture_free(rt->external.texture); memdelete(t); rt->external.fbo = 0; } if (rt->depth) { - if (config.support_depth_texture) { + if (config->support_depth_texture) { glDeleteTextures(1, &rt->depth); } else { glDeleteRenderbuffers(1, &rt->depth); @@ -3302,7 +2089,7 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { rt->depth = 0; } - Texture *tex = texture_owner.get_or_null(rt->texture); + GLES3::Texture *tex = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture); tex->alloc_height = 0; tex->alloc_width = 0; tex->width = 0; @@ -3345,8 +2132,8 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { } RID RasterizerStorageGLES3::render_target_create() { - RenderTarget *rt = memnew(RenderTarget); - Texture *t = memnew(Texture); + GLES3::RenderTarget *rt = memnew(GLES3::RenderTarget); + GLES3::Texture *t = memnew(GLES3::Texture); t->type = RenderingDevice::TEXTURE_TYPE_2D; t->flags = 0; @@ -3368,12 +2155,12 @@ RID RasterizerStorageGLES3::render_target_create() { t->tex_id = 0; t->render_target = rt; - rt->texture = texture_owner.make_rid(t); + rt->texture = GLES3::TextureStorage::get_singleton()->make_rid(t); return render_target_owner.make_rid(rt); } void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->x = p_x; @@ -3381,7 +2168,7 @@ void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int } void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); if (p_width == rt->width && p_height == rt->height) { @@ -3401,14 +2188,14 @@ void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_w // TODO: convert to Size2i internally Size2i RasterizerStorageGLES3::render_target_get_size(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, Size2()); return Size2i(rt->width, rt->height); } RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, RID()); if (rt->external.fbo == 0) { @@ -3419,7 +2206,7 @@ RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) { } void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); if (p_texture_id == 0) { @@ -3433,13 +2220,13 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar } // clean up our texture - Texture *t = texture_owner.get_or_null(rt->external.texture); + GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture); t->alloc_height = 0; t->alloc_width = 0; t->width = 0; t->height = 0; t->active = false; - texture_owner.free(rt->external.texture); + GLES3::TextureStorage::get_singleton()->texture_free(rt->external.texture); memdelete(t); rt->external.fbo = 0; @@ -3447,7 +2234,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar rt->external.depth = 0; } } else { - Texture *t; + GLES3::Texture *t; if (rt->external.fbo == 0) { // create our fbo @@ -3455,7 +2242,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar bind_framebuffer(rt->external.fbo); // allocate a texture - t = memnew(Texture); + t = memnew(GLES3::Texture); t->type = RenderingDevice::TEXTURE_TYPE_2D; t->flags = 0; @@ -3478,14 +2265,14 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar t->tex_id = 0; t->render_target = rt; - rt->external.texture = texture_owner.make_rid(t); + rt->external.texture = GLES3::TextureStorage::get_singleton()->make_rid(t); } else { // bind our frame buffer bind_framebuffer(rt->external.fbo); // find our texture - t = texture_owner.get_or_null(rt->external.texture); + t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture); } // set our texture @@ -3504,7 +2291,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0); // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :) - if (config.support_depth_texture) { + if (config->support_depth_texture) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); } else { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); @@ -3524,7 +2311,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar } void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as @@ -3556,21 +2343,21 @@ void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderT } bool RasterizerStorageGLES3::render_target_was_used(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, false); return rt->used_in_frame; } void RasterizerStorageGLES3::render_target_clear_used(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->used_in_frame = false; } void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); if (rt->msaa == p_msaa) { @@ -3582,20 +2369,20 @@ void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, RS::Vie _render_target_allocate(rt); } -//RasterizerStorageGLES3::RenderTarget * RasterizerStorageGLES3::render_target_get(RID p_render_target) +//RasterizerStorageGLES3::GLES3::RenderTarget * RasterizerStorageGLES3::render_target_get(RID p_render_target) //{ // return render_target_owner.get_or_null(p_render_target); //} void RasterizerStorageGLES3::render_target_set_use_fxaa(RID p_render_target, bool p_fxaa) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->use_fxaa = p_fxaa; } void RasterizerStorageGLES3::render_target_set_use_debanding(RID p_render_target, bool p_debanding) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); if (p_debanding) { @@ -3606,7 +2393,7 @@ void RasterizerStorageGLES3::render_target_set_use_debanding(RID p_render_target } void RasterizerStorageGLES3::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->clear_requested = true; rt->clear_color = p_clear_color; @@ -3617,18 +2404,18 @@ void RasterizerStorageGLES3::render_target_request_clear(RID p_render_target, co } bool RasterizerStorageGLES3::render_target_is_clear_requested(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, false); return rt->clear_requested; } Color RasterizerStorageGLES3::render_target_get_clear_request_color(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, Color()); return rt->clear_color; } void RasterizerStorageGLES3::render_target_disable_clear_request(RID p_render_target) { - RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); rt->clear_requested = false; } @@ -3651,8 +2438,8 @@ void RasterizerStorageGLES3::render_target_mark_sdf_enabled(RID p_render_target, RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) { CanvasLightShadow *cls = memnew(CanvasLightShadow); - if (p_width > config.max_texture_size) { - p_width = config.max_texture_size; + if (p_width > config->max_texture_size) { + p_width = config->max_texture_size; } cls->size = p_width; @@ -3665,12 +2452,12 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) { glGenRenderbuffers(1, &cls->depth); glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); - glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, cls->size, cls->height); + glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, cls->size, cls->height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); glGenTextures(1, &cls->distance); glBindTexture(GL_TEXTURE_2D, cls->distance); - if (config.use_rgba_2d_shadows) { + if (config->use_rgba_2d_shadows) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } else { #ifdef GLES_OVER_GL @@ -3822,33 +2609,23 @@ RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { bool RasterizerStorageGLES3::free(RID p_rid) { if (render_target_owner.owns(p_rid)) { - RenderTarget *rt = render_target_owner.get_or_null(p_rid); + GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_rid); _render_target_clear(rt); - Texture *t = texture_owner.get_or_null(rt->texture); + GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture); if (t) { - texture_owner.free(rt->texture); + GLES3::TextureStorage::get_singleton()->texture_free(rt->texture); memdelete(t); } render_target_owner.free(p_rid); memdelete(rt); return true; - } else if (texture_owner.owns(p_rid)) { - Texture *t = texture_owner.get_or_null(p_rid); - // can't free a render target texture - ERR_FAIL_COND_V(t->render_target, true); - if (t->canvas_texture) { - memdelete(t->canvas_texture); - } - - info.texture_mem -= t->total_data_size; - texture_owner.free(p_rid); - memdelete(t); - + } else if (GLES3::TextureStorage::get_singleton()->owns_texture(p_rid)) { + GLES3::TextureStorage::get_singleton()->texture_free(p_rid); return true; - } else if (canvas_texture_owner.owns(p_rid)) { - canvas_texture_owner.free(p_rid); + } else if (GLES3::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { + GLES3::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid); return true; } else if (sky_owner.owns(p_rid)) { Sky *sky = sky_owner.get_or_null(p_rid); @@ -4042,15 +2819,15 @@ bool RasterizerStorageGLES3::free(RID p_rid) { bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const { if (p_feature == "s3tc") { - return config.s3tc_supported; + return config->s3tc_supported; } if (p_feature == "etc") { - return config.etc_supported; + return config->etc_supported; } if (p_feature == "skinning_fallback") { - return config.use_skeleton_software; + return config->use_skeleton_software; } return false; @@ -4157,105 +2934,11 @@ RenderingDevice::DeviceType RasterizerStorageGLES3::get_video_adapter_type() con void RasterizerStorageGLES3::initialize() { RasterizerStorageGLES3::system_fbo = 0; + config = GLES3::Config::get_singleton(); + config->initialize(); - { - const GLubyte *extension_string = glGetString(GL_EXTENSIONS); - - Vector<String> extensions = String((const char *)extension_string).split(" "); - - for (int i = 0; i < extensions.size(); i++) { - config.extensions.insert(extensions[i]); - } - } - - config.keep_original_textures = true; // false - config.shrink_textures_x2 = false; - config.depth_internalformat = GL_DEPTH_COMPONENT; - config.depth_type = GL_UNSIGNED_INT; - -#ifdef GLES_OVER_GL - config.float_texture_supported = true; - config.s3tc_supported = true; - config.etc_supported = false; - config.support_npot_repeat_mipmap = true; - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24; -#else - 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.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1"); - config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot"); - -#ifdef JAVASCRIPT_ENABLED - // RenderBuffer internal format must be 16 bits in WebGL, - // but depth_texture should default to 32 always - // if the implementation doesn't support 32, it should just quietly use 16 instead - // https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/ - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - config.depth_type = GL_UNSIGNED_INT; -#else - // on mobile check for 24 bit depth support for RenderBufferStorage - if (config.extensions.has("GL_OES_depth24")) { - config.depth_buffer_internalformat = _DEPTH_COMPONENT24_OES; - config.depth_type = GL_UNSIGNED_INT; - } else { - config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16; - config.depth_type = GL_UNSIGNED_SHORT; - } -#endif -#endif - -#ifdef GLES_OVER_GL - //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps - config.render_to_mipmap_supported = false; -#else - //check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms - config.render_to_mipmap_supported = config.extensions.has("GL_OES_fbo_render_mipmap") && config.extensions.has("GL_EXT_texture_lod"); -#endif - -#ifdef GLES_OVER_GL - config.use_rgba_2d_shadows = false; - config.support_depth_texture = true; - config.use_rgba_3d_shadows = false; - config.support_depth_cubemaps = true; -#else - config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg")); - config.support_depth_texture = config.extensions.has("GL_OES_depth_texture") || config.extensions.has("WEBGL_depth_texture"); - config.use_rgba_3d_shadows = !config.support_depth_texture; - config.support_depth_cubemaps = config.extensions.has("GL_OES_depth_texture_cube_map"); -#endif - -#ifdef GLES_OVER_GL - config.support_32_bits_indices = true; -#else - config.support_32_bits_indices = config.extensions.has("GL_OES_element_index_uint"); -#endif - -#ifdef GLES_OVER_GL - config.support_write_depth = true; -#elif defined(JAVASCRIPT_ENABLED) - config.support_write_depth = false; -#else - config.support_write_depth = config.extensions.has("GL_EXT_frag_depth"); -#endif - - config.support_half_float_vertices = true; -//every platform should support this except web, iOS has issues with their support, so add option to disable -#ifdef JAVASCRIPT_ENABLED - config.support_half_float_vertices = false; -#endif - bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float"); - if (disable_half_float) { - config.support_half_float_vertices = false; - } - - config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); - config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc"); - config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc"); - config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc"); - config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc") || config.extensions.has("EXT_texture_compression_bptc"); - config.srgb_decode_supported = config.extensions.has("GL_EXT_texture_sRGB_decode"); //determine formats for depth textures (or renderbuffers) - if (config.support_depth_texture) { + if (config->support_depth_texture) { // Will use texture for depth // have to manually see if we can create a valid framebuffer texture using UNSIGNED_INT, // as there is no extension to test for this. @@ -4265,7 +2948,7 @@ void RasterizerStorageGLES3::initialize() { GLuint depth; glGenTextures(1, &depth); glBindTexture(GL_TEXTURE_2D, depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config.depth_type, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -4285,19 +2968,19 @@ void RasterizerStorageGLES3::initialize() { // If it fails, test to see if it supports a framebuffer texture using UNSIGNED_SHORT // This is needed because many OSX devices don't support either UNSIGNED_INT or UNSIGNED_SHORT #ifdef GLES_OVER_GL - config.depth_internalformat = GL_DEPTH_COMPONENT16; + config->depth_internalformat = GL_DEPTH_COMPONENT16; #else // OES_depth_texture extension only specifies GL_DEPTH_COMPONENT. - config.depth_internalformat = GL_DEPTH_COMPONENT; + config->depth_internalformat = GL_DEPTH_COMPONENT; #endif - config.depth_type = GL_UNSIGNED_SHORT; + config->depth_type = GL_UNSIGNED_SHORT; glGenFramebuffers(1, &fbo); bind_framebuffer(fbo); glGenTextures(1, &depth); glBindTexture(GL_TEXTURE_2D, depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -4309,8 +2992,8 @@ void RasterizerStorageGLES3::initialize() { status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { //if it fails again depth textures aren't supported, use rgba shadows and renderbuffer for depth - config.support_depth_texture = false; - config.use_rgba_3d_shadows = true; + config->support_depth_texture = false; + config->use_rgba_3d_shadows = true; } bind_framebuffer_system(); @@ -4321,20 +3004,16 @@ void RasterizerStorageGLES3::initialize() { } //picky requirements for these - config.support_shadow_cubemaps = config.support_depth_texture && config.support_write_depth && config.support_depth_cubemaps; + config->support_shadow_cubemaps = config->support_depth_texture && config->support_write_depth && config->support_depth_cubemaps; frame.count = 0; frame.delta = 0; frame.current_rt = nullptr; frame.clear_request = false; - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &config.max_vertex_texture_image_units); - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); - // the use skeleton software path should be used if either float texture is not supported, // OR max_vertex_texture_image_units is zero - config.use_skeleton_software = (config.float_texture_supported == false) || (config.max_vertex_texture_image_units == 0); + config->use_skeleton_software = (config->float_texture_supported == false) || (config->max_vertex_texture_image_units == 0); shaders.copy.initialize(); shaders.copy_version = shaders.copy.version_create(); //TODO @@ -4438,7 +3117,7 @@ void RasterizerStorageGLES3::initialize() { // radical inverse vdc cache texture // used for cubemap filtering - if (true /*||config.float_texture_supported*/) { //uint8 is similar and works everywhere + if (true /*||config->float_texture_supported*/) { //uint8 is similar and works everywhere glGenTextures(1, &resources.radical_inverse_vdc_cache_tex); glActiveTexture(GL_TEXTURE0); @@ -4476,16 +3155,12 @@ void RasterizerStorageGLES3::initialize() { #ifdef GLES_OVER_GL //this needs to be enabled manually in OpenGL 2.1 - if (config.extensions.has("GL_ARB_seamless_cube_map")) { + if (config->extensions.has("GL_ARB_seamless_cube_map")) { glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); } glEnable(GL_POINT_SPRITE); glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); #endif - - config.force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); - config.use_fast_texture_filter = false; //GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter"); - //config.should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers"); } void RasterizerStorageGLES3::finalize() { @@ -4512,7 +3187,6 @@ void RasterizerStorageGLES3::update_dirty_resources() { RasterizerStorageGLES3::RasterizerStorageGLES3() { RasterizerStorageGLES3::system_fbo = 0; - config.should_orphan = true; } RasterizerStorageGLES3::~RasterizerStorageGLES3() { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index de984fa8df..ba457e54b0 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -40,6 +40,10 @@ #include "servers/rendering/renderer_storage.h" #include "servers/rendering/shader_compiler.h" #include "servers/rendering/shader_language.h" +#include "storage/canvas_texture_storage.h" +#include "storage/config.h" +#include "storage/render_target_storage.h" +#include "storage/texture_storage.h" #include "shaders/copy.glsl.gen.h" @@ -47,66 +51,13 @@ class RasterizerCanvasGLES3; class RasterizerSceneGLES3; class RasterizerStorageGLES3 : public RendererStorage { - friend class RasterizerGLES3; - - Thread::ID _main_thread_id = 0; - bool _is_main_thread(); - public: RasterizerCanvasGLES3 *canvas; RasterizerSceneGLES3 *scene; static GLuint system_fbo; - struct Config { - bool shrink_textures_x2; - bool use_fast_texture_filter; - bool use_skeleton_software; - - int max_vertex_texture_image_units; - int max_texture_image_units; - int max_texture_size; - - // TODO implement wireframe in OpenGL - // bool generate_wireframes; - - Set<String> extensions; - - bool float_texture_supported; - bool s3tc_supported; - bool latc_supported; - bool rgtc_supported; - bool bptc_supported; - bool etc_supported; - bool etc2_supported; - bool srgb_decode_supported; - - bool keep_original_textures; - - bool force_vertex_shading; - - bool use_rgba_2d_shadows; - bool use_rgba_3d_shadows; - - bool support_32_bits_indices; - bool support_write_depth; - bool support_half_float_vertices; - bool support_npot_repeat_mipmap; - bool support_depth_texture; - bool support_depth_cubemaps; - - bool support_shadow_cubemaps; - - bool render_to_mipmap_supported; - - GLuint depth_internalformat; - GLuint depth_type; - GLuint depth_buffer_internalformat; - - // in some cases the legacy render didn't orphan. We will mark these - // so the user can switch orphaning off for them. - bool should_orphan; - } config; + GLES3::Config *config; struct Resources { GLuint white_tex; @@ -180,334 +131,7 @@ public: //////////////////////////////////API//////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// - bool can_create_resources_async() const override; - - // TEXTURE API - - enum OpenGLTextureFlags { - TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available - TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping - TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter - TEXTURE_FLAG_ANISOTROPIC_FILTER = 8, - TEXTURE_FLAG_CONVERT_TO_LINEAR = 16, - TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored - TEXTURE_FLAG_USED_FOR_STREAMING = 2048, - TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER - }; - - /* CANVAS TEXTURE API (2D) */ - - struct CanvasTexture { - RID diffuse; - RID normal_map; - RID specular; - Color specular_color = Color(1, 1, 1, 1); - float shininess = 1.0; - - RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - - Size2i size_cache = Size2i(1, 1); - bool use_normal_cache = false; - bool use_specular_cache = false; - bool cleared_cache = true; - }; - - RID_Owner<CanvasTexture, true> canvas_texture_owner; - - struct RenderTarget; - - struct Texture { - RID self; - - Texture *proxy; - Set<Texture *> proxy_owners; - - String path; - uint32_t flags; - int width, height, depth; - int alloc_width, alloc_height; - Image::Format format; - RenderingDevice::TextureType type; - - GLenum target; - GLenum gl_format_cache; - GLenum gl_internal_format_cache; - GLenum gl_type_cache; - - int data_size; - int total_data_size; - bool ignore_mipmaps; - - bool compressed; - - bool srgb; - - int mipmaps; - - bool resize_to_po2; - - bool active; - GLenum tex_id; - - uint16_t stored_cube_sides; - - RenderTarget *render_target; - - Vector<Ref<Image>> images; - - bool redraw_if_visible; - - RS::TextureDetectCallback detect_3d; - void *detect_3d_ud; - - RS::TextureDetectCallback detect_srgb; - void *detect_srgb_ud; - - RS::TextureDetectCallback detect_normal; - void *detect_normal_ud; - - CanvasTexture *canvas_texture = nullptr; - - // some silly opengl shenanigans where - // texture coords start from bottom left, means we need to draw render target textures upside down - // to be compatible with vulkan etc. - bool is_upside_down() const { - if (proxy) { - return proxy->is_upside_down(); - } - - return render_target != nullptr; - } - - Texture() { - create(); - } - - _ALWAYS_INLINE_ Texture *get_ptr() { - if (proxy) { - return proxy; //->get_ptr(); only one level of indirection, else not inlining possible. - } else { - return this; - } - } - - ~Texture() { - destroy(); - - if (tex_id != 0) { - glDeleteTextures(1, &tex_id); - } - } - - void copy_from(const Texture &o) { - proxy = o.proxy; - flags = o.flags; - width = o.width; - height = o.height; - alloc_width = o.alloc_width; - alloc_height = o.alloc_height; - format = o.format; - type = o.type; - target = o.target; - data_size = o.data_size; - total_data_size = o.total_data_size; - ignore_mipmaps = o.ignore_mipmaps; - compressed = o.compressed; - mipmaps = o.mipmaps; - resize_to_po2 = o.resize_to_po2; - active = o.active; - tex_id = o.tex_id; - stored_cube_sides = o.stored_cube_sides; - render_target = o.render_target; - redraw_if_visible = o.redraw_if_visible; - detect_3d = o.detect_3d; - detect_3d_ud = o.detect_3d_ud; - detect_srgb = o.detect_srgb; - detect_srgb_ud = o.detect_srgb_ud; - detect_normal = o.detect_normal; - detect_normal_ud = o.detect_normal_ud; - - images.clear(); - } - - void create() { - proxy = nullptr; - flags = 0; - width = 0; - height = 0; - alloc_width = 0; - alloc_height = 0; - format = Image::FORMAT_L8; - type = RenderingDevice::TEXTURE_TYPE_2D; - target = 0; - data_size = 0; - total_data_size = 0; - ignore_mipmaps = false; - compressed = false; - mipmaps = 0; - resize_to_po2 = false; - active = false; - tex_id = 0; - stored_cube_sides = 0; - render_target = nullptr; - redraw_if_visible = false; - detect_3d = nullptr; - detect_3d_ud = nullptr; - detect_srgb = nullptr; - detect_srgb_ud = nullptr; - detect_normal = nullptr; - detect_normal_ud = nullptr; - } - void destroy() { - images.clear(); - - for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) { - E->get()->proxy = nullptr; - } - - if (proxy) { - proxy->proxy_owners.erase(this); - } - } - - // texture state - void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) { - if (p_filter == state_filter) { - return; - } - state_filter = p_filter; - GLint pmin = GL_LINEAR; // param min - GLint pmag = GL_LINEAR; // param mag - switch (state_filter) { - default: { - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { - pmin = GL_LINEAR_MIPMAP_LINEAR; - pmag = GL_LINEAR; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { - pmin = GL_NEAREST; - pmag = GL_NEAREST; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { - pmin = GL_NEAREST_MIPMAP_NEAREST; - pmag = GL_NEAREST; - } break; - } - glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin); - glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag); - } - void GLSetRepeat(GLenum p_target, RS::CanvasItemTextureRepeat p_repeat) { - if (p_repeat == state_repeat) { - return; - } - state_repeat = p_repeat; - GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat - switch (state_repeat) { - default: { - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { - prep = GL_REPEAT; - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { - prep = GL_MIRRORED_REPEAT; - } break; - } - glTexParameteri(p_target, GL_TEXTURE_WRAP_S, prep); - glTexParameteri(p_target, GL_TEXTURE_WRAP_T, prep); - } - - private: - RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; - RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; - }; - - mutable RID_PtrOwner<Texture> texture_owner; - - Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const; - - void _texture_set_state_from_flags(Texture *p_tex); - - // new - RID texture_allocate() override; - void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; - void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; - void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override; - void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent - - void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; - void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {} - void texture_proxy_update(RID p_proxy, RID p_base) override {} - - void texture_2d_placeholder_initialize(RID p_texture) override; - void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; - void texture_3d_placeholder_initialize(RID p_texture) override; - - Ref<Image> texture_2d_get(RID p_texture) const override; - Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); } - Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); } - - void texture_replace(RID p_texture, RID p_by_texture) override; - //void texture_set_size_override(RID p_texture, int p_width, int p_height) override {} - - void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - - // old - uint32_t texture_get_width(RID p_texture) const; - uint32_t texture_get_height(RID p_texture) const; - -private: - RID texture_create(); - - //void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); - void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); - - void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); - void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0); - //Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const; - void texture_set_flags(RID p_texture, uint32_t p_flags); - uint32_t texture_get_flags(RID p_texture) const; - Image::Format texture_get_format(RID p_texture) const; - RenderingDevice::TextureType texture_get_type(RID p_texture) const; - uint32_t texture_get_texid(RID p_texture) const; - uint32_t texture_get_depth(RID p_texture) const; - void texture_set_size_override(RID p_texture, int p_width, int p_height) override; - - void texture_bind(RID p_texture, uint32_t p_texture_no); - - void texture_set_path(RID p_texture, const String &p_path) override; - String texture_get_path(RID p_texture) const override; - - void texture_set_shrink_all_x2_on_set_data(bool p_enable); - - void texture_debug_usage(List<RS::TextureInfo> *r_info) override; - - RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const; - - void textures_keep_original(bool p_enable); - - void texture_set_proxy(RID p_texture, RID p_proxy); - Size2 texture_size_with_proxy(RID p_texture) override; - - void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; - void texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); - void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; - void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {} - - void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override; - public: - RID canvas_texture_allocate() override; - void canvas_texture_initialize(RID p_rid) override; - - void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override; - void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) override; - - void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) override; - void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) override; - /* SKY API */ // not sure if used in godot 4? struct Sky { @@ -971,6 +595,9 @@ public: AABB decal_get_aabb(RID p_decal) const override; + void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + /* VOXEL GI API */ RID voxel_gi_allocate() override; @@ -1151,85 +778,10 @@ public: // RENDER TARGET - struct RenderTarget { - RID self; - GLuint fbo = 0; - GLuint color = 0; - GLuint depth = 0; - - GLuint multisample_fbo = 0; - GLuint multisample_color = 0; - GLuint multisample_depth = 0; - bool multisample_active = false; - - struct Effect { - GLuint fbo = 0; - int width = 0; - int height = 0; - - GLuint color = 0; - }; - - Effect copy_screen_effect; - - struct MipMaps { - struct Size { - GLuint fbo = 0; - GLuint color = 0; - int width = 0; - int height = 0; - }; - - Vector<Size> sizes; - GLuint color = 0; - int levels = 0; - }; - - MipMaps mip_maps[2]; - - struct External { - GLuint fbo = 0; - GLuint color = 0; - GLuint depth = 0; - RID texture; - } external; - - int x = 0; - int y = 0; - int width = 0; - int height = 0; - - bool flags[RENDER_TARGET_FLAG_MAX] = {}; - - // instead of allocating sized render targets immediately, - // defer this for faster startup - bool allocate_is_dirty = false; - bool used_in_frame = false; - RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; - - bool use_fxaa = false; - bool use_debanding = false; - - RID texture; - - bool used_dof_blur_near = false; - bool mip_maps_allocated = false; - - Color clear_color = Color(1, 1, 1, 1); - bool clear_requested = false; - - RenderTarget() { - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; ++i) { - flags[i] = false; - } - external.fbo = 0; - } - }; - - mutable RID_PtrOwner<RenderTarget> render_target_owner; + mutable RID_PtrOwner<GLES3::RenderTarget> render_target_owner; - void _render_target_clear(RenderTarget *rt); - void _render_target_allocate(RenderTarget *rt); + void _render_target_clear(GLES3::RenderTarget *rt); + void _render_target_allocate(GLES3::RenderTarget *rt); void _set_current_render_target(RID p_render_target); RID render_target_create() override; @@ -1262,7 +814,7 @@ public: void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override; // access from canvas - // RenderTarget * render_target_get(RID p_render_target); + // GLES3::RenderTarget * render_target_get(RID p_render_target); /* CANVAS SHADOW */ @@ -1301,7 +853,7 @@ public: bool free(RID p_rid) override; struct Frame { - RenderTarget *current_rt; + GLES3::RenderTarget *current_rt; // these 2 may have been superseded by the equivalents in the render target. // these may be able to be removed. @@ -1408,7 +960,7 @@ inline bool RasterizerStorageGLES3::safe_buffer_sub_data(unsigned int p_total_bu inline void RasterizerStorageGLES3::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target, GLenum p_usage, bool p_optional_orphan) const { // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData // Was previously #ifndef GLES_OVER_GL however this causes stalls on desktop mac also (and possibly other) - if (!p_optional_orphan || (config.should_orphan)) { + if (!p_optional_orphan || (config->should_orphan)) { glBufferData(p_target, p_buffer_size, nullptr, p_usage); #ifdef RASTERIZER_EXTRA_CHECKS // fill with garbage off the end of the array diff --git a/drivers/gles3/storage/SCsub b/drivers/gles3/storage/SCsub new file mode 100644 index 0000000000..91e1140b75 --- /dev/null +++ b/drivers/gles3/storage/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.drivers_sources, "*.cpp") diff --git a/drivers/gles3/storage/canvas_texture_storage.cpp b/drivers/gles3/storage/canvas_texture_storage.cpp new file mode 100644 index 0000000000..fe12700c21 --- /dev/null +++ b/drivers/gles3/storage/canvas_texture_storage.cpp @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* canvas_texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "canvas_texture_storage.h" + +using namespace GLES3; + +CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr; + +CanvasTextureStorage *CanvasTextureStorage::get_singleton() { + return singleton; +} + +CanvasTextureStorage::CanvasTextureStorage() { + singleton = this; +} + +CanvasTextureStorage::~CanvasTextureStorage() { + singleton = nullptr; +} + +RID CanvasTextureStorage::canvas_texture_allocate() { + return canvas_texture_owner.allocate_rid(); +} + +void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) { + canvas_texture_owner.initialize_rid(p_rid); +} + +void CanvasTextureStorage::canvas_texture_free(RID p_rid) { + canvas_texture_owner.free(p_rid); +} + +void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + switch (p_channel) { + case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { + ct->diffuse = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { + ct->normal_map = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { + ct->specular = p_texture; + } break; + } +} + +void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ct->specular_color.r = p_specular_color.r; + ct->specular_color.g = p_specular_color.g; + ct->specular_color.b = p_specular_color.b; + ct->specular_color.a = p_shininess; +} + +void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ct->texture_filter = p_filter; +} + +void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ct->texture_repeat = p_repeat; +} + +#endif // !GLES3_ENABLED diff --git a/drivers/gles3/storage/canvas_texture_storage.h b/drivers/gles3/storage/canvas_texture_storage.h new file mode 100644 index 0000000000..5930e927fe --- /dev/null +++ b/drivers/gles3/storage/canvas_texture_storage.h @@ -0,0 +1,87 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_GLES3_H +#define CANVAS_TEXTURE_STORAGE_GLES3_H + +#ifdef GLES3_ENABLED + +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/canvas_texture_storage.h" + +namespace GLES3 { + +struct CanvasTexture { + RID diffuse; + RID normal_map; + RID specular; + Color specular_color = Color(1, 1, 1, 1); + float shininess = 1.0; + + RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + + Size2i size_cache = Size2i(1, 1); + bool use_normal_cache = false; + bool use_specular_cache = false; + bool cleared_cache = true; +}; + +class CanvasTextureStorage : public RendererCanvasTextureStorage { +private: + static CanvasTextureStorage *singleton; + + RID_Owner<CanvasTexture, true> canvas_texture_owner; + +public: + static CanvasTextureStorage *get_singleton(); + + CanvasTextureStorage(); + virtual ~CanvasTextureStorage(); + + CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }; + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + + virtual RID canvas_texture_allocate() override; + virtual void canvas_texture_initialize(RID p_rid) override; + virtual void canvas_texture_free(RID p_rid) override; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override; +}; + +} // namespace GLES3 + +#endif // !GLES3_ENABLED + +#endif // !CANVAS_TEXTURE_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp new file mode 100644 index 0000000000..1f66401427 --- /dev/null +++ b/drivers/gles3/storage/config.cpp @@ -0,0 +1,156 @@ +/*************************************************************************/ +/* config.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "config.h" +#include "core/templates/vector.h" + +using namespace GLES3; + +Config *Config::singleton = nullptr; + +Config::Config() { + singleton = this; + should_orphan = true; +} + +Config::~Config() { + singleton = nullptr; +} + +void Config::initialize() { + { + const GLubyte *extension_string = glGetString(GL_EXTENSIONS); + + Vector<String> exts = String((const char *)extension_string).split(" "); + + for (int i = 0; i < exts.size(); i++) { + extensions.insert(exts[i]); + } + } + + keep_original_textures = true; // false + shrink_textures_x2 = false; + depth_internalformat = GL_DEPTH_COMPONENT; + depth_type = GL_UNSIGNED_INT; + +#ifdef GLES_OVER_GL + float_texture_supported = true; + s3tc_supported = true; + etc_supported = false; + support_npot_repeat_mipmap = true; + depth_buffer_internalformat = GL_DEPTH_COMPONENT24; +#else + float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float"); + s3tc_supported = extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); + etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || extensions.has("WEBGL_compressed_texture_etc1"); + support_npot_repeat_mipmap = extensions.has("GL_OES_texture_npot"); + +#ifdef JAVASCRIPT_ENABLED + // RenderBuffer internal format must be 16 bits in WebGL, + // but depth_texture should default to 32 always + // if the implementation doesn't support 32, it should just quietly use 16 instead + // https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/ + depth_buffer_internalformat = GL_DEPTH_COMPONENT16; + depth_type = GL_UNSIGNED_INT; +#else + // on mobile check for 24 bit depth support for RenderBufferStorage + if (extensions.has("GL_OES_depth24")) { + depth_buffer_internalformat = _DEPTH_COMPONENT24_OES; + depth_type = GL_UNSIGNED_INT; + } else { + depth_buffer_internalformat = GL_DEPTH_COMPONENT16; + depth_type = GL_UNSIGNED_SHORT; + } +#endif +#endif + +#ifdef GLES_OVER_GL + //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps + render_to_mipmap_supported = false; +#else + //check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms + render_to_mipmap_supported = extensions.has("GL_OES_fbo_render_mipmap") && extensions.has("GL_EXT_texture_lod"); +#endif + +#ifdef GLES_OVER_GL + use_rgba_2d_shadows = false; + support_depth_texture = true; + use_rgba_3d_shadows = false; + support_depth_cubemaps = true; +#else + use_rgba_2d_shadows = !(float_texture_supported && extensions.has("GL_EXT_texture_rg")); + support_depth_texture = extensions.has("GL_OES_depth_texture") || extensions.has("WEBGL_depth_texture"); + use_rgba_3d_shadows = !support_depth_texture; + support_depth_cubemaps = extensions.has("GL_OES_depth_texture_cube_map"); +#endif + +#ifdef GLES_OVER_GL + support_32_bits_indices = true; +#else + support_32_bits_indices = extensions.has("GL_OES_element_index_uint"); +#endif + +#ifdef GLES_OVER_GL + support_write_depth = true; +#elif defined(JAVASCRIPT_ENABLED) + support_write_depth = false; +#else + support_write_depth = extensions.has("GL_EXT_frag_depth"); +#endif + + support_half_float_vertices = true; +//every platform should support this except web, iOS has issues with their support, so add option to disable +#ifdef JAVASCRIPT_ENABLED + support_half_float_vertices = false; +#endif + bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float"); + if (disable_half_float) { + support_half_float_vertices = false; + } + + etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture"); + latc_supported = extensions.has("GL_EXT_texture_compression_latc"); + bptc_supported = extensions.has("GL_ARB_texture_compression_bptc"); + rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc"); + bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc"); + srgb_decode_supported = extensions.has("GL_EXT_texture_sRGB_decode"); + + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units); + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_image_units); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); + + force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); + use_fast_texture_filter = false; //GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter"); + // should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers"); +} + +#endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h new file mode 100644 index 0000000000..25bd3fd9a1 --- /dev/null +++ b/drivers/gles3/storage/config.h @@ -0,0 +1,113 @@ +/*************************************************************************/ +/* config.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CONFIG_GLES3_H +#define CONFIG_GLES3_H + +#ifdef GLES3_ENABLED + +#include "core/string/ustring.h" +#include "core/templates/set.h" + +// This must come first to avoid windows.h mess +#include "platform_config.h" +#ifndef OPENGL_INCLUDE_H +#include <GLES3/gl3.h> +#else +#include OPENGL_INCLUDE_H +#endif + +namespace GLES3 { + +class Config { +private: + static Config *singleton; + +public: + bool shrink_textures_x2; + bool use_fast_texture_filter; + bool use_skeleton_software; + + int max_vertex_texture_image_units; + int max_texture_image_units; + int max_texture_size; + + // TODO implement wireframe in OpenGL + // bool generate_wireframes; + + Set<String> extensions; + + bool float_texture_supported; + bool s3tc_supported; + bool latc_supported; + bool rgtc_supported; + bool bptc_supported; + bool etc_supported; + bool etc2_supported; + bool srgb_decode_supported; + + bool keep_original_textures; + + bool force_vertex_shading; + + bool use_rgba_2d_shadows; + bool use_rgba_3d_shadows; + + bool support_32_bits_indices; + bool support_write_depth; + bool support_half_float_vertices; + bool support_npot_repeat_mipmap; + bool support_depth_texture; + bool support_depth_cubemaps; + + bool support_shadow_cubemaps; + + bool render_to_mipmap_supported; + + GLuint depth_internalformat; + GLuint depth_type; + GLuint depth_buffer_internalformat; + + // in some cases the legacy render didn't orphan. We will mark these + // so the user can switch orphaning off for them. + bool should_orphan = true; + + static Config *get_singleton() { return singleton; }; + + Config(); + ~Config(); + void initialize(); +}; + +} // namespace GLES3 + +#endif // GLES3_ENABLED + +#endif // !CONFIG_GLES3_H diff --git a/drivers/gles3/storage/render_target_storage.h b/drivers/gles3/storage/render_target_storage.h new file mode 100644 index 0000000000..816cc76e40 --- /dev/null +++ b/drivers/gles3/storage/render_target_storage.h @@ -0,0 +1,132 @@ +/*************************************************************************/ +/* render_target_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDER_TARGET_STORAGE_GLES3_H +#define RENDER_TARGET_STORAGE_GLES3_H + +#ifdef GLES3_ENABLED + +#include "core/templates/rid_owner.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_storage.h" // included until we move stuff into storage/render_target_storage.h +// #include "servers/rendering/storage/render_target_storage.h" + +// This must come first to avoid windows.h mess +#include "platform_config.h" +#ifndef OPENGL_INCLUDE_H +#include <GLES3/gl3.h> +#else +#include OPENGL_INCLUDE_H +#endif + +namespace GLES3 { + +// NOTE, this class currently is just a container for the the RenderTarget struct and is not yet implemented further, we'll do that next after we finish with TextureStorage + +struct RenderTarget { + RID self; + GLuint fbo = 0; + GLuint color = 0; + GLuint depth = 0; + + GLuint multisample_fbo = 0; + GLuint multisample_color = 0; + GLuint multisample_depth = 0; + bool multisample_active = false; + + struct Effect { + GLuint fbo = 0; + int width = 0; + int height = 0; + + GLuint color = 0; + }; + + Effect copy_screen_effect; + + struct MipMaps { + struct Size { + GLuint fbo = 0; + GLuint color = 0; + int width = 0; + int height = 0; + }; + + Vector<Size> sizes; + GLuint color = 0; + int levels = 0; + }; + + MipMaps mip_maps[2]; + + struct External { + GLuint fbo = 0; + GLuint color = 0; + GLuint depth = 0; + RID texture; + } external; + + int x = 0; + int y = 0; + int width = 0; + int height = 0; + + bool flags[RendererStorage::RENDER_TARGET_FLAG_MAX] = {}; + + // instead of allocating sized render targets immediately, + // defer this for faster startup + bool allocate_is_dirty = false; + bool used_in_frame = false; + RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; + + bool use_fxaa = false; + bool use_debanding = false; + + RID texture; + + bool used_dof_blur_near = false; + bool mip_maps_allocated = false; + + Color clear_color = Color(1, 1, 1, 1); + bool clear_requested = false; + + RenderTarget() { + for (int i = 0; i < RendererStorage::RENDER_TARGET_FLAG_MAX; ++i) { + flags[i] = false; + } + external.fbo = 0; + } +}; + +} // namespace GLES3 + +#endif // !GLES3_ENABLED + +#endif // !RENDER_TARGET_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp new file mode 100644 index 0000000000..d199b1032e --- /dev/null +++ b/drivers/gles3/storage/texture_storage.cpp @@ -0,0 +1,1211 @@ +/*************************************************************************/ +/* texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "texture_storage.h" +#include "config.h" + +using namespace GLES3; + +TextureStorage *TextureStorage::singleton = nullptr; + +TextureStorage *TextureStorage::get_singleton() { + return singleton; +} + +TextureStorage::TextureStorage() { + singleton = this; +} + +TextureStorage::~TextureStorage() { + singleton = nullptr; +} + +void TextureStorage::set_main_thread_id(Thread::ID p_id) { + _main_thread_id = p_id; +} + +bool TextureStorage::_is_main_thread() { + //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED + // must be called from main thread in OpenGL + bool is_main_thread = _main_thread_id == Thread::get_caller_id(); + //#endif + return is_main_thread; +} + +bool TextureStorage::can_create_resources_async() const { + return false; +} + +static const GLenum _cube_side_enum[6] = { + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, +}; + +Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { + Config *config = Config::get_singleton(); + r_gl_format = 0; + Ref<Image> image = p_image; + r_compressed = false; + r_real_format = p_format; + + bool need_decompress = false; + + switch (p_format) { + case Image::FORMAT_L8: { +#ifdef GLES_OVER_GL + r_gl_internal_format = GL_R8; + r_gl_format = GL_RED; + r_gl_type = GL_UNSIGNED_BYTE; +#else + r_gl_internal_format = GL_LUMINANCE; + r_gl_format = GL_LUMINANCE; + r_gl_type = GL_UNSIGNED_BYTE; +#endif + } break; + case Image::FORMAT_LA8: { +#ifdef GLES_OVER_GL + r_gl_internal_format = GL_RG8; + r_gl_format = GL_RG; + r_gl_type = GL_UNSIGNED_BYTE; +#else + r_gl_internal_format = GL_LUMINANCE_ALPHA; + r_gl_format = GL_LUMINANCE_ALPHA; + r_gl_type = GL_UNSIGNED_BYTE; +#endif + } break; + case Image::FORMAT_R8: { + r_gl_internal_format = GL_R8; + r_gl_format = GL_RED; + r_gl_type = GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RG8: { + r_gl_internal_format = GL_RG8; + r_gl_format = GL_RG; + r_gl_type = GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RGB8: { + r_gl_internal_format = GL_RGB8; + r_gl_format = GL_RGB; + r_gl_type = GL_UNSIGNED_BYTE; + //r_srgb = true; + + } break; + case Image::FORMAT_RGBA8: { + r_gl_format = GL_RGBA; + r_gl_internal_format = GL_RGBA8; + r_gl_type = GL_UNSIGNED_BYTE; + //r_srgb = true; + + } break; + case Image::FORMAT_RGBA4444: { + r_gl_internal_format = GL_RGBA4; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4; + + } break; + //case Image::FORMAT_RGBA5551: { + // r_gl_internal_format = GL_RGB5_A1; + // r_gl_format = GL_RGBA; + // r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1; + // + //} break; + case Image::FORMAT_RF: { + r_gl_internal_format = GL_R32F; + r_gl_format = GL_RED; + r_gl_type = GL_FLOAT; + + } break; + case Image::FORMAT_RGF: { + r_gl_internal_format = GL_RG32F; + r_gl_format = GL_RG; + r_gl_type = GL_FLOAT; + + } break; + case Image::FORMAT_RGBF: { + r_gl_internal_format = GL_RGB32F; + r_gl_format = GL_RGB; + r_gl_type = GL_FLOAT; + + } break; + case Image::FORMAT_RGBAF: { + r_gl_internal_format = GL_RGBA32F; + r_gl_format = GL_RGBA; + r_gl_type = GL_FLOAT; + + } break; + case Image::FORMAT_RH: { + r_gl_internal_format = GL_R16F; + r_gl_format = GL_RED; + r_gl_type = GL_HALF_FLOAT; + } break; + case Image::FORMAT_RGH: { + r_gl_internal_format = GL_RG16F; + r_gl_format = GL_RG; + r_gl_type = GL_HALF_FLOAT; + + } break; + case Image::FORMAT_RGBH: { + r_gl_internal_format = GL_RGB16F; + r_gl_format = GL_RGB; + r_gl_type = GL_HALF_FLOAT; + + } break; + case Image::FORMAT_RGBAH: { + r_gl_internal_format = GL_RGBA16F; + r_gl_format = GL_RGBA; + r_gl_type = GL_HALF_FLOAT; + + } break; + case Image::FORMAT_RGBE9995: { + r_gl_internal_format = GL_RGB9_E5; + r_gl_format = GL_RGB; + r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV; + + } break; + case Image::FORMAT_DXT1: { + if (config->s3tc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_DXT3: { + if (config->s3tc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_DXT5: { + if (config->s3tc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_RGTC_R: { + if (config->rgtc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_RGTC_RG: { + if (config->rgtc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_BPTC_RGBA: { + if (config->bptc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_BPTC_RGBF: { + if (config->bptc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; + r_gl_format = GL_RGB; + r_gl_type = GL_FLOAT; + r_compressed = true; + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_BPTC_RGBFU: { + if (config->bptc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + r_gl_format = GL_RGB; + r_gl_type = GL_FLOAT; + r_compressed = true; + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC: { + if (config->etc_supported) { + r_gl_internal_format = _EXT_ETC1_RGB8_OES; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + + } break; + /* + case Image::FORMAT_ETC2_R11: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_R11_EAC; + r_gl_format = GL_RED; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_R11S: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC; + r_gl_format = GL_RED; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_RG11: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC; + r_gl_format = GL_RG; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_RG11S: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC; + r_gl_format = GL_RG; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_RGB8: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGB8_ETC2; + r_gl_format = GL_RGB; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_RGBA8: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA8_ETC2_EAC; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ETC2_RGB8A1: { + if (config->etc2_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + //r_srgb = true; + + } else { + need_decompress = true; + } + } break; + */ + default: { + ERR_FAIL_V(Ref<Image>()); + } + } + + if (need_decompress || p_force_decompress) { + if (!image.is_null()) { + image = image->duplicate(); + image->decompress(); + ERR_FAIL_COND_V(image->is_compressed(), image); + switch (image->get_format()) { + case Image::FORMAT_RGB8: { + r_gl_format = GL_RGB; + r_gl_internal_format = GL_RGB; + r_gl_type = GL_UNSIGNED_BYTE; + r_real_format = Image::FORMAT_RGB8; + r_compressed = false; + } break; + case Image::FORMAT_RGBA8: { + r_gl_format = GL_RGBA; + r_gl_internal_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_real_format = Image::FORMAT_RGBA8; + r_compressed = false; + } break; + default: { + image->convert(Image::FORMAT_RGBA8); + r_gl_format = GL_RGBA; + r_gl_internal_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_real_format = Image::FORMAT_RGBA8; + r_compressed = false; + + } break; + } + } + + return image; + } + + return p_image; +} + +void TextureStorage::_texture_set_state_from_flags(Texture *p_tex) { + // Config *config = Config::get_singleton(); + + if ((p_tex->flags & TEXTURE_FLAG_MIPMAPS) && !p_tex->ignore_mipmaps) { + if (p_tex->flags & TEXTURE_FLAG_FILTER) { + // these do not exactly correspond ... + p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); + //texture->glTexParam_MinFilter(texture->target, config->use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); + } else { + p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); + //texture->glTexParam_MinFilter(texture->target, config->use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR); + } + } else { + if (p_tex->flags & TEXTURE_FLAG_FILTER) { + p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR); + //texture->glTexParam_MinFilter(texture->target, GL_LINEAR); + } else { + p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST); + //texture->glTexParam_MinFilter(texture->target, GL_NEAREST); + } + } + + if (((p_tex->flags & TEXTURE_FLAG_REPEAT) || (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT)) && p_tex->target != GL_TEXTURE_CUBE_MAP) { + if (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT) { + p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); + } else { + p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + } + } else { + p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + } +} + +void TextureStorage::_texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags) { + // GLenum format; + // GLenum internal_format; + // GLenum type; + + // bool compressed = false; + + // Config *config = Config::get_singleton(); + + if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { + p_flags &= ~TEXTURE_FLAG_MIPMAPS; // no mipies for video + } + + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + texture->width = p_width; + texture->height = p_height; + texture->format = p_format; + texture->flags = p_flags; + texture->stored_cube_sides = 0; + texture->type = p_type; + + switch (p_type) { + case RenderingDevice::TEXTURE_TYPE_2D: { + texture->target = GL_TEXTURE_2D; + texture->images.resize(1); + } break; + // case RenderingDevice::TEXTURE_TYPE_EXTERNAL: { + //#ifdef ANDROID_ENABLED + // texture->target = _GL_TEXTURE_EXTERNAL_OES; + //#else + // texture->target = GL_TEXTURE_2D; + //#endif + // texture->images.resize(0); + // } break; + case RenderingDevice::TEXTURE_TYPE_CUBE: { + texture->target = GL_TEXTURE_CUBE_MAP; + texture->images.resize(6); + } break; + case RenderingDevice::TEXTURE_TYPE_2D_ARRAY: + case RenderingDevice::TEXTURE_TYPE_3D: { + texture->target = GL_TEXTURE_3D; + ERR_PRINT("3D textures and Texture Arrays are not supported in OpenGL. Please switch to the Vulkan backend."); + return; + } break; + default: { + ERR_PRINT("Unknown texture type!"); + return; + } + } + +#if 0 + // if (p_type != RS::TEXTURE_TYPE_EXTERNAL) { + if (p_type == RenderingDevice::TEXTURE_TYPE_2D) { + texture->alloc_width = texture->width; + texture->alloc_height = texture->height; + texture->resize_to_po2 = false; + if (!config->support_npot_repeat_mipmap) { + int po2_width = next_power_of_2(p_width); + int po2_height = next_power_of_2(p_height); + + bool is_po2 = p_width == po2_width && p_height == po2_height; + + if (!is_po2 && (p_flags & TEXTURE_FLAG_REPEAT || p_flags & TEXTURE_FLAG_MIPMAPS)) { + if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { + //not supported + ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled."); + texture->flags &= ~(TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS); + } else { + texture->alloc_height = po2_height; + texture->alloc_width = po2_width; + texture->resize_to_po2 = true; + } + } + } + + GLenum format; + GLenum internal_format; + GLenum type; + bool compressed = false; + + Image::Format real_format; + _get_gl_image_and_format(Ref<Image>(), + texture->format, + texture->flags, + real_format, + format, + internal_format, + type, + compressed, + texture->resize_to_po2); + + texture->gl_format_cache = format; + texture->gl_type_cache = type; + texture->gl_internal_format_cache = internal_format; + texture->data_size = 0; + texture->mipmaps = 1; + + texture->compressed = compressed; + } +#endif + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + // if (p_type == RS::TEXTURE_TYPE_EXTERNAL) { + // glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + // glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + // } else if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) { + // //prealloc if video + // glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL); + // } + + texture->active = true; +} + +RID TextureStorage::texture_create() { + ERR_FAIL_COND_V(!_is_main_thread(), RID()); + + Texture *texture = memnew(Texture); + ERR_FAIL_COND_V(!texture, RID()); + glGenTextures(1, &texture->tex_id); + texture->active = false; + texture->total_data_size = 0; + + return texture_owner.make_rid(texture); +} + +RID TextureStorage::texture_allocate() { + RID id = texture_create(); + ERR_FAIL_COND_V(id == RID(), id); + return id; +} + +void TextureStorage::texture_free(RID p_rid) { + Texture *t = texture_owner.get_or_null(p_rid); + + // can't free a render target texture + ERR_FAIL_COND(t->render_target); + if (t->canvas_texture) { + memdelete(t->canvas_texture); + } + + // info.texture_mem -= t->total_data_size; // TODO make this work again!! + texture_owner.free(p_rid); + memdelete(t); +} + +void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + int w = p_image->get_width(); + int h = p_image->get_height(); + + _texture_allocate_internal(p_texture, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0); + texture_set_data(p_texture, p_image); +} + +void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { +} + +void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { +} + +void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) { + texture_set_proxy(p_texture, p_base); +} + +//RID TextureStorage::texture_2d_create(const Ref<Image> &p_image) { +// RID id = texture_create(); +// ERR_FAIL_COND_V(id == RID(), id); + +// int w = p_image->get_width(); +// int h = p_image->get_height(); + +// texture_allocate(id, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0); + +// texture_set_data(id, p_image); + +// return id; +//} + +//RID TextureStorage::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { +// return RID(); +//} + +//void TextureStorage::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) { +// // only 1 layer so far +// texture_set_data(p_texture, p_image); +//} + +void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { + // only 1 layer so far + texture_set_data(p_texture, p_image); +} + +void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { +} + +void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) { +} + +void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { +} + +Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + + /* +#ifdef TOOLS_ENABLED + if (tex->image_cache_2d.is_valid()) { + return tex->image_cache_2d; + } +#endif + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instance(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + tex->image_cache_2d = image; + } +#endif +*/ + ERR_FAIL_COND_V(!tex->images.size(), Ref<Image>()); + + return tex->images[0]; + + // return image; + + // return Ref<Image>(); +} + +void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { + Texture *tex_to = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex_to); + Texture *tex_from = texture_owner.get_or_null(p_by_texture); + ERR_FAIL_COND(!tex_from); + + tex_to->destroy(); + tex_to->copy_from(*tex_from); + + // copy image data and upload to GL + tex_to->images.resize(tex_from->images.size()); + + for (int n = 0; n < tex_from->images.size(); n++) { + texture_set_data(p_texture, tex_from->images[n], n); + } + + texture_free(p_by_texture); +} + +void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND(!texture); + ERR_FAIL_COND(texture->render_target); + + ERR_FAIL_COND(p_width <= 0 || p_width > 16384); + ERR_FAIL_COND(p_height <= 0 || p_height > 16384); + //real texture size is in alloc width and height + texture->width = p_width; + texture->height = p_height; +} + +void TextureStorage::texture_set_path(RID p_texture, const String &p_path) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + texture->path = p_path; +} + +String TextureStorage::texture_get_path(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!texture, ""); + + return texture->path; +} + +void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + texture->detect_3d = p_callback; + texture->detect_3d_ud = p_userdata; +} + +void TextureStorage::texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + texture->detect_srgb = p_callback; + texture->detect_srgb_ud = p_userdata; +} + +void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + texture->detect_normal = p_callback; + texture->detect_normal_ud = p_userdata; +} + +void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) { + List<RID> textures; + texture_owner.get_owned_list(&textures); + + for (List<RID>::Element *E = textures.front(); E; E = E->next()) { + Texture *t = texture_owner.get_or_null(E->get()); + if (!t) { + continue; + } + RS::TextureInfo tinfo; + tinfo.path = t->path; + tinfo.format = t->format; + tinfo.width = t->alloc_width; + tinfo.height = t->alloc_height; + tinfo.depth = 0; + tinfo.bytes = t->total_data_size; + r_info->push_back(tinfo); + } +} + +void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + texture->redraw_if_visible = p_enable; +} + +Size2 TextureStorage::texture_size_with_proxy(RID p_texture) { + const Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!texture, Size2()); + if (texture->proxy) { + return Size2(texture->proxy->width, texture->proxy->height); + } else { + return Size2(texture->width, texture->height); + } +} + +// example use in 3.2 +// VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid); + +// p_proxy is the source (pre-existing) texture? +// and p_texture is the one that is being made into a proxy? +//This naming is confusing. Comments!!! + +// The naming of the parameters seemed to be reversed? +// The p_proxy is the source texture +// and p_texture is actually the proxy???? + +void TextureStorage::texture_set_proxy(RID p_texture, RID p_proxy) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + if (texture->proxy) { + texture->proxy->proxy_owners.erase(texture); + texture->proxy = nullptr; + } + + if (p_proxy.is_valid()) { + Texture *proxy = texture_owner.get_or_null(p_proxy); + ERR_FAIL_COND(!proxy); + ERR_FAIL_COND(proxy == texture); + proxy->proxy_owners.insert(texture); + texture->proxy = proxy; + } +} + +void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) { + Config *config = Config::get_singleton(); + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND(!_is_main_thread()); + + 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 + return; + } + ERR_FAIL_COND(!texture->active); + ERR_FAIL_COND(texture->render_target); + ERR_FAIL_COND(p_image.is_null()); + ERR_FAIL_COND(texture->format != p_image->get_format()); + + ERR_FAIL_COND(!p_image->get_width()); + ERR_FAIL_COND(!p_image->get_height()); + + // ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL); + + GLenum type; + GLenum format; + GLenum internal_format; + bool compressed = false; + + if (config->keep_original_textures && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { + texture->images.write[p_layer] = p_image; + } + + // print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height())); + + Image::Format real_format; + Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2); + + if (texture->resize_to_po2) { + if (p_image->is_compressed()) { + ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage."); + } + + if (img == p_image) { + img = img->duplicate(); + } + img->resize_to_po2(false); + } + + if (config->shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) { + texture->alloc_height = MAX(1, texture->alloc_height / 2); + texture->alloc_width = MAX(1, texture->alloc_width / 2); + + if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) { + img->shrink_x2(); + } else if (img->get_format() <= Image::FORMAT_RGBA8) { + img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); + } + } + + GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D; + + texture->data_size = img->get_data().size(); + Vector<uint8_t> read = img->get_data(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + texture->ignore_mipmaps = compressed && !img->has_mipmaps(); + + // set filtering and repeat state + _texture_set_state_from_flags(texture); + + //set swizle for older format compatibility +#ifdef GLES_OVER_GL + switch (texture->format) { + case Image::FORMAT_L8: { + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE); + + } break; + case Image::FORMAT_LA8: { + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN); + } break; + default: { + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE); + glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); + + } break; + } +#endif + + int mipmaps = ((texture->flags & TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; + + int w = img->get_width(); + int h = img->get_height(); + + int tsize = 0; + + for (int i = 0; i < mipmaps; i++) { + int size, ofs; + img->get_mipmap_offset_and_size(i, ofs, size); + + if (compressed) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + int bw = w; + int bh = h; + + glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]); + } else { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (texture->flags & 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]); + } + } + + tsize += size; + + w = MAX(1, w >> 1); + h = MAX(1, h >> 1); + } + + // info.texture_mem -= texture->total_data_size; // TODO make this work again!! + texture->total_data_size = tsize; + // info.texture_mem += texture->total_data_size; // TODO make this work again!! + + // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem); + + texture->stored_cube_sides |= (1 << p_layer); + + if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RenderingDevice::TEXTURE_TYPE_CUBE || texture->stored_cube_sides == (1 << 6) - 1)) { + //generate mipmaps if they were requested and the image does not contain them + glGenerateMipmap(texture->target); + } + + texture->mipmaps = mipmaps; +} + +void TextureStorage::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) { + // TODO + ERR_PRINT("Not implemented (ask Karroffel to do it :p)"); +} + +/* +Ref<Image> TextureStorage::texture_get_data(RID p_texture, int p_layer) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, Ref<Image>()); + ERR_FAIL_COND_V(!texture->active, Ref<Image>()); + ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>()); + + if (texture->type == RS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) { + return texture->images[p_layer]; + } + +#ifdef GLES_OVER_GL + + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + bool compressed; + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, false); + + PoolVector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + glActiveTexture(GL_TEXTURE0); + + glBindTexture(texture->target, texture->tex_id); + + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + for (int i = 0; i < texture->mipmaps; i++) { + int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i); + + if (texture->compressed) { + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glGetCompressedTexImage(texture->target, i, &wb[ofs]); + } else { + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]); + } + } + + wb.release(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, real_format, data)); + + return Ref<Image>(img); +#else + + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + bool compressed; + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, texture->resize_to_po2); + + PoolVector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + GLuint temp_framebuffer; + glGenFramebuffers(1, &temp_framebuffer); + + GLuint temp_color_texture; + glGenTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); + + glBindTexture(GL_TEXTURE_2D, temp_color_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + shaders.copy.bind(); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + bind_quad_array(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + glDeleteTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &temp_framebuffer); + + wb.release(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); + +#endif +} +*/ + +void TextureStorage::texture_set_flags(RID p_texture, uint32_t p_flags) { + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!texture); + + bool had_mipmaps = texture->flags & TEXTURE_FLAG_MIPMAPS; + + texture->flags = p_flags; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + // set filtering and repeat state + _texture_set_state_from_flags(texture); + + if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { + if (!had_mipmaps && texture->mipmaps == 1) { + glGenerateMipmap(texture->target); + } + } +} + +uint32_t TextureStorage::texture_get_flags(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->flags; +} + +Image::Format TextureStorage::texture_get_format(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, Image::FORMAT_L8); + + return texture->format; +} + +RenderingDevice::TextureType TextureStorage::texture_get_type(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, RenderingDevice::TEXTURE_TYPE_2D); + + return texture->type; +} + +uint32_t TextureStorage::texture_get_texid(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->tex_id; +} + +uint32_t TextureStorage::texture_get_width(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->width; +} + +uint32_t TextureStorage::texture_get_height(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->height; +} + +uint32_t TextureStorage::texture_get_depth(RID p_texture) const { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->depth; +} + +void TextureStorage::texture_bind(RID p_texture, uint32_t p_texture_no) { + Texture *texture = texture_owner.get_or_null(p_texture); + + ERR_FAIL_COND(!texture); + + glActiveTexture(GL_TEXTURE0 + p_texture_no); + glBindTexture(texture->target, texture->tex_id); +} + +void TextureStorage::texture_set_shrink_all_x2_on_set_data(bool p_enable) { + Config::get_singleton()->shrink_textures_x2 = p_enable; +} + +RID TextureStorage::texture_create_radiance_cubemap(RID p_source, int p_resolution) const { + return RID(); +} + +void TextureStorage::textures_keep_original(bool p_enable) { + Config::get_singleton()->keep_original_textures = p_enable; +} + +#endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h new file mode 100644 index 0000000000..8a921fbe10 --- /dev/null +++ b/drivers/gles3/storage/texture_storage.h @@ -0,0 +1,389 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_GLES3_H +#define TEXTURE_STORAGE_GLES3_H + +#ifdef GLES3_ENABLED + +#include "canvas_texture_storage.h" +#include "config.h" +#include "core/os/os.h" +#include "core/templates/rid_owner.h" +#include "render_target_storage.h" +#include "servers/rendering/storage/texture_storage.h" + +namespace GLES3 { + +#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB +#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD +#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE +#define _EXT_ETC1_RGB8_OES 0x8D64 + +#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F + +#define _GL_TEXTURE_EXTERNAL_OES 0x8D65 + +#ifdef GLES_OVER_GL +#define _GL_HALF_FLOAT_OES 0x140B +#else +#define _GL_HALF_FLOAT_OES 0x8D61 +#endif + +#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F + +#define _RED_OES 0x1903 + +#define _DEPTH_COMPONENT24_OES 0x81A6 + +#ifndef GLES_OVER_GL +#define glClearDepth glClearDepthf +#endif //!GLES_OVER_GL + +enum OpenGLTextureFlags { + TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available + TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping + TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter + TEXTURE_FLAG_ANISOTROPIC_FILTER = 8, + TEXTURE_FLAG_CONVERT_TO_LINEAR = 16, + TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored + TEXTURE_FLAG_USED_FOR_STREAMING = 2048, + TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER +}; + +struct Texture { + RID self; + + Texture *proxy; + Set<Texture *> proxy_owners; + + String path; + uint32_t flags; + int width, height, depth; + int alloc_width, alloc_height; + Image::Format format; + RenderingDevice::TextureType type; + + GLenum target; + GLenum gl_format_cache; + GLenum gl_internal_format_cache; + GLenum gl_type_cache; + + int data_size; + int total_data_size; + bool ignore_mipmaps; + + bool compressed; + + bool srgb; + + int mipmaps; + + bool resize_to_po2; + + bool active; + GLenum tex_id; + + uint16_t stored_cube_sides; + + RenderTarget *render_target; + + Vector<Ref<Image>> images; + + bool redraw_if_visible; + + RS::TextureDetectCallback detect_3d; + void *detect_3d_ud; + + RS::TextureDetectCallback detect_srgb; + void *detect_srgb_ud; + + RS::TextureDetectCallback detect_normal; + void *detect_normal_ud; + + CanvasTexture *canvas_texture = nullptr; + + // some silly opengl shenanigans where + // texture coords start from bottom left, means we need to draw render target textures upside down + // to be compatible with vulkan etc. + bool is_upside_down() const { + if (proxy) { + return proxy->is_upside_down(); + } + + return render_target != nullptr; + } + + Texture() { + create(); + } + + _ALWAYS_INLINE_ Texture *get_ptr() { + if (proxy) { + return proxy; //->get_ptr(); only one level of indirection, else not inlining possible. + } else { + return this; + } + } + + ~Texture() { + destroy(); + + if (tex_id != 0) { + glDeleteTextures(1, &tex_id); + } + } + + void copy_from(const Texture &o) { + proxy = o.proxy; + flags = o.flags; + width = o.width; + height = o.height; + alloc_width = o.alloc_width; + alloc_height = o.alloc_height; + format = o.format; + type = o.type; + target = o.target; + data_size = o.data_size; + total_data_size = o.total_data_size; + ignore_mipmaps = o.ignore_mipmaps; + compressed = o.compressed; + mipmaps = o.mipmaps; + resize_to_po2 = o.resize_to_po2; + active = o.active; + tex_id = o.tex_id; + stored_cube_sides = o.stored_cube_sides; + render_target = o.render_target; + redraw_if_visible = o.redraw_if_visible; + detect_3d = o.detect_3d; + detect_3d_ud = o.detect_3d_ud; + detect_srgb = o.detect_srgb; + detect_srgb_ud = o.detect_srgb_ud; + detect_normal = o.detect_normal; + detect_normal_ud = o.detect_normal_ud; + + images.clear(); + } + + void create() { + proxy = nullptr; + flags = 0; + width = 0; + height = 0; + alloc_width = 0; + alloc_height = 0; + format = Image::FORMAT_L8; + type = RenderingDevice::TEXTURE_TYPE_2D; + target = 0; + data_size = 0; + total_data_size = 0; + ignore_mipmaps = false; + compressed = false; + mipmaps = 0; + resize_to_po2 = false; + active = false; + tex_id = 0; + stored_cube_sides = 0; + render_target = nullptr; + redraw_if_visible = false; + detect_3d = nullptr; + detect_3d_ud = nullptr; + detect_srgb = nullptr; + detect_srgb_ud = nullptr; + detect_normal = nullptr; + detect_normal_ud = nullptr; + } + void destroy() { + images.clear(); + + for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) { + E->get()->proxy = nullptr; + } + + if (proxy) { + proxy->proxy_owners.erase(this); + } + } + + // texture state + void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) { + if (p_filter == state_filter) { + return; + } + state_filter = p_filter; + GLint pmin = GL_LINEAR; // param min + GLint pmag = GL_LINEAR; // param mag + switch (state_filter) { + default: { + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { + pmin = GL_LINEAR_MIPMAP_LINEAR; + pmag = GL_LINEAR; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { + pmin = GL_NEAREST; + pmag = GL_NEAREST; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { + pmin = GL_NEAREST_MIPMAP_NEAREST; + pmag = GL_NEAREST; + } break; + } + glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin); + glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag); + } + void GLSetRepeat(GLenum p_target, RS::CanvasItemTextureRepeat p_repeat) { + if (p_repeat == state_repeat) { + return; + } + state_repeat = p_repeat; + GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat + switch (state_repeat) { + default: { + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { + prep = GL_REPEAT; + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { + prep = GL_MIRRORED_REPEAT; + } break; + } + glTexParameteri(p_target, GL_TEXTURE_WRAP_S, prep); + glTexParameteri(p_target, GL_TEXTURE_WRAP_T, prep); + } + +private: + RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; + RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; +}; + +class TextureStorage : public RendererTextureStorage { +private: + static TextureStorage *singleton; + + Thread::ID _main_thread_id = 0; + bool _is_main_thread(); + + mutable RID_PtrOwner<Texture> texture_owner; + + Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const; + void _texture_set_state_from_flags(Texture *p_tex); + + void texture_set_proxy(RID p_texture, RID p_proxy); + +public: + static TextureStorage *get_singleton(); + + TextureStorage(); + virtual ~TextureStorage(); + + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + RID make_rid(Texture *p_texture) { return texture_owner.make_rid(p_texture); }; + + void set_main_thread_id(Thread::ID p_id); + + virtual bool can_create_resources_async() const override; + + RID texture_create(); + void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); + + virtual RID texture_allocate() override; + virtual void texture_free(RID p_rid) override; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{}; + virtual void texture_proxy_update(RID p_proxy, RID p_base) override{}; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) override; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; + virtual void texture_3d_placeholder_initialize(RID p_texture) override; + + virtual Ref<Image> texture_2d_get(RID p_texture) const override; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }; + + virtual void texture_replace(RID p_texture, RID p_by_texture) override; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override; + + virtual void texture_set_path(RID p_texture, const String &p_path) override; + virtual String texture_get_path(RID p_texture) const override; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + void texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{}; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override; + + virtual Size2 texture_size_with_proxy(RID p_proxy) override; + + void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); + void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0); + //Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const; + void texture_set_flags(RID p_texture, uint32_t p_flags); + uint32_t texture_get_flags(RID p_texture) const; + Image::Format texture_get_format(RID p_texture) const; + RenderingDevice::TextureType texture_get_type(RID p_texture) const; + uint32_t texture_get_texid(RID p_texture) const; + uint32_t texture_get_width(RID p_texture) const; + uint32_t texture_get_height(RID p_texture) const; + uint32_t texture_get_depth(RID p_texture) const; + void texture_bind(RID p_texture, uint32_t p_texture_no); + void texture_set_shrink_all_x2_on_set_data(bool p_enable); + RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const; + void textures_keep_original(bool p_enable); +}; + +} // namespace GLES3 + +#endif // !GLES3_ENABLED + +#endif // !TEXTURE_STORAGE_GLES3_H diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index b86b5f1579..a7e3ed95e5 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -1176,7 +1176,7 @@ uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_form } w = MAX(blockw, w >> 1); h = MAX(blockh, h >> 1); - d = MAX(1, d >> 1); + d = MAX(1u, d >> 1); } return size; @@ -1184,20 +1184,20 @@ uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_form uint32_t RenderingDeviceVulkan::get_image_required_mipmaps(uint32_t p_width, uint32_t p_height, uint32_t p_depth) { //formats and block size don't really matter here since they can all go down to 1px (even if block is larger) - int w = p_width; - int h = p_height; - int d = p_depth; + uint32_t w = p_width; + uint32_t h = p_height; + uint32_t d = p_depth; - int mipmaps = 1; + uint32_t mipmaps = 1; while (true) { if (w == 1 && h == 1 && d == 1) { break; } - w = MAX(1, w >> 1); - h = MAX(1, h >> 1); - d = MAX(1, d >> 1); + w = MAX(1u, w >> 1); + h = MAX(1u, h >> 1); + d = MAX(1u, d >> 1); mipmaps++; } @@ -2556,8 +2556,8 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co } mipmap_offset = image_total; - logic_width = MAX(1, logic_width >> 1); - logic_height = MAX(1, logic_height >> 1); + logic_width = MAX(1u, logic_width >> 1); + logic_height = MAX(1u, logic_height >> 1); } //barrier to restore layout @@ -2755,9 +2755,9 @@ Vector<uint8_t> RenderingDeviceVulkan::texture_get_data(RID p_texture, uint32_t vkCmdCopyImageToBuffer(command_buffer, tex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, tmp_buffer.buffer, 1, &buffer_image_copy); - computed_w = MAX(1, computed_w >> 1); - computed_h = MAX(1, computed_h >> 1); - computed_d = MAX(1, computed_d >> 1); + computed_w = MAX(1u, computed_w >> 1); + computed_h = MAX(1u, computed_h >> 1); + computed_d = MAX(1u, computed_d >> 1); offset += size; } @@ -9050,10 +9050,10 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de // Note: If adding new project settings here, also duplicate their definition in // rendering_server.cpp for headless doctool. staging_buffer_block_size = GLOBAL_DEF("rendering/vulkan/staging_buffer/block_size_kb", 256); - staging_buffer_block_size = MAX(4, staging_buffer_block_size); + staging_buffer_block_size = MAX(4u, staging_buffer_block_size); staging_buffer_block_size *= 1024; //kb -> bytes staging_buffer_max_size = GLOBAL_DEF("rendering/vulkan/staging_buffer/max_size_mb", 128); - staging_buffer_max_size = MAX(1, staging_buffer_max_size); + staging_buffer_max_size = MAX(1u, staging_buffer_max_size); staging_buffer_max_size *= 1024 * 1024; if (staging_buffer_max_size < staging_buffer_block_size * 4) { diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 92d53cc005..aab9743c43 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -1122,8 +1122,6 @@ void ActionMapEditor::use_external_search_box(LineEdit *p_searchbox) { } ActionMapEditor::ActionMapEditor() { - show_builtin_actions = false; - // Main Vbox Container VBoxContainer *main_vbox = memnew(VBoxContainer); main_vbox->set_anchors_and_offsets_preset(PRESET_WIDE); diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h index de24d3ee1f..34c70c942e 100644 --- a/editor/action_map_editor.h +++ b/editor/action_map_editor.h @@ -164,7 +164,7 @@ private: // Filtering and Adding actions - bool show_builtin_actions; + bool show_builtin_actions = false; CheckButton *show_builtin_actions_checkbutton; LineEdit *action_list_search; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 11995e8cb4..e61a1aae9c 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1814,13 +1814,6 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { - if (hsize_rect.has_point(mm->get_position())) { - // Change the cursor to indicate that the track name column's width can be adjusted - set_default_cursor_shape(Control::CURSOR_HSIZE); - } else { - set_default_cursor_shape(Control::CURSOR_ARROW); - } - if (dragging_hsize) { int ofs = mm->get_position().x - dragging_hsize_from; name_limit = dragging_hsize_at + ofs; @@ -1836,6 +1829,15 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) { } } +Control::CursorShape AnimationTimelineEdit::get_cursor_shape(const Point2 &p_pos) const { + if (dragging_hsize || hsize_rect.has_point(p_pos)) { + // Indicate that the track name column's width can be adjusted + return Control::CURSOR_HSIZE; + } else { + return get_default_cursor_shape(); + } +} + void AnimationTimelineEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { // Timeline has no vertical scroll, so we change it to horizontal. p_scroll_vec.x += p_scroll_vec.y; @@ -1884,8 +1886,6 @@ void AnimationTimelineEdit::_bind_methods() { } AnimationTimelineEdit::AnimationTimelineEdit() { - use_fps = false; - editing = false; name_limit = 150 * EDSCALE; zoom = nullptr; track_edit = nullptr; @@ -1933,9 +1933,6 @@ AnimationTimelineEdit::AnimationTimelineEdit() { add_track->get_popup()->connect("index_pressed", callable_mp(this, &AnimationTimelineEdit::_track_added)); len_hb->hide(); - dragging_timeline = false; - dragging_hsize = false; - panner.instantiate(); panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_scroll_callback), callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback)); @@ -3149,13 +3146,8 @@ AnimationTrackEdit::AnimationTrackEdit() { path = nullptr; path_popup = nullptr; menu = nullptr; - clicking_on_name = false; dropping_at = 0; - in_group = false; - - moving_selection_attempt = false; - moving_selection = false; select_single_attempt = -1; play_position_pos = 0; @@ -6314,8 +6306,6 @@ AnimationTrackEditor::AnimationTrackEditor() { add_child(method_selector); method_selector->connect("selected", callable_mp(this, &AnimationTrackEditor::_add_method_key)); - insert_queue = false; - insert_confirm = memnew(ConfirmationDialog); add_child(insert_confirm); insert_confirm->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_confirm_insert_list)); @@ -6333,8 +6323,6 @@ AnimationTrackEditor::AnimationTrackEditor() { insert_confirm_reset->set_text(TTR("Create RESET Track(s)", "")); insert_confirm_reset->set_pressed(EDITOR_GET("editors/animation/default_create_reset_tracks")); ichb->add_child(insert_confirm_reset); - keying = false; - moving_selection = false; key_edit = nullptr; multi_key_edit = nullptr; @@ -6344,7 +6332,6 @@ AnimationTrackEditor::AnimationTrackEditor() { box_selection->set_mouse_filter(MOUSE_FILTER_IGNORE); box_selection->hide(); box_selection->connect("draw", callable_mp(this, &AnimationTrackEditor::_box_selection_draw)); - box_selecting = false; // Default Plugins. @@ -6441,7 +6428,6 @@ AnimationTrackEditor::AnimationTrackEditor() { track_copy_select->set_hide_root(true); track_vbox->add_child(track_copy_select); track_copy_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_COPY_TRACKS_CONFIRM)); - animation_changing_awaiting_update = false; } AnimationTrackEditor::~AnimationTrackEditor() { diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 5f803ae796..1baebc469e 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -77,16 +77,16 @@ class AnimationTimelineEdit : public Range { UndoRedo *undo_redo; Rect2 hsize_rect; - bool editing; - bool use_fps; + bool editing = false; + bool use_fps = false; Ref<ViewPanner> panner; void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); void _pan_callback(Vector2 p_scroll_vec); void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); - bool dragging_timeline; - bool dragging_hsize; + bool dragging_timeline = false; + bool dragging_hsize = false; float dragging_hsize_from; float dragging_hsize_at; @@ -121,6 +121,8 @@ public: void set_hscroll(HScrollBar *p_hscroll); + virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override; + AnimationTimelineEdit(); }; @@ -169,7 +171,7 @@ class AnimationTrackEdit : public Control { PopupMenu *menu; - bool clicking_on_name; + bool clicking_on_name = false; void _zoom_changed(); @@ -186,12 +188,12 @@ class AnimationTrackEdit : public Control { mutable int dropping_at; float insert_at_pos; - bool moving_selection_attempt; + bool moving_selection_attempt = false; int select_single_attempt; - bool moving_selection; + bool moving_selection = false; float moving_selection_from_ofs; - bool in_group; + bool in_group = false; AnimationTrackEditor *editor; protected: @@ -310,7 +312,7 @@ class AnimationTrackEditor : public VBoxContainer { Vector<AnimationTrackEdit *> track_edits; Vector<AnimationTrackEditGroup *> groups; - bool animation_changing_awaiting_update; + bool animation_changing_awaiting_update = false; void _animation_update(); int _get_track_selected(); void _animation_changed(); @@ -340,7 +342,7 @@ class AnimationTrackEditor : public VBoxContainer { int adding_track_type; NodePath adding_track_path; - bool keying; + bool keying = false; struct InsertData { Animation::TrackType type; @@ -355,7 +357,7 @@ class AnimationTrackEditor : public VBoxContainer { CheckBox *insert_confirm_bezier; CheckBox *insert_confirm_reset; ConfirmationDialog *insert_confirm; - bool insert_queue; + bool insert_queue = false; List<InsertData> insert_data; void _query_insert(const InsertData &p_id); @@ -410,7 +412,7 @@ class AnimationTrackEditor : public VBoxContainer { void _key_selected(int p_key, bool p_single, int p_track); void _key_deselected(int p_key, int p_track); - bool moving_selection; + bool moving_selection = false; float moving_selection_offset; void _move_selection_begin(); void _move_selection(float p_offset); @@ -425,7 +427,7 @@ class AnimationTrackEditor : public VBoxContainer { Control *box_selection; void _box_selection_draw(); - bool box_selecting; + bool box_selecting = false; Vector2 box_selecting_from; Rect2 box_select_rect; void _scroll_input(const Ref<InputEvent> &p_event); diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index e87678a51b..2ad8b2d2a4 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -1080,12 +1080,7 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) { len_resizing_index = i; } } - - if (use_hsize_cursor) { - set_default_cursor_shape(CURSOR_HSIZE); - } else { - set_default_cursor_shape(CURSOR_ARROW); - } + over_drag_position = use_hsize_cursor; } if (len_resizing && mm.is_valid()) { @@ -1097,7 +1092,7 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && get_default_cursor_shape() == CURSOR_HSIZE) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && over_drag_position) { len_resizing = true; len_resizing_start = mb->is_shift_pressed(); len_resizing_from_px = mb->get_position().x; @@ -1124,7 +1119,6 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) { get_undo_redo()->commit_action(); } - len_resizing = false; len_resizing_index = -1; update(); accept_event(); @@ -1134,6 +1128,14 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) { AnimationTrackEdit::gui_input(p_event); } +Control::CursorShape AnimationTrackEditTypeAudio::get_cursor_shape(const Point2 &p_pos) const { + if (over_drag_position || len_resizing) { + return Control::CURSOR_HSIZE; + } else { + return get_default_cursor_shape(); + } +} + //////////////////// /// SUB ANIMATION /// diff --git a/editor/animation_track_editor_plugins.h b/editor/animation_track_editor_plugins.h index 271c1a000b..adfe517356 100644 --- a/editor/animation_track_editor_plugins.h +++ b/editor/animation_track_editor_plugins.h @@ -81,7 +81,7 @@ class AnimationTrackEditSpriteFrame : public AnimationTrackEdit { GDCLASS(AnimationTrackEditSpriteFrame, AnimationTrackEdit); ObjectID id; - bool is_coords; + bool is_coords = false; public: virtual int get_key_height() const override; @@ -92,7 +92,7 @@ public: void set_node(Object *p_object); void set_as_coords(); - AnimationTrackEditSpriteFrame() { is_coords = false; } + AnimationTrackEditSpriteFrame() {} }; class AnimationTrackEditSubAnim : public AnimationTrackEdit { @@ -114,11 +114,12 @@ class AnimationTrackEditTypeAudio : public AnimationTrackEdit { void _preview_changed(ObjectID p_which); - bool len_resizing; + bool len_resizing = false; bool len_resizing_start; int len_resizing_index; float len_resizing_from_px; float len_resizing_rel; + bool over_drag_position = false; protected: static void _bind_methods(); @@ -134,6 +135,8 @@ public: virtual bool is_key_selectable_by_distance() const override; virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) override; + virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override; + AnimationTrackEditTypeAudio(); }; diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 22d3155159..2896fda2d2 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -618,8 +618,6 @@ void FindReplaceBar::_bind_methods() { FindReplaceBar::FindReplaceBar() { results_count = -1; - replace_all_mode = false; - preserve_cursor = false; vbc_lineedit = memnew(VBoxContainer); add_child(vbc_lineedit); @@ -1887,8 +1885,6 @@ CodeTextEditor::CodeTextEditor() { error_button->set_default_cursor_shape(CURSOR_POINTING_HAND); error_button->connect("pressed", callable_mp(this, &CodeTextEditor::_error_button_pressed)); error_button->set_tooltip(TTR("Errors")); - - is_errors_panel_opened = false; set_error_count(0); // Warnings @@ -1899,8 +1895,6 @@ CodeTextEditor::CodeTextEditor() { warning_button->set_default_cursor_shape(CURSOR_POINTING_HAND); warning_button->connect("pressed", callable_mp(this, &CodeTextEditor::_warning_button_pressed)); warning_button->set_tooltip(TTR("Warnings")); - - is_warnings_panel_opened = false; set_warning_count(0); // Line and column diff --git a/editor/code_editor.h b/editor/code_editor.h index 24316bf8b0..d7025e7fd9 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -86,8 +86,8 @@ class FindReplaceBar : public HBoxContainer { int result_col; int results_count; - bool replace_all_mode; - bool preserve_cursor; + bool replace_all_mode = false; + bool preserve_cursor = false; void _get_search_from(int &r_line, int &r_col); void _update_results_count(); @@ -206,8 +206,8 @@ protected: void _notification(int); static void _bind_methods(); - bool is_warnings_panel_opened; - bool is_errors_panel_opened; + bool is_warnings_panel_opened = false; + bool is_errors_panel_opened = false; public: void trim_trailing_whitespace(); diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index 32e3c3679a..4e2e8634e5 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -396,6 +396,7 @@ void EditorProfiler::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: + case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index 885d8bd5c4..2f33a0bc31 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -67,7 +67,7 @@ void EditorVisualProfiler::add_frame_metric(const Metric &p_metric) { updating_frame = true; cursor_metric_edit->set_max(frame_metrics[last_metric].frame_number); - cursor_metric_edit->set_min(MAX(frame_metrics[last_metric].frame_number - frame_metrics.size(), 0)); + cursor_metric_edit->set_min(MAX(frame_metrics[last_metric].frame_number - frame_metrics.size(), 0u)); if (!seeking) { cursor_metric_edit->set_value(frame_metrics[last_metric].frame_number); @@ -426,6 +426,7 @@ void EditorVisualProfiler::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: + case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { if (is_layout_rtl()) { activate->set_icon(get_theme_icon(SNAME("PlayBackwards"), SNAME("EditorIcons"))); diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 453e9e3a0c..f6fdd5fc57 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -779,18 +779,20 @@ void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType void ScriptEditorDebugger::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - skip_breakpoints->set_icon(get_theme_icon(SNAME("DebugSkipBreakpointsOff"), SNAME("EditorIcons"))); - copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"))); - - step->set_icon(get_theme_icon(SNAME("DebugStep"), SNAME("EditorIcons"))); - next->set_icon(get_theme_icon(SNAME("DebugNext"), SNAME("EditorIcons"))); - dobreak->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons"))); - docontinue->set_icon(get_theme_icon(SNAME("DebugContinue"), SNAME("EditorIcons"))); le_set->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_live_edit_set)); le_clear->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_live_edit_clear)); error_tree->connect("item_selected", callable_mp(this, &ScriptEditorDebugger::_error_selected)); error_tree->connect("item_activated", callable_mp(this, &ScriptEditorDebugger::_error_activated)); breakpoints_tree->connect("item_activated", callable_mp(this, &ScriptEditorDebugger::_breakpoint_tree_clicked)); + [[fallthrough]]; + } + case NOTIFICATION_THEME_CHANGED: { + skip_breakpoints->set_icon(get_theme_icon(skip_breakpoints_value ? SNAME("DebugSkipBreakpointsOn") : SNAME("DebugSkipBreakpointsOff"), SNAME("EditorIcons"))); + copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"))); + step->set_icon(get_theme_icon(SNAME("DebugStep"), SNAME("EditorIcons"))); + next->set_icon(get_theme_icon(SNAME("DebugNext"), SNAME("EditorIcons"))); + dobreak->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons"))); + docontinue->set_icon(get_theme_icon(SNAME("DebugContinue"), SNAME("EditorIcons"))); vmem_refresh->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); vmem_export->set_icon(get_theme_icon(SNAME("Save"), SNAME("EditorIcons"))); search->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 1802bdec93..95b3a02631 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -749,12 +749,11 @@ void OrphanResourcesDialog::_find_to_delete(TreeItem *p_item, List<String> &path } void OrphanResourcesDialog::_delete_confirm() { - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); for (const String &E : paths) { da->remove(E); EditorFileSystem::get_singleton()->update_file(E); } - memdelete(da); refresh(); } diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index a9d18e9dcc..adad8fdba8 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -685,6 +685,11 @@ void DocTools::generate(bool p_basic_types) { for (int j = 0; j < Variant::OP_AND; j++) { // Showing above 'and' is pretty confusing and there are a lot of variations. for (int k = 0; k < Variant::VARIANT_MAX; k++) { + // Prevent generating for comparison with null. + if (Variant::Type(k) == Variant::NIL && (Variant::Operator(j) == Variant::OP_EQUAL || Variant::Operator(j) == Variant::OP_NOT_EQUAL)) { + continue; + } + Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(j), Variant::Type(i), Variant::Type(k)); if (rt != Variant::NIL) { // Has operator. // Skip String % operator as it's registered separately for each Variant arg type, diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 3835399c99..f1674c47c5 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -277,10 +277,8 @@ void EditorAssetInstaller::ok_pressed() { dirpath = dirpath.substr(0, dirpath.length() - 1); } - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); da->make_dir(dirpath); - memdelete(da); - } else { Vector<uint8_t> data; data.resize(info.uncompressed_size); @@ -358,7 +356,5 @@ EditorAssetInstaller::EditorAssetInstaller() { get_ok_button()->set_text(TTR("Install")); set_title(TTR("Asset Installer")); - updating = false; - set_hide_on_ok(true); } diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h index f5993f73e7..58c232f351 100644 --- a/editor/editor_asset_installer.h +++ b/editor/editor_asset_installer.h @@ -42,7 +42,7 @@ class EditorAssetInstaller : public ConfirmationDialog { String asset_name; AcceptDialog *error; Map<String, TreeItem *> status_map; - bool updating; + bool updating = false; void _item_edited(); void _check_propagated_to_item(Object *p_obj, int column); virtual void ok_pressed() override; diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index e1198026b6..4474d6893a 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -771,9 +771,7 @@ void EditorAudioBus::_bind_methods() { EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { buses = p_buses; - updating_bus = false; is_master = p_is_master; - hovering_drop = false; set_tooltip(TTR("Drag & drop to rearrange.")); @@ -925,7 +923,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { String name = E.operator String().replace("AudioEffect", ""); effect_options->add_item(name); - effect_options->set_item_metadata(effect_options->get_item_count() - 1, E); + effect_options->set_item_metadata(-1, E); } bus_options = memnew(MenuButton); @@ -992,7 +990,6 @@ void EditorAudioBusDrop::_bind_methods() { } EditorAudioBusDrop::EditorAudioBusDrop() { - hovering_drop = false; } void EditorAudioBuses::_update_buses() { diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h index a830a2719d..0020b61370 100644 --- a/editor/editor_audio_buses.h +++ b/editor/editor_audio_buses.h @@ -85,9 +85,9 @@ class EditorAudioBus : public PanelContainer { Tree *effects; - bool updating_bus; + bool updating_bus = false; bool is_master; - mutable bool hovering_drop; + mutable bool hovering_drop = false; virtual void gui_input(const Ref<InputEvent> &p_event) override; void _effects_gui_input(Ref<InputEvent> p_event); @@ -140,7 +140,7 @@ class EditorAudioBusDrop : public Control { virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const override; virtual void drop_data(const Point2 &p_point, const Variant &p_data) override; - mutable bool hovering_drop; + mutable bool hovering_drop = false; protected: static void _bind_methods(); diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 829948d3cb..b37b06748d 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -35,6 +35,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/filesystem_dock.h" #include "project_settings_editor.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" @@ -63,6 +64,28 @@ void EditorAutoloadSettings::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { browse_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } break; + + case NOTIFICATION_VISIBILITY_CHANGED: { + FileSystemDock *dock = FileSystemDock::get_singleton(); + + if (dock != nullptr) { + ScriptCreateDialog *dialog = dock->get_script_create_dialog(); + + if (dialog != nullptr) { + Callable script_created = callable_mp(this, &EditorAutoloadSettings::_script_created); + + if (is_visible_in_tree()) { + if (!dialog->is_connected(SNAME("script_created"), script_created)) { + dialog->connect("script_created", script_created); + } + } else { + if (dialog->is_connected(SNAME("script_created"), script_created)) { + dialog->disconnect("script_created", script_created); + } + } + } + } + } break; } } @@ -134,12 +157,22 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin } void EditorAutoloadSettings::_autoload_add() { - if (autoload_add(autoload_add_name->get_text(), autoload_add_path->get_text())) { - autoload_add_path->set_text(""); - } + if (autoload_add_path->get_text().is_empty()) { + ScriptCreateDialog *dialog = FileSystemDock::get_singleton()->get_script_create_dialog(); + String fpath = path; + if (!fpath.ends_with("/")) { + fpath = fpath.get_base_dir(); + } + dialog->config("Node", fpath.plus_file(vformat("%s.gd", autoload_add_name->get_text().camelcase_to_underscore())), false, false); + dialog->popup_centered(); + } else { + if (autoload_add(autoload_add_name->get_text(), autoload_add_path->get_text())) { + autoload_add_path->set_text(""); + } - autoload_add_name->set_text(""); - add_autoload->set_disabled(true); + autoload_add_name->set_text(""); + add_autoload->set_disabled(true); + } } void EditorAutoloadSettings::_autoload_selected() { @@ -351,14 +384,13 @@ void EditorAutoloadSettings::_autoload_text_submitted(const String p_name) { } void EditorAutoloadSettings::_autoload_path_text_changed(const String p_path) { - add_autoload->set_disabled( - p_path.is_empty() || !_autoload_name_is_valid(autoload_add_name->get_text(), nullptr)); + add_autoload->set_disabled(!_autoload_name_is_valid(autoload_add_name->get_text(), nullptr)); } void EditorAutoloadSettings::_autoload_text_changed(const String p_name) { String error_string; bool is_name_valid = _autoload_name_is_valid(p_name, &error_string); - add_autoload->set_disabled(autoload_add_path->get_text().is_empty() || !is_name_valid); + add_autoload->set_disabled(!is_name_valid); error_message->set_text(error_string); error_message->set_visible(!autoload_add_name->get_text().is_empty() && !is_name_valid); } @@ -540,6 +572,14 @@ void EditorAutoloadSettings::update_autoload() { updating_autoload = false; } +void EditorAutoloadSettings::_script_created(Ref<Script> p_script) { + FileSystemDock::get_singleton()->get_script_create_dialog()->hide(); + path = p_script->get_path().get_base_dir(); + autoload_add_path->set_text(p_script->get_path()); + autoload_add_name->set_text(p_script->get_path().get_file().get_basename().capitalize().replace(" ", "")); + _autoload_add(); +} + Variant EditorAutoloadSettings::get_drag_data_fw(const Point2 &p_point, Control *p_control) { if (autoload_cache.size() <= 1) { return false; @@ -833,11 +873,6 @@ EditorAutoloadSettings::EditorAutoloadSettings() { } } - autoload_changed = "autoload_changed"; - - updating_autoload = false; - selected_autoload = ""; - HBoxContainer *hbc = memnew(HBoxContainer); add_child(hbc); @@ -854,6 +889,8 @@ EditorAutoloadSettings::EditorAutoloadSettings() { autoload_add_path = memnew(LineEdit); hbc->add_child(autoload_add_path); autoload_add_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); + autoload_add_path->set_clear_button_enabled(true); + autoload_add_path->set_placeholder(vformat(TTR(R"(Set path or press "%s" to create a script.)"), TTR("Add"))); autoload_add_path->connect("text_changed", callable_mp(this, &EditorAutoloadSettings::_autoload_path_text_changed)); browse_button = memnew(Button); diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h index 044eea4245..380cadbebb 100644 --- a/editor/editor_autoload_settings.h +++ b/editor/editor_autoload_settings.h @@ -47,7 +47,8 @@ class EditorAutoloadSettings : public VBoxContainer { BUTTON_DELETE }; - String autoload_changed; + String path = "res://"; + String autoload_changed = "autoload_changed"; struct AutoloadInfo { String name; @@ -64,17 +65,16 @@ class EditorAutoloadSettings : public VBoxContainer { List<AutoloadInfo> autoload_cache; - bool updating_autoload; - int number_of_autoloads; + bool updating_autoload = false; String selected_autoload; - Tree *tree; - LineEdit *autoload_add_name; - Button *add_autoload; - LineEdit *autoload_add_path; - Label *error_message; - Button *browse_button; - EditorFileDialog *file_dialog; + Tree *tree = nullptr; + LineEdit *autoload_add_name = nullptr; + Button *add_autoload = nullptr; + LineEdit *autoload_add_path = nullptr; + Label *error_message = nullptr; + Button *browse_button = nullptr; + EditorFileDialog *file_dialog = nullptr; bool _autoload_name_is_valid(const String &p_name, String *r_error = nullptr); @@ -90,6 +90,8 @@ class EditorAutoloadSettings : public VBoxContainer { void _autoload_file_callback(const String &p_path); Node *_create_autoload(const String &p_path); + void _script_created(Ref<Script> p_script); + Variant get_drag_data_fw(const Point2 &p_point, Control *p_control); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_control) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_control); diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 69c7e9d52c..c16451f3c6 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -1206,9 +1206,6 @@ void EditorSelection::clear() { } EditorSelection::EditorSelection() { - emitted = false; - changed = false; - nl_changed = false; } EditorSelection::~EditorSelection() { diff --git a/editor/editor_data.h b/editor/editor_data.h index 0d1efc9b62..79f8227e5c 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -239,9 +239,9 @@ class EditorSelection : public Object { private: Map<Node *, Object *> selection; - bool emitted; - bool changed; - bool nl_changed; + bool emitted = false; + bool changed = false; + bool nl_changed = false; void _node_removed(Node *p_node); diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp index f181c04004..32ef87a4ab 100644 --- a/editor/editor_dir_dialog.cpp +++ b/editor/editor_dir_dialog.cpp @@ -175,8 +175,6 @@ void EditorDirDialog::_bind_methods() { } EditorDirDialog::EditorDirDialog() { - updating = false; - set_title(TTR("Choose a Directory")); set_hide_on_ok(false); @@ -206,6 +204,4 @@ EditorDirDialog::EditorDirDialog() { add_child(mkdirerr); get_ok_button()->set_text(TTR("Choose")); - - must_reload = false; } diff --git a/editor/editor_dir_dialog.h b/editor/editor_dir_dialog.h index 053c1f5503..e97b5ce8af 100644 --- a/editor/editor_dir_dialog.h +++ b/editor/editor_dir_dialog.h @@ -47,7 +47,7 @@ class EditorDirDialog : public ConfirmationDialog { Set<String> opened_paths; Tree *tree; - bool updating; + bool updating = false; void _item_collapsed(Object *p_item); void _item_activated(); @@ -58,7 +58,7 @@ class EditorDirDialog : public ConfirmationDialog { void ok_pressed() override; - bool must_reload; + bool must_reload = false; protected: void _notification(int p_what); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index d081ee05a0..02495252bc 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -566,8 +566,8 @@ void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p extra_files.push_back(ef); } -void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &tags) { - shared_objects.push_back(SharedObject(p_path, tags)); +void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &p_tags, const String &p_target) { + shared_objects.push_back(SharedObject(p_path, p_tags, p_target)); } void EditorExportPlugin::add_ios_framework(const String &p_path) { @@ -660,7 +660,7 @@ void EditorExportPlugin::skip() { } void EditorExportPlugin::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags"), &EditorExportPlugin::add_shared_object); + ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object); ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_ios_project_static_lib); ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file); ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework); @@ -678,10 +678,9 @@ void EditorExportPlugin::_bind_methods() { } EditorExportPlugin::EditorExportPlugin() { - skipped = false; } -EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset) { +EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug) { Ref<EditorExportPlatform> platform = p_preset->get_platform(); List<String> feature_list; platform->get_platform_features(&feature_list); @@ -693,6 +692,14 @@ EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_contai result.features_pv.push_back(E); } + if (p_debug) { + result.features.insert("debug"); + result.features_pv.push_back("debug"); + } else { + result.features.insert("release"); + result.features_pv.push_back("release"); + } + if (!p_preset->get_custom_features().is_empty()) { Vector<String> tmp_custom_list = p_preset->get_custom_features().split(","); @@ -709,7 +716,7 @@ EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_contai } EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { - FeatureContainers features = p_platform.get_feature_containers(p_preset); + FeatureContainers features = p_platform.get_feature_containers(p_preset, p_debug); Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); //initial export plugin callback for (int i = 0; i < export_plugins.size(); i++) { @@ -731,7 +738,7 @@ EditorExportPlatform::ExportNotifier::~ExportNotifier() { } } -Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { +Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { //figure out paths of files that will be exported Set<String> paths; Vector<String> path_remaps; @@ -865,7 +872,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & export_plugins.write[i]->_clear(); } - FeatureContainers feature_containers = get_feature_containers(p_preset); + FeatureContainers feature_containers = get_feature_containers(p_preset, p_debug); Set<String> &features = feature_containers.features; Vector<String> &features_pv = feature_containers.features_pv; @@ -1119,7 +1126,7 @@ Error EditorExportPlatform::_add_shared_object(void *p_userdata, const SharedObj return OK; } -Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files, bool p_embed, int64_t *r_embedded_start, int64_t *r_embedded_size) { +Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, bool p_embed, int64_t *r_embedded_start, int64_t *r_embedded_size) { EditorProgress ep("savepack", TTR("Packing"), 102, true); // Create the temporary export directory if it doesn't exist. @@ -1135,7 +1142,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c pd.f = ftmp; pd.so_files = p_so_files; - Error err = export_project_files(p_preset, _save_pack_file, &pd, _add_shared_object); + Error err = export_project_files(p_preset, p_debug, _save_pack_file, &pd, _add_shared_object); memdelete(ftmp); //close tmp file @@ -1325,7 +1332,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c return OK; } -Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, const String &p_path) { +Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) { EditorProgress ep("savezip", TTR("Packing"), 102, true); FileAccess *src_f; @@ -1336,7 +1343,7 @@ Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, co zd.ep = &ep; zd.zip = zip; - Error err = export_project_files(p_preset, _save_zip_file, &zd); + Error err = export_project_files(p_preset, p_debug, _save_zip_file, &zd); if (err != OK && err != ERR_SKIP) { ERR_PRINT("Failed to export project files"); } @@ -1348,12 +1355,12 @@ Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, co Error EditorExportPlatform::export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); - return save_pack(p_preset, p_path); + return save_pack(p_preset, p_debug, p_path); } Error EditorExportPlatform::export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); - return save_zip(p_preset, p_path); + return save_zip(p_preset, p_debug, p_path); } void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags) { @@ -1722,7 +1729,6 @@ EditorExport::EditorExport() { save_timer->set_wait_time(0.8); save_timer->set_one_shot(true); save_timer->connect("timeout", callable_mp(this, &EditorExport::_save)); - block_save = false; _export_presets_updated = "export_presets_updated"; @@ -1875,7 +1881,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr int64_t embedded_pos; int64_t embedded_size; - err = save_pack(p_preset, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); + err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); if (err == OK && p_preset->get("binary_format/embed_pck")) { if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) { EditorNode::get_singleton()->show_warning(TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB.")); @@ -1889,12 +1895,27 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr } if (err == OK && !so_files.is_empty()) { - //if shared object files, copy them + // If shared object files, copy them. da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < so_files.size() && err == OK; i++) { - err = da->copy(so_files[i].path, p_path.get_base_dir().plus_file(so_files[i].path.get_file())); - if (err == OK) { - err = sign_shared_object(p_preset, p_debug, p_path.get_base_dir().plus_file(so_files[i].path.get_file())); + String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path); + String target_path; + if (so_files[i].target.is_empty()) { + target_path = p_path.get_base_dir().plus_file(src_path.get_file()); + } else { + target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file()); + } + + if (da->dir_exists(src_path)) { + err = da->make_dir_recursive(target_path); + if (err == OK) { + err = da->copy_dir(src_path, target_path, -1, true); + } + } else { + err = da->copy(src_path, target_path); + if (err == OK) { + err = sign_shared_object(p_preset, p_debug, target_path); + } } } } diff --git a/editor/editor_export.h b/editor/editor_export.h index 796fb12793..d9039f601e 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -152,10 +152,12 @@ public: struct SharedObject { String path; Vector<String> tags; + String target; - SharedObject(const String &p_path, const Vector<String> &p_tags) : + SharedObject(const String &p_path, const Vector<String> &p_tags, const String &p_target) : path(p_path), - tags(p_tags) { + tags(p_tags), + target(p_target) { } SharedObject() {} @@ -216,7 +218,7 @@ protected: ~ExportNotifier(); }; - FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset); + FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug); bool exists_export_template(String template_file_name, String *err) const; String find_export_template(String template_file_name, String *err = nullptr) const; @@ -246,10 +248,10 @@ public: virtual String get_name() const = 0; virtual Ref<Texture2D> get_logo() const = 0; - Error export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr); + Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr); - Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); - Error save_zip(const Ref<EditorExportPreset> &p_preset, const String &p_path); + Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); + Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); virtual bool poll_export() { return false; } virtual int get_options_count() const { return 0; } @@ -297,7 +299,7 @@ class EditorExportPlugin : public RefCounted { bool remap = false; }; Vector<ExtraFile> extra_files; - bool skipped; + bool skipped = false; Vector<String> ios_frameworks; Vector<String> ios_embedded_frameworks; @@ -334,7 +336,7 @@ protected: Ref<EditorExportPreset> get_export_preset() const; void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap); - void add_shared_object(const String &p_path, const Vector<String> &tags); + void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String()); void add_ios_framework(const String &p_path); void add_ios_embedded_framework(const String &p_path); @@ -379,7 +381,7 @@ class EditorExport : public Node { StringName _export_presets_updated; Timer *save_timer; - bool block_save; + bool block_save = false; static EditorExport *singleton; diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index b1708e756a..3d5ca7de42 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -1010,7 +1010,5 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { update_timer->connect("timeout", callable_mp(this, &EditorFeatureProfileManager::_emit_current_profile_changed)); update_timer->set_one_shot(true); - updating_features = false; - singleton = this; } diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h index 7ea40502a6..881f14638f 100644 --- a/editor/editor_feature_profile.h +++ b/editor/editor_feature_profile.h @@ -155,7 +155,7 @@ class EditorFeatureProfileManager : public AcceptDialog { void _import_profiles(const Vector<String> &p_paths); void _export_profile(const String &p_path); - bool updating_features; + bool updating_features = false; void _class_list_item_selected(); void _class_list_item_edited(); diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 0fef4597be..31f2f24066 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -214,7 +214,7 @@ void EditorFileDialog::update_dir() { if (dir_access->get_current_dir().is_network_share_path()) { _update_drives(false); drives->add_item(RTR("Network")); - drives->set_item_disabled(drives->get_item_count() - 1, true); + drives->set_item_disabled(-1, true); drives->select(drives->get_item_count() - 1); } else { drives->select(dir_access->get_current_drive()); @@ -314,8 +314,8 @@ void EditorFileDialog::_post_popup() { recentd.remove_at(i--); } else { recent->add_item(name, folder); - recent->set_item_metadata(recent->get_item_count() - 1, recentd[i]); - recent->set_item_icon_modulate(recent->get_item_count() - 1, folder_color); + recent->set_item_metadata(-1, recentd[i]); + recent->set_item_icon_modulate(-1, folder_color); } } EditorSettings::get_singleton()->set_recent_dirs(recentd); @@ -800,9 +800,9 @@ void EditorFileDialog::update_file_list() { item_list->add_item(dir_name); if (display_mode == DISPLAY_THUMBNAILS) { - item_list->set_item_icon(item_list->get_item_count() - 1, folder_thumbnail); + item_list->set_item_icon(-1, folder_thumbnail); } else { - item_list->set_item_icon(item_list->get_item_count() - 1, folder); + item_list->set_item_icon(-1, folder); } Dictionary d; @@ -810,8 +810,8 @@ void EditorFileDialog::update_file_list() { d["path"] = cdir.plus_file(dir_name); d["dir"] = true; - item_list->set_item_metadata(item_list->get_item_count() - 1, d); - item_list->set_item_icon_modulate(item_list->get_item_count() - 1, folder_color); + item_list->set_item_metadata(-1, d); + item_list->set_item_icon_modulate(-1, folder_color); dirs.pop_front(); } @@ -858,10 +858,10 @@ void EditorFileDialog::update_file_list() { if (get_icon_func) { Ref<Texture2D> icon = get_icon_func(cdir.plus_file(files.front()->get())); if (display_mode == DISPLAY_THUMBNAILS) { - item_list->set_item_icon(item_list->get_item_count() - 1, file_thumbnail); - item_list->set_item_tag_icon(item_list->get_item_count() - 1, icon); + item_list->set_item_icon(-1, file_thumbnail); + item_list->set_item_tag_icon(-1, icon); } else { - item_list->set_item_icon(item_list->get_item_count() - 1, icon); + item_list->set_item_icon(-1, icon); } } @@ -870,7 +870,7 @@ void EditorFileDialog::update_file_list() { d["dir"] = false; String fullpath = cdir.plus_file(files.front()->get()); d["path"] = fullpath; - item_list->set_item_metadata(item_list->get_item_count() - 1, d); + item_list->set_item_metadata(-1, d); if (display_mode == DISPLAY_THUMBNAILS && previews_enabled) { EditorResourcePreview::get_singleton()->queue_resource_preview(fullpath, this, "_thumbnail_result", fullpath); @@ -1321,8 +1321,8 @@ void EditorFileDialog::_update_favorites() { continue; // We don't handle favorite files here. } - favorites->set_item_metadata(favorites->get_item_count() - 1, favorited[i]); - favorites->set_item_icon_modulate(favorites->get_item_count() - 1, folder_color); + favorites->set_item_metadata(-1, favorited[i]); + favorites->set_item_icon_modulate(-1, folder_color); if (setthis) { favorite->set_pressed(true); @@ -1471,9 +1471,9 @@ void EditorFileDialog::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::INT, "display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"), "set_display_mode", "get_display_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"), "set_file_mode", "get_file_mode"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR), "set_current_dir", "get_current_dir"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*"), "set_current_file", "get_current_file"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path"), "set_current_path", "get_current_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*", PROPERTY_USAGE_NONE), "set_current_file", "get_current_file"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_path", "get_current_path"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_overwrite_warning"), "set_disable_overwrite_warning", "is_overwrite_warning_disabled"); @@ -1557,7 +1557,6 @@ EditorFileDialog::EditorFileDialog() { show_hidden_files = default_show_hidden_files; display_mode = default_display_mode; local_history_pos = 0; - disable_overwrite_warning = false; VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); @@ -1814,15 +1813,12 @@ EditorFileDialog::EditorFileDialog() { set_hide_on_ok(false); vbox = vbc; - invalidated = true; if (register_func) { register_func(this); } - previews_enabled = true; preview_wheel_timeout = 0; preview_wheel_index = 0; - preview_waiting = false; } EditorFileDialog::~EditorFileDialog() { diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h index 65a4c9e544..a747255ce8 100644 --- a/editor/editor_file_dialog.h +++ b/editor/editor_file_dialog.h @@ -135,8 +135,8 @@ private: Vector<String> filters; - bool previews_enabled; - bool preview_waiting; + bool previews_enabled = true; + bool preview_waiting = false; int preview_wheel_index; float preview_wheel_timeout; @@ -145,8 +145,8 @@ private: bool show_hidden_files; DisplayMode display_mode; - bool disable_overwrite_warning; - bool invalidated; + bool disable_overwrite_warning = false; + bool invalidated = true; void update_dir(); void update_file_name(); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 0c46cebec0..98ba3ae3d8 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -194,7 +194,6 @@ void EditorFileSystemDirectory::_bind_methods() { EditorFileSystemDirectory::EditorFileSystemDirectory() { modified_time = 0; parent = nullptr; - verified = false; } EditorFileSystemDirectory::~EditorFileSystemDirectory() { @@ -1094,12 +1093,11 @@ void EditorFileSystem::_delete_internal_files(String p_file) { if (FileAccess::exists(p_file + ".import")) { List<String> paths; ResourceFormatImporter::get_singleton()->get_internal_resource_path_list(p_file, &paths); - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); for (const String &E : paths) { da->remove(E); } da->remove(p_file + ".import"); - memdelete(da); } } @@ -2384,24 +2382,14 @@ EditorFileSystem::EditorFileSystem() { filesystem = memnew(EditorFileSystemDirectory); //like, empty filesystem->parent = nullptr; - scanning = false; - importing = false; - use_threads = true; new_filesystem = nullptr; - abort_scan = false; - scanning_changes = false; - scanning_changes_done = false; - // This should probably also work on Unix and use the string it returns for FAT32 or exFAT DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT"); scan_total = 0; update_script_classes_queued.clear(); - first_scan = true; - scan_changes_pending = false; - revalidate_import_files = false; import_threads.init(); ResourceUID::get_singleton()->clear(); //will be updated on scan ResourceSaver::set_get_resource_id_for_path(_resource_saver_get_resource_id_for_path); diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 0c1bfbca47..0ec0094030 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -47,7 +47,7 @@ class EditorFileSystemDirectory : public Object { String name; uint64_t modified_time; - bool verified; //used for checking changes + bool verified = false; //used for checking changes EditorFileSystemDirectory *parent; Vector<EditorFileSystemDirectory *> subdirs; @@ -132,20 +132,20 @@ class EditorFileSystem : public Node { EditorFileSystemDirectory::FileInfo *new_file = nullptr; }; - bool use_threads; + bool use_threads = true; Thread thread; static void _thread_func(void *_userdata); EditorFileSystemDirectory *new_filesystem; - bool abort_scan; - bool scanning; - bool importing; - bool first_scan; - bool scan_changes_pending; + bool abort_scan = false; + bool scanning = false; + bool importing = false; + bool first_scan = true; + bool scan_changes_pending = false; float scan_total; String filesystem_settings_version_for_import; - bool revalidate_import_files; + bool revalidate_import_files = false; void _scan_filesystem(); @@ -197,8 +197,8 @@ class EditorFileSystem : public Node { void _scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress); Thread thread_sources; - bool scanning_changes; - bool scanning_changes_done; + bool scanning_changes = false; + bool scanning_changes_done = false; static void _thread_func_sources(void *_userdata); diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index d80ee1d569..7b72e09bd7 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -64,8 +64,8 @@ m_name->add_data(FontTamilBold); \ m_name->add_data(FontTeluguBold); \ m_name->add_data(FontThaiBold); \ - m_name->add_data(FontJapanese); \ - m_name->add_data(FontFallback); + m_name->add_data(FontJapaneseBold); \ + m_name->add_data(FontFallbackBold); #define MAKE_DEFAULT_FONT(m_name, m_variations) \ Ref<Font> m_name; \ @@ -174,7 +174,7 @@ Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, Te } void editor_register_fonts(Ref<Theme> p_theme) { - DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); /* Custom font */ @@ -206,7 +206,8 @@ void editor_register_fonts(Ref<Theme> p_theme) { break; } - int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE; + const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE; + const float embolden_strength = 0.6; String custom_font_path = EditorSettings::get_singleton()->get("interface/editor/main_font"); Ref<FontData> CustomFont; @@ -226,6 +227,11 @@ void editor_register_fonts(Ref<Theme> p_theme) { EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", ""); } + if (CustomFont.is_valid() && !CustomFontBold.is_valid()) { + CustomFontBold = CustomFont->duplicate(); + CustomFontBold->set_embolden(embolden_strength); + } + /* Custom source code font */ String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font"); @@ -236,8 +242,6 @@ void editor_register_fonts(Ref<Theme> p_theme) { EditorSettings::get_singleton()->set_manually("interface/editor/code_font", ""); } - memdelete(dir); - /* Noto Sans */ Ref<FontData> DefaultFont = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); @@ -270,6 +274,11 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontData> FontFallback = load_cached_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontData> FontJapanese = load_cached_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontData> FontFallbackBold = FontFallback->duplicate(); + FontFallbackBold->set_embolden(embolden_strength); + Ref<FontData> FontJapaneseBold = FontJapanese->duplicate(); + FontJapaneseBold->set_embolden(embolden_strength); + /* Hack */ Ref<FontData> dfmono = load_cached_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 39c8509148..622547f0a8 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1897,8 +1897,6 @@ EditorHelp::EditorHelp() { class_desc->set_selection_enabled(true); - scroll_locked = false; - select_locked = false; class_desc->hide(); } diff --git a/editor/editor_help.h b/editor/editor_help.h index 10281a764c..b40d1709b6 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -98,7 +98,7 @@ class EditorHelp : public VBoxContainer { }; - bool select_locked; + bool select_locked = false; String prev_search; @@ -144,7 +144,7 @@ class EditorHelp : public VBoxContainer { void _help_callback(const String &p_topic); void _add_text(const String &p_bbcode); - bool scroll_locked; + bool scroll_locked = false; //void _button_pressed(int p_idx); void _add_type(const String &p_type, const String &p_enum = String()); diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index eab62349d1..8e03c55712 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -180,8 +180,6 @@ void EditorHelpSearch::popup_dialog(const String &p_term) { } EditorHelpSearch::EditorHelpSearch() { - old_search = false; - set_hide_on_ok(false); set_title(TTR("Search Help")); diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h index 7d918d0c68..bf69fe1693 100644 --- a/editor/editor_help_search.h +++ b/editor/editor_help_search.h @@ -60,7 +60,7 @@ class EditorHelpSearch : public ConfirmationDialog { Button *hierarchy_button; OptionButton *filter_combo; Tree *results_tree; - bool old_search; + bool old_search = false; String old_term; class Runner; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index f5d318a227..9efd942a51 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -882,7 +882,7 @@ void EditorProperty::menu_option(int p_option) { emit_changed(property, InspectorDock::get_inspector_singleton()->get_property_clipboard()); } break; case MENU_COPY_PROPERTY_PATH: { - DisplayServer::get_singleton()->clipboard_set(property); + DisplayServer::get_singleton()->clipboard_set(property_path); } break; case MENU_PIN_VALUE: { emit_signal(SNAME("property_pinned"), property, !pinned); @@ -948,31 +948,13 @@ void EditorProperty::_bind_methods() { } EditorProperty::EditorProperty() { - draw_top_bg = true; object = nullptr; split_ratio = 0.5; - selectable = true; text_size = 0; - read_only = false; - checkable = false; - checked = false; - draw_warning = false; - keying = false; - deletable = false; - keying_hover = false; - revert_hover = false; - check_hover = false; - can_revert = false; - can_pin = false; - pin_hidden = false; - pinned = false; - use_folding = false; property_usage = 0; - selected = false; selected_focusable = -1; label_reference = nullptr; bottom_editor = nullptr; - delete_hover = false; menu = nullptr; set_process_unhandled_key_input(true); } @@ -2332,6 +2314,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit if (F.properties.size() == 1) { //since it's one, associate: ep->property = F.properties[0]; + ep->property_path = property_prefix + F.properties[0]; ep->property_usage = 0; } @@ -2892,6 +2875,7 @@ void EditorInspector::update_tree() { if (F.properties.size() == 1) { //since it's one, associate: ep->property = F.properties[0]; + ep->property_path = property_prefix + F.properties[0]; ep->property_usage = p.usage; //and set label? } @@ -3675,25 +3659,11 @@ EditorInspector::EditorInspector() { add_child(main_vbox); set_horizontal_scroll_mode(SCROLL_MODE_DISABLED); - wide_editors = false; - show_categories = false; - hide_script = true; - use_doc_hints = false; - capitalize_paths = true; - use_filter = false; - autoclear = false; changing = 0; - use_folding = false; - update_all_pending = false; - update_tree_pending = false; - read_only = false; search_box = nullptr; - keying = false; _prop_edited = "property_edited"; set_process(false); property_focusable = -1; - sub_inspector = false; - deletable_properties = false; property_clipboard = Variant(); get_v_scroll_bar()->connect("value_changed", callable_mp(this, &EditorInspector::_vscroll_changed)); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 43f71740e3..3c482a07e7 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -68,15 +68,16 @@ private: friend class EditorInspector; Object *object; StringName property; + String property_path; int property_usage; - bool read_only; - bool checkable; - bool checked; - bool draw_warning; - bool keying; - bool deletable; + bool read_only = false; + bool checkable = false; + bool checked = false; + bool draw_warning = false; + bool keying = false; + bool deletable = false; Rect2 right_child_rect; Rect2 bottom_child_rect; @@ -90,19 +91,19 @@ private: Rect2 delete_rect; bool delete_hover = false; - bool can_revert; - bool can_pin; - bool pin_hidden; - bool pinned; + bool can_revert = false; + bool can_pin = false; + bool pin_hidden = false; + bool pinned = false; - bool use_folding; - bool draw_top_bg; + bool use_folding = false; + bool draw_top_bg = true; void _update_popup(); void _focusable_focused(int p_index); - bool selectable; - bool selected; + bool selectable = true; + bool selected = false; int selected_focusable; float split_ratio; @@ -442,23 +443,23 @@ class EditorInspector : public ScrollContainer { // LineEdit *search_box; - bool show_categories; - bool hide_script; - bool use_doc_hints; - bool capitalize_paths; - bool use_filter; - bool autoclear; - bool use_folding; + bool show_categories = false; + bool hide_script = true; + bool use_doc_hints = false; + bool capitalize_paths = true; + bool use_filter = false; + bool autoclear = false; + bool use_folding = false; int changing; - bool update_all_pending; - bool read_only; - bool keying; - bool sub_inspector; - bool wide_editors; - bool deletable_properties; + bool update_all_pending = false; + bool read_only = false; + bool keying = false; + bool sub_inspector = false; + bool wide_editors = false; + bool deletable_properties = false; float refresh_countdown; - bool update_tree_pending; + bool update_tree_pending = false; StringName _prop_edited; StringName property_selected; int property_focusable; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index d9ba4139c2..54a55286e9 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -80,6 +80,11 @@ void EditorLog::_update_theme() { type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); + type_filter_map[MSG_TYPE_STD]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); + type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); + type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); + type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); + clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); copy_button->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"))); collapse_button->set_icon(get_theme_icon(SNAME("CombineLines"), SNAME("EditorIcons"))); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 17b219f8dc..b6a7e51807 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -146,6 +146,7 @@ #include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/editor_preview_plugins.h" #include "editor/plugins/font_editor_plugin.h" +#include "editor/plugins/gdextension_export_plugin.h" #include "editor/plugins/gpu_particles_2d_editor_plugin.h" #include "editor/plugins/gpu_particles_3d_editor_plugin.h" #include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h" @@ -701,7 +702,7 @@ void EditorNode::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); + scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int()); bool theme_changed = EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") || @@ -5841,16 +5842,7 @@ EditorNode::EditorNode() { } singleton = this; - exiting = false; - dimmed = false; last_checked_version = 0; - changing_scene = false; - _initializing_addons = false; - docks_visible = true; - restoring_scenes = false; - cmdline_export_mode = false; - scene_distraction = false; - script_distraction = false; TranslationServer::get_singleton()->set_enabled(false); // load settings @@ -6025,7 +6017,6 @@ EditorNode::EditorNode() { ClassDB::set_class_enabled("RootMotionView", true); // defs here, use EDITOR_GET in logic - EDITOR_DEF_RST("interface/scene_tabs/always_show_close_button", false); EDITOR_DEF("interface/editor/save_on_focus_loss", false); EDITOR_DEF("interface/editor/show_update_spinner", false); EDITOR_DEF("interface/editor/update_continuously", false); @@ -6251,7 +6242,7 @@ EditorNode::EditorNode() { scene_tabs->set_select_with_rmb(true); scene_tabs->add_tab("unsaved"); scene_tabs->set_tab_alignment(TabBar::ALIGNMENT_LEFT); - scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); + scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int()); scene_tabs->set_max_tab_width(int(EDITOR_GET("interface/scene_tabs/maximum_width")) * EDSCALE); scene_tabs->set_drag_to_rearrange_enabled(true); scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed)); @@ -6301,7 +6292,7 @@ EditorNode::EditorNode() { scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL); scene_root = memnew(SubViewport); - scene_root->set_embed_subwindows_hint(true); + scene_root->set_embedding_subwindows(true); scene_root->set_disable_3d(true); scene_root->set_disable_input(true); @@ -6516,7 +6507,7 @@ EditorNode::EditorNode() { ED_SHORTCUT_OVERRIDE("editor/take_screenshot", "macos", KeyModifierMask::CMD | Key::F12); p->add_shortcut(ED_GET_SHORTCUT("editor/take_screenshot"), EDITOR_SCREENSHOT); - p->set_item_tooltip(p->get_item_count() - 1, TTR("Screenshots are stored in the Editor Data/Settings Folder.")); + p->set_item_tooltip(-1, TTR("Screenshots are stored in the Editor Data/Settings Folder.")); ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KeyModifierMask::SHIFT | Key::F11); ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::F); @@ -7104,6 +7095,11 @@ EditorNode::EditorNode() { EditorExport::get_singleton()->add_export_plugin(export_text_to_binary_plugin); + Ref<GDExtensionExportPlugin> gdextension_export_plugin; + gdextension_export_plugin.instantiate(); + + EditorExport::get_singleton()->add_export_plugin(gdextension_export_plugin); + Ref<PackedSceneEditorTranslationParserPlugin> packed_scene_translation_parser_plugin; packed_scene_translation_parser_plugin.instantiate(); EditorTranslationParser::get_singleton()->add_parser(packed_scene_translation_parser_plugin, EditorTranslationParser::STANDARD); @@ -7112,9 +7108,6 @@ EditorNode::EditorNode() { current = nullptr; saving_resource = Ref<Resource>(); - reference_resource_mem = true; - save_external_resources_mem = true; - set_process(true); open_imported = memnew(ConfirmationDialog); @@ -7125,7 +7118,6 @@ EditorNode::EditorNode() { gui_base->add_child(open_imported); saved_version = 1; - unsaved_cache = true; _last_instantiated_scene = nullptr; quick_open = memnew(EditorQuickOpen); @@ -7139,10 +7131,7 @@ EditorNode::EditorNode() { _update_recent_scenes(); editor_data.restore_editor_global_states(); - convert_old = false; - opening_prev = false; set_process_unhandled_input(true); - _playing_edited = false; load_errors = memnew(RichTextLabel); load_error_dialog = memnew(AcceptDialog); @@ -7183,8 +7172,6 @@ EditorNode::EditorNode() { FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify); - waiting_for_first_scan = true; - print_handler.printfunc = _print_handler; print_handler.userdata = this; add_print_handler(&print_handler); diff --git a/editor/editor_node.h b/editor/editor_node.h index c05e6cd281..0b6dbaec49 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -263,8 +263,8 @@ private: TextureRect *tab_preview; int tab_closing; - bool exiting; - bool dimmed; + bool exiting = false; + bool dimmed = false; int old_split_ofs; VSplitContainer *top_split; @@ -380,15 +380,15 @@ private: Button *dock_tab_move_right; int dock_popup_selected; Timer *dock_drag_timer; - bool docks_visible; + bool docks_visible = true; HBoxContainer *tabbar_container; Button *distraction_free; Button *scene_tab_add; Control *scene_tab_add_ph; - bool scene_distraction; - bool script_distraction; + bool scene_distraction = false; + bool script_distraction = false; String _tmp_import_path; @@ -397,18 +397,15 @@ private: Object *current; Ref<Resource> saving_resource; - bool _playing_edited; + bool _playing_edited = false; String run_custom_filename; - bool reference_resource_mem; - bool save_external_resources_mem; + bool reference_resource_mem = true; uint64_t saved_version; uint64_t last_checked_version; - bool unsaved_cache; + bool unsaved_cache = true; String open_navigate; - bool changing_scene; - bool waiting_for_first_scan; - - bool waiting_for_sources_changed; + bool changing_scene = false; + bool waiting_for_first_scan = true; uint64_t update_spinner_step_msec; uint64_t update_spinner_step_frame; @@ -457,7 +454,7 @@ private: String external_file; List<String> previous_scenes; - bool opening_prev; + bool opening_prev = false; void _dialog_action(String p_file); @@ -534,7 +531,7 @@ private: void _exit_editor(int p_exit_code); - bool convert_old; + bool convert_old = false; virtual void unhandled_input(const Ref<InputEvent> &p_event) override; @@ -551,7 +548,7 @@ private: Map<String, Ref<Texture2D>> icon_type_cache; void _build_icon_type_cache(); - bool _initializing_addons; + bool _initializing_addons = false; Map<String, EditorPlugin *> plugin_addons; static Ref<Texture2D> _file_dialog_get_icon(const String &p_path); @@ -587,7 +584,7 @@ private: bool pack_only = false; } export_defer; - bool cmdline_export_mode; + bool cmdline_export_mode = false; static EditorNode *singleton; @@ -627,7 +624,7 @@ private: void _update_dock_slots_visibility(); void _dock_tab_changed(int p_tab); - bool restoring_scenes; + bool restoring_scenes = false; void _save_open_scenes_to_config(Ref<ConfigFile> p_layout, const String &p_section); void _load_open_scenes_from_config(Ref<ConfigFile> p_layout, const String &p_section); diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index 401414ae50..b6f48c7536 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -240,6 +240,4 @@ EditorPluginSettings::EditorPluginSettings() { mc->set_h_size_flags(SIZE_EXPAND_FILL); add_child(mc); - - updating = false; } diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h index 4648d105f7..c239b735de 100644 --- a/editor/editor_plugin_settings.h +++ b/editor/editor_plugin_settings.h @@ -48,7 +48,7 @@ class EditorPluginSettings : public VBoxContainer { Button *create_plugin; Button *update_list; Tree *plugin_list; - bool updating; + bool updating = false; void _plugin_activity_changed(); void _create_clicked(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 1a4d507eef..b495d29911 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -110,9 +110,6 @@ EditorPropertyText::EditorPropertyText() { add_focusable(text); text->connect("text_changed", callable_mp(this, &EditorPropertyText::_text_changed)); text->connect("text_submitted", callable_mp(this, &EditorPropertyText::_text_submitted)); - - string_name = false; - updating = false; } ///////////////////// MULTILINE TEXT ///////////////////////// @@ -500,9 +497,6 @@ EditorPropertyPath::EditorPropertyPath() { add_focusable(path); dialog = nullptr; path_edit->connect("pressed", callable_mp(this, &EditorPropertyPath::_path_pressed)); - folder = false; - global = false; - save_mode = false; } ///////////////////// CLASS NAME ///////////////////////// @@ -1278,7 +1272,6 @@ EditorPropertyInteger::EditorPropertyInteger() { add_child(spin); add_focusable(spin); spin->connect("value_changed", callable_mp(this, &EditorPropertyInteger::_value_changed)); - setting = false; } ///////////////////// OBJECT ID ///////////////////////// @@ -1587,10 +1580,6 @@ EditorPropertyEasing::EditorPropertyEasing() { spin->get_line_edit()->connect("focus_exited", callable_mp(this, &EditorPropertyEasing::_spin_focus_exited)); spin->hide(); add_child(spin); - - dragging = false; - flip = false; - full = false; } ///////////////////// VECTOR2 ///////////////////////// @@ -1680,7 +1669,6 @@ EditorPropertyVector2::EditorPropertyVector2(bool p_force_wide) { if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } - setting = false; } ///////////////////// RECT2 ///////////////////////// @@ -1784,7 +1772,6 @@ EditorPropertyRect2::EditorPropertyRect2(bool p_force_wide) { if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } - setting = false; } ///////////////////// VECTOR3 ///////////////////////// @@ -1993,7 +1980,6 @@ EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) { if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } - setting = false; } ///////////////////// RECT2i ///////////////////////// @@ -2097,7 +2083,6 @@ EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) { if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } - setting = false; } ///////////////////// VECTOR3i ///////////////////////// @@ -2188,7 +2173,6 @@ EditorPropertyVector3i::EditorPropertyVector3i(bool p_force_wide) { if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } - setting = false; } ///////////////////// PLANE ///////////////////////// @@ -2282,7 +2266,6 @@ EditorPropertyPlane::EditorPropertyPlane(bool p_force_wide) { if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } - setting = false; } ///////////////////// QUATERNION ///////////////////////// @@ -2373,7 +2356,6 @@ EditorPropertyQuaternion::EditorPropertyQuaternion() { if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } - setting = false; } ///////////////////// AABB ///////////////////////// @@ -2457,7 +2439,6 @@ EditorPropertyAABB::EditorPropertyAABB() { spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyAABB::_value_changed), varray(desc[i])); } set_bottom_editor(g); - setting = false; } ///////////////////// TRANSFORM2D ///////////////////////// @@ -2547,7 +2528,6 @@ EditorPropertyTransform2D::EditorPropertyTransform2D(bool p_include_origin) { spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform2D::_value_changed), varray(desc[i])); } set_bottom_editor(g); - setting = false; } ///////////////////// BASIS ///////////////////////// @@ -2636,7 +2616,6 @@ EditorPropertyBasis::EditorPropertyBasis() { spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyBasis::_value_changed), varray(desc[i])); } set_bottom_editor(g); - setting = false; } ///////////////////// TRANSFORM ///////////////////////// @@ -2733,7 +2712,6 @@ EditorPropertyTransform3D::EditorPropertyTransform3D() { spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform3D::_value_changed), varray(desc[i])); } set_bottom_editor(g); - setting = false; } ////////////// COLOR PICKER ////////////////////// @@ -2969,7 +2947,6 @@ EditorPropertyNodePath::EditorPropertyNodePath() { clear->set_flat(true); clear->connect("pressed", callable_mp(this, &EditorPropertyNodePath::_node_clear)); hbc->add_child(clear); - use_path_from_scene_root = false; scene_tree = nullptr; //do not allocate unnecessarily } @@ -3738,8 +3715,13 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ } break; case Variant::DICTIONARY: { - EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary); - return editor; + if (p_hint == PROPERTY_HINT_LOCALIZABLE_STRING) { + EditorPropertyLocalizableString *editor = memnew(EditorPropertyLocalizableString); + return editor; + } else { + EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary); + return editor; + } } break; case Variant::ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 9a16a78ff8..c21e0e0b4d 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -54,8 +54,8 @@ class EditorPropertyText : public EditorProperty { GDCLASS(EditorPropertyText, EditorProperty); LineEdit *text; - bool updating; - bool string_name; + bool updating = false; + bool string_name = false; void _text_changed(const String &p_string); void _text_submitted(const String &p_string); @@ -131,9 +131,9 @@ public: class EditorPropertyPath : public EditorProperty { GDCLASS(EditorPropertyPath, EditorProperty); Vector<String> extensions; - bool folder; - bool global; - bool save_mode; + bool folder = false; + bool global = false; + bool save_mode = false; EditorFileDialog *dialog; LineEdit *path; Button *path_edit; @@ -359,7 +359,7 @@ public: class EditorPropertyInteger : public EditorProperty { GDCLASS(EditorPropertyInteger, EditorProperty); EditorSpinSlider *spin; - bool setting; + bool setting = false; void _value_changed(int64_t p_val); protected: @@ -410,11 +410,11 @@ class EditorPropertyEasing : public EditorProperty { Control *easing_draw; PopupMenu *preset; EditorSpinSlider *spin; - bool setting; + bool setting = false; - bool dragging; - bool full; - bool flip; + bool dragging = false; + bool full = false; + bool flip = false; enum { EASING_ZERO, @@ -450,7 +450,7 @@ public: class EditorPropertyVector2 : public EditorProperty { GDCLASS(EditorPropertyVector2, EditorProperty); EditorSpinSlider *spin[2]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -467,7 +467,7 @@ public: class EditorPropertyRect2 : public EditorProperty { GDCLASS(EditorPropertyRect2, EditorProperty); EditorSpinSlider *spin[4]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -504,7 +504,7 @@ public: class EditorPropertyVector2i : public EditorProperty { GDCLASS(EditorPropertyVector2i, EditorProperty); EditorSpinSlider *spin[2]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -521,7 +521,7 @@ public: class EditorPropertyRect2i : public EditorProperty { GDCLASS(EditorPropertyRect2i, EditorProperty); EditorSpinSlider *spin[4]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -538,7 +538,7 @@ public: class EditorPropertyVector3i : public EditorProperty { GDCLASS(EditorPropertyVector3i, EditorProperty); EditorSpinSlider *spin[3]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -555,7 +555,7 @@ public: class EditorPropertyPlane : public EditorProperty { GDCLASS(EditorPropertyPlane, EditorProperty); EditorSpinSlider *spin[4]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -572,7 +572,7 @@ public: class EditorPropertyQuaternion : public EditorProperty { GDCLASS(EditorPropertyQuaternion, EditorProperty); EditorSpinSlider *spin[4]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -589,7 +589,7 @@ public: class EditorPropertyAABB : public EditorProperty { GDCLASS(EditorPropertyAABB, EditorProperty); EditorSpinSlider *spin[6]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -606,7 +606,7 @@ public: class EditorPropertyTransform2D : public EditorProperty { GDCLASS(EditorPropertyTransform2D, EditorProperty); EditorSpinSlider *spin[6]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -623,7 +623,7 @@ public: class EditorPropertyBasis : public EditorProperty { GDCLASS(EditorPropertyBasis, EditorProperty); EditorSpinSlider *spin[9]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -640,7 +640,7 @@ public: class EditorPropertyTransform3D : public EditorProperty { GDCLASS(EditorPropertyTransform3D, EditorProperty); EditorSpinSlider *spin[12]; - bool setting; + bool setting = false; void _value_changed(double p_val, const String &p_name); protected: @@ -681,7 +681,7 @@ class EditorPropertyNodePath : public EditorProperty { Button *clear; SceneTreeDialog *scene_tree; NodePath base_hint; - bool use_path_from_scene_root; + bool use_path_from_scene_root = false; Vector<StringName> valid_types; void _node_selected(const NodePath &p_path); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index d354be9af5..f59ba66862 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -253,6 +253,7 @@ void EditorPropertyArray::update_property() { if (vbox) { set_bottom_editor(nullptr); memdelete(vbox); + button_add_item = nullptr; vbox = nullptr; } return; @@ -408,6 +409,7 @@ void EditorPropertyArray::update_property() { if (vbox) { set_bottom_editor(nullptr); memdelete(vbox); + button_add_item = nullptr; vbox = nullptr; } } @@ -714,7 +716,6 @@ EditorPropertyArray::EditorPropertyArray() { size_slider = nullptr; button_add_item = nullptr; paginator = nullptr; - updating = false; change_type = memnew(PopupMenu); add_child(change_type); change_type->connect("id_pressed", callable_mp(this, &EditorPropertyArray::_change_type_menu)); @@ -723,8 +724,6 @@ EditorPropertyArray::EditorPropertyArray() { subtype = Variant::NIL; subtype_hint = PROPERTY_HINT_NONE; subtype_hint_string = ""; - - dropping = false; } ///////////////////// DICTIONARY /////////////////////////// @@ -742,7 +741,7 @@ void EditorPropertyDictionary::_property_changed(const String &p_property, Varia emit_changed(get_edited_property(), dict, "", true); - dict = dict.duplicate(); // Duplicate, so undo/redo works better\. + dict = dict.duplicate(); // Duplicate, so undo/redo works better. object->set_dict(dict); } } @@ -805,7 +804,7 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) { emit_changed(get_edited_property(), dict, "", false); - dict = dict.duplicate(); // Duplicate, so undo/redo works better\. + dict = dict.duplicate(); // Duplicate, so undo/redo works better. object->set_dict(dict); update_property(); } @@ -814,11 +813,12 @@ void EditorPropertyDictionary::update_property() { Variant updated_val = get_edited_object()->get(get_edited_property()); if (updated_val.get_type() == Variant::NIL) { - edit->set_text("Dictionary (Nil)"); // This provides symmetry with the array property. + edit->set_text(TTR("Dictionary (Nil)")); // This provides symmetry with the array property. edit->set_pressed(false); if (vbox) { set_bottom_editor(nullptr); memdelete(vbox); + button_add_item = nullptr; vbox = nullptr; } return; @@ -826,7 +826,7 @@ void EditorPropertyDictionary::update_property() { Dictionary dict = updated_val; - edit->set_text("Dictionary (size " + itos(dict.size()) + ")"); + edit->set_text(vformat(TTR("Dictionary (size %d)"), dict.size())); bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); if (edit->is_pressed() != unfolded) { @@ -1144,6 +1144,7 @@ void EditorPropertyDictionary::update_property() { if (vbox) { set_bottom_editor(nullptr); memdelete(vbox); + button_add_item = nullptr; vbox = nullptr; } } @@ -1210,9 +1211,232 @@ EditorPropertyDictionary::EditorPropertyDictionary() { vbox = nullptr; button_add_item = nullptr; paginator = nullptr; - updating = false; change_type = memnew(PopupMenu); add_child(change_type); change_type->connect("id_pressed", callable_mp(this, &EditorPropertyDictionary::_change_type_menu)); changing_type_index = -1; } + +///////////////////// LOCALIZABLE STRING /////////////////////////// + +void EditorPropertyLocalizableString::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) { + if (p_property.begins_with("indices")) { + int index = p_property.get_slice("/", 1).to_int(); + Dictionary dict = object->get_dict(); + Variant key = dict.get_key_at_index(index); + dict[key] = p_value; + + emit_changed(get_edited_property(), dict, "", true); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + } +} + +void EditorPropertyLocalizableString::_add_locale_popup() { + locale_select->popup_locale_dialog(); +} + +void EditorPropertyLocalizableString::_add_locale(const String &p_locale) { + Dictionary dict = object->get_dict(); + + object->set_new_item_key(p_locale); + object->set_new_item_value(String()); + dict[object->get_new_item_key()] = object->get_new_item_value(); + + emit_changed(get_edited_property(), dict, "", false); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + update_property(); +} + +void EditorPropertyLocalizableString::_remove_item(Object *p_button, int p_index) { + Dictionary dict = object->get_dict(); + + Variant key = dict.get_key_at_index(p_index); + dict.erase(key); + + emit_changed(get_edited_property(), dict, "", false); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + update_property(); +} + +void EditorPropertyLocalizableString::update_property() { + Variant updated_val = get_edited_object()->get(get_edited_property()); + + if (updated_val.get_type() == Variant::NIL) { + edit->set_text(TTR("Localizable String (Nil)")); // This provides symmetry with the array property. + edit->set_pressed(false); + if (vbox) { + set_bottom_editor(nullptr); + memdelete(vbox); + button_add_item = nullptr; + vbox = nullptr; + } + return; + } + + Dictionary dict = updated_val; + + edit->set_text(vformat(TTR("Localizable String (size %d)"), dict.size())); + + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); + if (edit->is_pressed() != unfolded) { + edit->set_pressed(unfolded); + } + + if (unfolded) { + updating = true; + + if (!vbox) { + vbox = memnew(VBoxContainer); + add_child(vbox); + set_bottom_editor(vbox); + + property_vbox = memnew(VBoxContainer); + property_vbox->set_h_size_flags(SIZE_EXPAND_FILL); + vbox->add_child(property_vbox); + + paginator = memnew(EditorPaginator); + paginator->connect("page_changed", callable_mp(this, &EditorPropertyLocalizableString::_page_changed)); + vbox->add_child(paginator); + } else { + // Queue children for deletion, deleting immediately might cause errors. + for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) { + property_vbox->get_child(i)->queue_delete(); + } + } + + int size = dict.size(); + + int max_page = MAX(0, size - 1) / page_length; + page_index = MIN(page_index, max_page); + + paginator->update(page_index, max_page); + paginator->set_visible(max_page > 0); + + int offset = page_index * page_length; + + int amount = MIN(size - offset, page_length); + + dict = dict.duplicate(); + + object->set_dict(dict); + + for (int i = 0; i < amount; i++) { + String prop_name; + Variant key; + Variant value; + + prop_name = "indices/" + itos(i + offset); + key = dict.get_key_at_index(i + offset); + value = dict.get_value_at_index(i + offset); + + EditorProperty *prop = memnew(EditorPropertyText); + + prop->set_object_and_property(object.ptr(), prop_name); + int remove_index = 0; + + String cs = key.get_construct_string(); + prop->set_label(cs); + prop->set_tooltip(cs); + remove_index = i + offset; + + prop->set_selectable(false); + prop->connect("property_changed", callable_mp(this, &EditorPropertyLocalizableString::_property_changed)); + prop->connect("object_id_selected", callable_mp(this, &EditorPropertyLocalizableString::_object_id_selected)); + + HBoxContainer *hbox = memnew(HBoxContainer); + property_vbox->add_child(hbox); + hbox->add_child(prop); + prop->set_h_size_flags(SIZE_EXPAND_FILL); + Button *edit = memnew(Button); + edit->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); + hbox->add_child(edit); + edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_remove_item), varray(edit, remove_index)); + + prop->update_property(); + } + + if (page_index == max_page) { + button_add_item = memnew(Button); + button_add_item->set_text(TTR("Add Translation")); + button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + button_add_item->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_add_locale_popup)); + property_vbox->add_child(button_add_item); + } + + updating = false; + + } else { + if (vbox) { + set_bottom_editor(nullptr); + memdelete(vbox); + button_add_item = nullptr; + vbox = nullptr; + } + } +} + +void EditorPropertyLocalizableString::_object_id_selected(const StringName &p_property, ObjectID p_id) { + emit_signal(SNAME("object_id_selected"), p_property, p_id); +} + +void EditorPropertyLocalizableString::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: + case NOTIFICATION_ENTER_TREE: { + if (Object::cast_to<Button>(button_add_item)) { + button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + } + } break; + } +} + +void EditorPropertyLocalizableString::_edit_pressed() { + Variant prop_val = get_edited_object()->get(get_edited_property()); + if (prop_val.get_type() == Variant::NIL) { + Callable::CallError ce; + Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce); + get_edited_object()->set(get_edited_property(), prop_val); + } + + get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed()); + update_property(); +} + +void EditorPropertyLocalizableString::_page_changed(int p_page) { + if (updating) { + return; + } + page_index = p_page; + update_property(); +} + +void EditorPropertyLocalizableString::_bind_methods() { +} + +EditorPropertyLocalizableString::EditorPropertyLocalizableString() { + object.instantiate(); + page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page")); + + edit = memnew(Button); + edit->set_h_size_flags(SIZE_EXPAND_FILL); + edit->set_clip_text(true); + edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_edit_pressed)); + edit->set_toggle_mode(true); + add_child(edit); + add_focusable(edit); + + vbox = nullptr; + button_add_item = nullptr; + paginator = nullptr; + updating = false; + + locale_select = memnew(EditorLocaleDialog); + locale_select->connect("locale_selected", callable_mp(this, &EditorPropertyLocalizableString::_add_locale)); + add_child(locale_select); +} diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h index 292de6d6db..3d9fe90b20 100644 --- a/editor/editor_properties_array_dict.h +++ b/editor/editor_properties_array_dict.h @@ -32,6 +32,7 @@ #define EDITOR_PROPERTIES_ARRAY_DICT_H #include "editor/editor_inspector.h" +#include "editor/editor_locale_dialog.h" #include "editor/editor_spin_slider.h" #include "editor/filesystem_dock.h" #include "scene/gui/button.h" @@ -80,8 +81,8 @@ class EditorPropertyArray : public EditorProperty { GDCLASS(EditorPropertyArray, EditorProperty); PopupMenu *change_type; - bool updating; - bool dropping; + bool updating = false; + bool dropping = false; Ref<EditorPropertyArrayObject> object; int page_length = 20; @@ -138,7 +139,7 @@ class EditorPropertyDictionary : public EditorProperty { GDCLASS(EditorPropertyDictionary, EditorProperty); PopupMenu *change_type; - bool updating; + bool updating = false; Ref<EditorPropertyDictionaryObject> object; int page_length = 20; @@ -169,4 +170,39 @@ public: EditorPropertyDictionary(); }; +class EditorPropertyLocalizableString : public EditorProperty { + GDCLASS(EditorPropertyLocalizableString, EditorProperty); + + EditorLocaleDialog *locale_select; + + bool updating; + + Ref<EditorPropertyDictionaryObject> object; + int page_length = 20; + int page_index = 0; + Button *edit; + VBoxContainer *vbox; + VBoxContainer *property_vbox; + EditorSpinSlider *size_slider; + Button *button_add_item; + EditorPaginator *paginator; + + void _page_changed(int p_page); + void _edit_pressed(); + void _remove_item(Object *p_button, int p_index); + void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false); + + void _add_locale_popup(); + void _add_locale(const String &p_locale); + void _object_id_selected(const StringName &p_property, ObjectID p_id); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + virtual void update_property() override; + EditorPropertyLocalizableString(); +}; + #endif // EDITOR_PROPERTIES_ARRAY_DICT_H diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp index 38003ab2f4..20327cb867 100644 --- a/editor/editor_property_name_processor.cpp +++ b/editor/editor_property_name_processor.cpp @@ -69,7 +69,9 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { // The map name and value definition format should be kept synced with the regex. capitalize_string_remaps["2d"] = "2D"; capitalize_string_remaps["3d"] = "3D"; + capitalize_string_remaps["Aa"] = "AA"; capitalize_string_remaps["Adb"] = "ADB"; + capitalize_string_remaps["Ao"] = "AO"; capitalize_string_remaps["Bptc"] = "BPTC"; capitalize_string_remaps["Bvh"] = "BVH"; capitalize_string_remaps["Csg"] = "CSG"; @@ -81,21 +83,27 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["Fbx"] = "FBX"; capitalize_string_remaps["Fps"] = "FPS"; capitalize_string_remaps["Fov"] = "FOV"; + capitalize_string_remaps["Fsr"] = "FSR"; capitalize_string_remaps["Fs"] = "FS"; capitalize_string_remaps["Fxaa"] = "FXAA"; capitalize_string_remaps["Ggx"] = "GGX"; + capitalize_string_remaps["Gi"] = "GI"; capitalize_string_remaps["Gdscript"] = "GDScript"; capitalize_string_remaps["Gles 2"] = "GLES2"; capitalize_string_remaps["Gles 3"] = "GLES3"; - capitalize_string_remaps["Gi Probe"] = "GI Probe"; + capitalize_string_remaps["Gpu"] = "GPU"; + capitalize_string_remaps["Gui"] = "GUI"; capitalize_string_remaps["Hdr"] = "HDR"; capitalize_string_remaps["Hidpi"] = "hiDPI"; + capitalize_string_remaps["Http"] = "HTTP"; capitalize_string_remaps["Ik"] = "IK"; capitalize_string_remaps["Ios"] = "iOS"; capitalize_string_remaps["Kb"] = "KB"; + capitalize_string_remaps["Lod"] = "LOD"; capitalize_string_remaps["Msaa"] = "MSAA"; capitalize_string_remaps["Macos"] = "macOS"; capitalize_string_remaps["Opentype"] = "OpenType"; + capitalize_string_remaps["Openxr"] = "OpenXR"; capitalize_string_remaps["Png"] = "PNG"; capitalize_string_remaps["Pvs"] = "PVS"; capitalize_string_remaps["Pvrtc"] = "PVRTC"; @@ -104,16 +112,23 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["Srgb"] = "sRGB"; capitalize_string_remaps["Ssao"] = "SSAO"; capitalize_string_remaps["Ssl"] = "SSL"; + capitalize_string_remaps["Ssil"] = "SSIL"; capitalize_string_remaps["Ssh"] = "SSH"; + capitalize_string_remaps["Sdf"] = "SDF"; capitalize_string_remaps["Sdk"] = "SDK"; capitalize_string_remaps["Tcp"] = "TCP"; + capitalize_string_remaps["Url"] = "URL"; capitalize_string_remaps["Uv 1"] = "UV1"; capitalize_string_remaps["Uv 2"] = "UV2"; + capitalize_string_remaps["Uv"] = "UV"; + capitalize_string_remaps["Uwp"] = "UWP"; capitalize_string_remaps["Vram"] = "VRAM"; capitalize_string_remaps["Vsync"] = "V-Sync"; capitalize_string_remaps["Vector 2"] = "Vector2"; + capitalize_string_remaps["Webp"] = "WebP"; capitalize_string_remaps["Webrtc"] = "WebRTC"; capitalize_string_remaps["Websocket"] = "WebSocket"; + capitalize_string_remaps["Xr"] = "XR"; } EditorPropertyNameProcessor::~EditorPropertyNameProcessor() { diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index 85d304ec5d..5db7b8673f 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -83,7 +83,7 @@ void EditorRunNative::_notification(int p_what) { mb->set_tooltip(eep->get_options_tooltip()); for (int i = 0; i < dc; i++) { mb->get_popup()->add_icon_item(eep->get_option_icon(i), eep->get_option_label(i)); - mb->get_popup()->set_item_tooltip(mb->get_popup()->get_item_count() - 1, eep->get_option_tooltip(i)); + mb->get_popup()->set_item_tooltip(-1, eep->get_option_tooltip(i)); } } } @@ -168,7 +168,6 @@ bool EditorRunNative::is_deploy_debug_remote_enabled() const { EditorRunNative::EditorRunNative() { set_process(true); - first = true; resume_idx = 0; resume_platform = 0; } diff --git a/editor/editor_run_native.h b/editor/editor_run_native.h index 199d094e55..4cb5779350 100644 --- a/editor/editor_run_native.h +++ b/editor/editor_run_native.h @@ -38,7 +38,7 @@ class EditorRunNative : public HBoxContainer { GDCLASS(EditorRunNative, HBoxContainer); Map<int, MenuButton *> menus; - bool first; + bool first = true; int resume_idx; int resume_platform; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 45685b8fb2..2d80fe85f8 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -460,6 +460,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/theme/custom_theme", "", "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) // Scene tabs + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/scene_tabs/display_close_button", 1, "Never,If Tab Active,Always"); // TabBar::CloseButtonDisplayPolicy _initial_set("interface/scene_tabs/show_thumbnail_on_hover", true); EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_RANGE, "interface/scene_tabs/maximum_width", 350, "0,9999,1", PROPERTY_USAGE_DEFAULT) _initial_set("interface/scene_tabs/show_script_button", false); @@ -1222,7 +1223,7 @@ bool EditorSettings::is_dark_theme() { void EditorSettings::list_text_editor_themes() { String themes = "Default,Godot 2,Custom"; - DirAccess *d = DirAccess::open(get_text_editor_themes_dir()); + DirAccessRef d = DirAccess::open(get_text_editor_themes_dir()); if (d) { List<String> custom_themes; d->list_dir_begin(); @@ -1234,7 +1235,6 @@ void EditorSettings::list_text_editor_themes() { file = d->get_next(); } d->list_dir_end(); - memdelete(d); custom_themes.sort(); for (const String &E : custom_themes) { @@ -1289,10 +1289,9 @@ bool EditorSettings::import_text_editor_theme(String p_file) { return false; } - DirAccess *d = DirAccess::open(get_text_editor_themes_dir()); + DirAccessRef d = DirAccess::open(get_text_editor_themes_dir()); if (d) { d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file())); - memdelete(d); return true; } } @@ -1342,7 +1341,7 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c if (!p_custom_path.is_empty()) { template_dir = p_custom_path; } - DirAccess *d = DirAccess::open(template_dir); + DirAccessRef d = DirAccess::open(template_dir); if (d) { d->list_dir_begin(); String file = d->get_next(); @@ -1353,7 +1352,6 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c file = d->get_next(); } d->list_dir_end(); - memdelete(d); } return templates; } @@ -1663,8 +1661,6 @@ void EditorSettings::_bind_methods() { EditorSettings::EditorSettings() { last_order = 0; - optimize_save = true; - save_changed_setting = true; _load_defaults(); } diff --git a/editor/editor_settings.h b/editor/editor_settings.h index 65723a24f8..4f25259a01 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -92,8 +92,8 @@ private: Vector<String> favorites; Vector<String> recent_dirs; - bool save_changed_setting; - bool optimize_save; //do not save stuff that came from config but was not set from engine + bool save_changed_setting = true; + bool optimize_save = true; //do not save stuff that came from config but was not set from engine bool _set(const StringName &p_name, const Variant &p_value); bool _set_only(const StringName &p_name, const Variant &p_value); diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index 1ec6d4a3a6..eb3cf08578 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -764,8 +764,6 @@ EditorSettingsDialog::EditorSettingsDialog() { add_child(timer); EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &EditorSettingsDialog::_settings_changed)); get_ok_button()->set_text(TTR("Close")); - - updating = false; } EditorSettingsDialog::~EditorSettingsDialog() { diff --git a/editor/editor_settings_dialog.h b/editor/editor_settings_dialog.h index 4b90506b4b..e3139bb07a 100644 --- a/editor/editor_settings_dialog.h +++ b/editor/editor_settings_dialog.h @@ -43,7 +43,7 @@ class EditorSettingsDialog : public AcceptDialog { GDCLASS(EditorSettingsDialog, AcceptDialog); - bool updating; + bool updating = false; TabContainer *tabs; Control *tab_general; diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 509a316ef3..2fd4f3d6e6 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -443,6 +443,7 @@ void EditorSpinSlider::_notification(int p_what) { case NOTIFICATION_WM_WINDOW_FOCUS_IN: case NOTIFICATION_WM_WINDOW_FOCUS_OUT: + case NOTIFICATION_WM_CLOSE_REQUEST: case NOTIFICATION_EXIT_TREE: { if (grabbing_spinner) { grabber->hide(); @@ -655,14 +656,10 @@ void EditorSpinSlider::_ensure_input_popup() { } EditorSpinSlider::EditorSpinSlider() { - flat = false; - grabbing_spinner_attempt = false; - grabbing_spinner = false; grabbing_spinner_dist_cache = 0; pre_grab_value = 0; set_focus_mode(FOCUS_ALL); updown_offset = -1; - hover_updown = false; grabber = memnew(TextureRect); add_child(grabber); grabber->hide(); @@ -671,12 +668,5 @@ EditorSpinSlider::EditorSpinSlider() { grabber->connect("mouse_entered", callable_mp(this, &EditorSpinSlider::_grabber_mouse_entered)); grabber->connect("mouse_exited", callable_mp(this, &EditorSpinSlider::_grabber_mouse_exited)); grabber->connect("gui_input", callable_mp(this, &EditorSpinSlider::_grabber_gui_input)); - mouse_over_spin = false; - mouse_over_grabber = false; - mousewheel_over_grabber = false; - grabbing_grabber = false; grabber_range = 1; - value_input_just_closed = false; - hide_slider = false; - read_only = false; } diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h index 4e52980804..405c3bfc22 100644 --- a/editor/editor_spin_slider.h +++ b/editor/editor_spin_slider.h @@ -41,24 +41,24 @@ class EditorSpinSlider : public Range { String label; String suffix; int updown_offset; - bool hover_updown; - bool mouse_hover; + bool hover_updown = false; + bool mouse_hover = false; TextureRect *grabber; int grabber_range; - bool mouse_over_spin; - bool mouse_over_grabber; - bool mousewheel_over_grabber; + bool mouse_over_spin = false; + bool mouse_over_grabber = false; + bool mousewheel_over_grabber = false; - bool grabbing_grabber; + bool grabbing_grabber = false; int grabbing_from; float grabbing_ratio; - bool grabbing_spinner_attempt; - bool grabbing_spinner; + bool grabbing_spinner_attempt = false; + bool grabbing_spinner = false; - bool read_only; + bool read_only = false; float grabbing_spinner_dist_cache; Vector2 grabbing_spinner_mouse_pos; double pre_grab_value; @@ -73,8 +73,8 @@ class EditorSpinSlider : public Range { void _value_input_submitted(const String &); void _value_focus_exited(); void _value_input_gui_input(const Ref<InputEvent> &p_event); - bool hide_slider; - bool flat; + bool hide_slider = false; + bool flat = false; void _evaluate_input_text(); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 7eceebb38b..28feac5d2b 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -702,6 +702,19 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("icon_focus_color", "Button", icon_focus_color); theme->set_color("icon_pressed_color", "Button", icon_pressed_color); + // Variation for Editor Log filter buttons + theme->set_type_variation("EditorLogFilterButton", "Button"); + // When pressed, don't tint the icons with the accent color, just leave them normal. + theme->set_color("icon_pressed_color", "EditorLogFilterButton", icon_normal_color); + // When unpressed, dim the icons. + theme->set_color("icon_normal_color", "EditorLogFilterButton", font_disabled_color); + // When pressed, add a small bottom border to the buttons to better show their active state, + // similar to active tabs. + Ref<StyleBoxFlat> editor_log_button_pressed = style_widget_pressed->duplicate(); + editor_log_button_pressed->set_border_width(SIDE_BOTTOM, 2 * EDSCALE); + editor_log_button_pressed->set_border_color(accent_color); + theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed); + // OptionButton theme->set_stylebox("focus", "OptionButton", style_widget_focus); @@ -1519,6 +1532,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("Information3dViewport", "EditorStyles", style_info_3d_viewport); // Asset Library. + theme->set_stylebox("bg", "AssetLib", style_empty); theme->set_stylebox("panel", "AssetLib", style_content_panel); theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5)); theme->set_icon("dismiss", "AssetLib", theme->get_icon(SNAME("Close"), SNAME("EditorIcons"))); diff --git a/editor/editor_vcs_interface.cpp b/editor/editor_vcs_interface.cpp index 97611d9786..0954779300 100644 --- a/editor/editor_vcs_interface.cpp +++ b/editor/editor_vcs_interface.cpp @@ -153,7 +153,6 @@ String EditorVCSInterface::get_vcs_name() { } EditorVCSInterface::EditorVCSInterface() { - is_initialized = false; } EditorVCSInterface::~EditorVCSInterface() { diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h index 091936dadc..487625e84c 100644 --- a/editor/editor_vcs_interface.h +++ b/editor/editor_vcs_interface.h @@ -38,7 +38,7 @@ class EditorVCSInterface : public Object { GDCLASS(EditorVCSInterface, Object) - bool is_initialized; + bool is_initialized = false; protected: static EditorVCSInterface *singleton; diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 0a8d35aff1..df3e73267e 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -44,7 +44,7 @@ void ExportTemplateManager::_update_template_status() { // Fetch installed templates from the file system. - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir(); Error err = da->change_dir(templates_dir); @@ -62,7 +62,6 @@ void ExportTemplateManager::_update_template_status() { } } da->list_dir_end(); - memdelete(da); // Update the state of the current version. String current_version = VERSION_FULL_CONFIG; diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index e8a2a46dd2..038cc2ab2f 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -525,16 +525,14 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa if (target_path.ends_with("/")) { target_path = target_path.substr(0, target_path.length() - 1); } - DirAccess *dirAccess = DirAccess::create(DirAccess::ACCESS_RESOURCES); - if (dirAccess->file_exists(p_path)) { + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (da->file_exists(p_path)) { path = target_path; - } else if (dirAccess->dir_exists(p_path)) { + } else if (da->dir_exists(p_path)) { path = target_path + "/"; } else { - memdelete(dirAccess); ERR_FAIL_MSG(vformat("Cannot navigate to '%s' as it has not been found in the file system!", p_path)); } - memdelete(dirAccess); } _set_current_path_text(path); @@ -781,14 +779,14 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { icon = folder_icon; if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) { files->add_item(text, icon, true); - files->set_item_metadata(files->get_item_count() - 1, favorite); + files->set_item_metadata(-1, favorite); } } else if (favorite.ends_with("/")) { text = favorite.substr(0, favorite.length() - 1).get_file(); icon = folder_icon; if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) { files->add_item(text, icon, true); - files->set_item_metadata(files->get_item_count() - 1, favorite); + files->set_item_metadata(-1, favorite); } } else { int index; @@ -842,9 +840,9 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { bd += "/"; } - files->set_item_metadata(files->get_item_count() - 1, bd); - files->set_item_selectable(files->get_item_count() - 1, false); - files->set_item_icon_modulate(files->get_item_count() - 1, folder_color); + files->set_item_metadata(-1, bd); + files->set_item_selectable(-1, false); + files->set_item_icon_modulate(-1, folder_color); } bool reversed = file_sort == FILE_SORT_NAME_REVERSE; @@ -854,8 +852,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { String dname = efd->get_subdir(i)->get_name(); files->add_item(dname, folder_icon, true); - files->set_item_metadata(files->get_item_count() - 1, directory.plus_file(dname) + "/"); - files->set_item_icon_modulate(files->get_item_count() - 1, folder_color); + files->set_item_metadata(-1, directory.plus_file(dname) + "/"); + files->set_item_icon_modulate(-1, folder_color); if (cselection.has(dname)) { files->select(files->get_item_count() - 1, false); @@ -1171,7 +1169,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_ _get_all_items_in_dir(EditorFileSystem::get_singleton()->get_filesystem_path(old_path), file_changed_paths, folder_changed_paths); } - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); print_verbose("Moving " + old_path + " -> " + new_path); Error err = da->rename(old_path, new_path); if (err == OK) { @@ -1211,7 +1209,6 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_ } else { EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + "\n"); } - memdelete(da); } void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const { @@ -1230,7 +1227,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin return; } - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); print_verbose("Duplicating " + old_path + " -> " + new_path); Error err = p_item.is_file ? da->copy(old_path, new_path) : da->copy_dir(old_path, new_path); if (err == OK) { @@ -1268,7 +1265,6 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin } else { EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + "\n"); } - memdelete(da); } void FileSystemDock::_update_resource_paths_after_move(const Map<String, String> &p_renames) const { @@ -1418,12 +1414,11 @@ void FileSystemDock::_make_dir_confirm() { directory = directory.get_base_dir(); } print_verbose("Making folder " + dir_name + " in " + directory); - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); Error err = da->change_dir(directory); if (err == OK) { err = da->make_dir(dir_name); } - memdelete(da); if (err == OK) { print_verbose("FileSystem: calling rescan."); @@ -1464,13 +1459,11 @@ void FileSystemDock::_make_scene_confirm() { scene_name = directory.plus_file(scene_name); - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (da->file_exists(scene_name)) { EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists.")); - memdelete(da); return; } - memdelete(da); int idx = EditorNode::get_singleton()->new_scene(); EditorNode::get_singleton()->get_editor_data().set_scene_path(idx, scene_name); @@ -1533,7 +1526,7 @@ void FileSystemDock::_rename_operation_confirm() { } // Present a more user friendly warning for name conflict. - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); #if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED) // Workaround case insensitivity on Windows. if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) { @@ -1541,10 +1534,8 @@ void FileSystemDock::_rename_operation_confirm() { if (da->file_exists(new_path) || da->dir_exists(new_path)) { #endif EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists.")); - memdelete(da); return; } - memdelete(da); Map<String, String> file_renames; Map<String, String> folder_renames; @@ -1588,13 +1579,11 @@ void FileSystemDock::_duplicate_operation_confirm() { String new_path = base_dir.plus_file(new_name); // Present a more user friendly warning for name conflict - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (da->file_exists(new_path) || da->dir_exists(new_path)) { EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists.")); - memdelete(da); return; } - memdelete(da); _try_duplicate_item(to_duplicate, new_path); @@ -2098,6 +2087,10 @@ void FileSystemDock::focus_on_filter() { } } +ScriptCreateDialog *FileSystemDock::get_script_create_dialog() const { + return make_script_dialog; +} + void FileSystemDock::set_file_list_display_mode(FileListDisplayMode p_mode) { if (p_mode == file_list_display_mode) { return; @@ -2818,7 +2811,7 @@ void FileSystemDock::_get_imported_files(const String &p_path, Vector<String> &f return; } - DirAccess *da = DirAccess::open(p_path); + DirAccessRef da = DirAccess::open(p_path); da->list_dir_begin(); String n = da->get_next(); while (!n.is_empty()) { @@ -3179,10 +3172,7 @@ FileSystemDock::FileSystemDock() { searched_string = String(); uncollapsed_paths_before_search = Vector<String>(); - updating_tree = false; tree_update_id = 0; - initialized = false; - import_dock_needs_update = false; history_pos = 0; history_max_size = 20; @@ -3191,8 +3181,6 @@ FileSystemDock::FileSystemDock() { display_mode = DISPLAY_MODE_TREE_ONLY; old_display_mode = DISPLAY_MODE_TREE_ONLY; file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; - - always_show_folders = false; } FileSystemDock::~FileSystemDock() { diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index d457c6acd4..92dac374ec 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -154,7 +154,7 @@ private: ShaderCreateDialog *make_shader_dialog; CreateDialog *new_resource_dialog; - bool always_show_folders; + bool always_show_folders = false; class FileOrFolder { public: @@ -177,13 +177,13 @@ private: String path; - bool initialized; + bool initialized = false; - bool updating_tree; + bool updating_tree = false; int tree_update_id; Tree *tree; ItemList *files; - bool import_dock_needs_update; + bool import_dock_needs_update = false; bool holding_branch = false; Vector<TreeItem *> tree_items_selected_on_drag_begin; @@ -320,6 +320,8 @@ public: void navigate_to_path(const String &p_path); void focus_on_filter(); + ScriptCreateDialog *get_script_create_dialog() const; + void fix_dependencies(const String &p_for_file); int get_split_offset() { return split_box->get_split_offset(); } diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index eff9185c71..1ce363c651 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -612,8 +612,6 @@ FindInFilesPanel::FindInFilesPanel() { _results_display->create_item(); // Root vbc->add_child(_results_display); - _with_replace = false; - { _replace_container = memnew(HBoxContainer); diff --git a/editor/find_in_files.h b/editor/find_in_files.h index 1b6666b554..cf14f3d5c3 100644 --- a/editor/find_in_files.h +++ b/editor/find_in_files.h @@ -210,7 +210,7 @@ private: ProgressBar *_progress_bar; Map<String, TreeItem *> _file_items; Map<TreeItem *, Result> _result_items; - bool _with_replace; + bool _with_replace = false; HBoxContainer *_replace_container; LineEdit *_replace_line_edit; diff --git a/editor/icons/StreamTexture.svg b/editor/icons/CompressedTexture2D.svg index 068f65dead..068f65dead 100644 --- a/editor/icons/StreamTexture.svg +++ b/editor/icons/CompressedTexture2D.svg diff --git a/editor/icons/ViewportSpeed.svg b/editor/icons/ViewportSpeed.svg index 8fceaffd52..57292e2e91 100644 --- a/editor/icons/ViewportSpeed.svg +++ b/editor/icons/ViewportSpeed.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 4.2333333 4.2333333" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.5875 0c-.28858 0-.52917.24059-.52917.52917v.61132c-.085589-.051-.18113-.0891-.28525-.0853-.34849.0127-.5952.37346-.48059.70278l.26355.79066c.048664.14623.15979.24805.29249.30644l-.60927.40669c-.13121.0845-.22102.22389-.24133.3633-.020312.13941.017471.26985.087333.37465s.17614.19045.31264.22532c.13634.0348.29946.006.42788-.0827h.0005159l1.0852-.72348.26097.52192c.11682.23391.39274.34829.64079.26561l.79375-.26458-.00775.003c.15105-.0454.27732-.15615.33486-.2863.057538-.13015.055144-.26773.014986-.38809-.03156-.0946-.10972-.1687-.19275-.23617.069099-.0546.1445-.10364.18035-.19325.051761-.12941.045257-.29292-.02377-.43098l-.26459-.52946c-.089407-.17933-.27348-.29308-.47335-.29305h-.1111c.052029-.0817.1111-.16214.1111-.26458v-.79375c0-.28858-.24059-.52917-.52917-.52917z"/><path d="m1.5875.26458c-.14658 0-.26458.118-.26458.26459v.79375c0 .14658.118.26458.26458.26458h.26458v.262a.26461.26461 0 0 0 -.083716.0165l-.5426.18086-.18087-.5426a.26461.26461 0 0 0 -.262-.18448.26461.26461 0 0 0 -.2403.3514l.26458.79375a.26461.26461 0 0 0 .33486.16743l.44545-.14831v.16174c0 .0108.00495.02.0062.0305l-1.2113.80771a.26461.26461 0 1 0 .29352.44028l1.3379-.89194.39532.79014a.26461.26461 0 0 0 .32039.1328l.79375-.26458a.26461.26461 0 1 0 -.16743-.50175l-.57619.19172-.25787-.51625c.072998-.047.12402-.12495.12402-.21859v-.26458h.36587l.1912.38292a.26461.26461 0 1 0 .47336-.23668l-.26458-.52916a.26461.26461 0 0 0 -.23668-.14625h-.79375v-.26458h.26458c.14658 0 .26458-.118.26458-.26458v-.79375c0-.14659-.118-.26459-.26458-.26459zm0 .52917h.26458v.52917h-.26458z" fill="#fff" fill-opacity=".99608"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width="3.77953"><path d="m6.0285136 0c-1.0906961 0-2.0000127.90931655-2.0000127 2.0000126v2.3105008c-.3234859-.1927559-.6845858-.3367559-1.0781102-.3223937-1.3171276.048-2.24957487 1.4115024-1.8164032 2.6561764l.9960945 2.9883213c.183927.5526806.6039307.9375116 1.1054741 1.1581986l-2.30275287 1.537096c-.49591181.31937-.83535119.846198-.91211339 1.373102-.07676977.526904.06603212 1.019906.33007748 1.416.26404536.396095.66572598.719811 1.18163158.851603.5153008.131528 1.1318173.02268 1.6171842-.312566h.00195l4.1015433-2.734413.9863434 1.972611c.4415244.884069 1.4843716 1.316372 2.4218832 1.00388l3-.999987-.02929.01134c.570898-.17159 1.048139-.590173 1.265613-1.082078.217466-.491906.208418-1.011893.05664-1.466797-.119282-.357543-.41469-.637606-.728504-.892611.261162-.206362.546142-.39171.681638-.730394.195632-.489109.17105-1.1070991-.08984-1.6289007l-1.000027-2.0011107c-.337916-.6777827-1.033625-1.1077039-1.789039-1.1075905h-.419906c.196645-.3087874.419906-.6128126.419906-.9999874v-3.0000001c0-1.09069605-.909317-2.0000126-2.000012-2.0000126z"/><path d="m6.0285136.99998741c-.5540032 0-.9999874.44598429-.9999874 1.00002519v3.0000001c0 .5540031.4459842.9999874.9999874.9999874h.9999874v.9902362a1.0001008 1.0001008 0 0 0 -.316407.062362l-2.0507716.6835656-.6836032-2.0507717a1.0001008 1.0001008 0 0 0 -.9902362-.6972473 1.0001008 1.0001008 0 0 0 -.9082205 1.328126l.9999874 3.0000001a1.0001008 1.0001008 0 0 0 1.2656126.6328063l1.6835906-.5605418v.6113008c0 .040819.018709.075591.023433.1152757l-4.5781418 3.052762a1.0001008 1.0001008 0 1 0 1.1093669 1.664051l5.05663-3.371112 1.4941228 2.986356a1.0001008 1.0001008 0 0 0 1.210922.501921l3.000001-.999987a1.0001008 1.0001008 0 1 0 -.632807-1.896378l-2.177726.724611-.9746262-1.951182c.275898-.177637.4687372-.472252.4687372-.8261665v-.9999874h1.382815l.722646 1.4472569a1.0001246 1.0001246 0 1 0 1.789077-.8945388l-.999987-1.9999748a1.0001008 1.0001008 0 0 0 -.894539-.5527559h-2.9999995v-.9999874h.9999875c.554003 0 .999987-.4459843.999987-.9999874v-3.0000001c0-.5540409-.445984-1.00002519-.999987-1.00002519zm0 2.00001259h.9999874v2.0000127h-.9999874z" fill="#fff" fill-opacity=".99608"/></g></svg> diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index f0a2d7d553..2ecc483938 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -484,6 +484,14 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper if (font_preview->get_data_count() > 0) { font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int()); } + } else if (p_edited_property == "embolden") { + if (font_preview->get_data_count() > 0) { + font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden")); + } + } else if (p_edited_property == "transform") { + if (font_preview->get_data_count() > 0) { + font_preview->get_data(0)->set_transform(import_settings_data->get("transform")); + } } else if (p_edited_property == "oversampling") { if (font_preview->get_data_count() > 0) { font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling")); @@ -924,6 +932,8 @@ void DynamicFontImportSettings::_re_import() { main_settings["force_autohinter"] = import_settings_data->get("force_autohinter"); main_settings["hinting"] = import_settings_data->get("hinting"); main_settings["subpixel_positioning"] = import_settings_data->get("subpixel_positioning"); + main_settings["embolden"] = import_settings_data->get("embolden"); + main_settings["transform"] = import_settings_data->get("transform"); main_settings["oversampling"] = import_settings_data->get("oversampling"); main_settings["compress"] = import_settings_data->get("compress"); @@ -1275,6 +1285,8 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { font_preview->get_data(0)->set_force_autohinter(import_settings_data->get("force_autohinter")); font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int()); font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int()); + font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden")); + font_preview->get_data(0)->set_transform(import_settings_data->get("transform")); font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling")); } font_preview_label->add_theme_font_override("font", font_preview); @@ -1334,6 +1346,8 @@ DynamicFontImportSettings::DynamicFontImportSettings() { options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1)); + options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f)); + options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D())); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, ""), false)); diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index 70fc87ea3f..077b94bb4e 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -109,6 +109,8 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List< r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f)); + r_options->push_back(ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D())); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true)); @@ -186,6 +188,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str int hinting = p_options["hinting"]; int subpixel_positioning = p_options["subpixel_positioning"]; real_t oversampling = p_options["oversampling"]; + real_t embolden = p_options["embolden"]; + Transform2D transform = p_options["transform"]; // Load base font data. Vector<uint8_t> data = FileAccess::get_file_as_array(p_source_file); @@ -202,6 +206,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str font->set_fixed_size(0); font->set_force_autohinter(autohinter); font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning); + font->set_embolden(embolden); + font->set_transform(transform); font->set_hinting((TextServer::Hinting)hinting); font->set_oversampling(oversampling); diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index 197cc49a95..9ddee9c058 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -85,16 +85,16 @@ void ResourceImporterLayeredTexture::get_recognized_extensions(List<String> *p_e String ResourceImporterLayeredTexture::get_save_extension() const { switch (mode) { case MODE_CUBEMAP: { - return "scube"; + return "ccube"; } break; case MODE_2D_ARRAY: { - return "stexarray"; + return "ctexarray"; } break; case MODE_CUBEMAP_ARRAY: { - return "scubearray"; + return "ccubearray"; } break; case MODE_3D: { - return "stex3d"; + return "ctex3d"; } break; } @@ -274,11 +274,11 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons f->store_32(0); for (int i = 0; i < p_images.size(); i++) { - ResourceImporterTexture::save_to_stex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy); + ResourceImporterTexture::save_to_ctex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy); } for (int i = 0; i < mipmap_images.size(); i++) { - ResourceImporterTexture::save_to_stex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy); + ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy); } f->close(); @@ -393,7 +393,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const texture_import->bptc_ldr = bptc_ldr; texture_import->mipmaps = mipmaps; texture_import->used_channels = used_channels; - _check_compress_stex(texture_import); + _check_compress_ctex(texture_import); if (r_metadata) { Dictionary metadata; metadata["vram_texture"] = compress_mode == COMPRESS_VRAM_COMPRESSED; @@ -474,7 +474,7 @@ ResourceImporterLayeredTexture::ResourceImporterLayeredTexture() { ResourceImporterLayeredTexture::~ResourceImporterLayeredTexture() { } -void ResourceImporterLayeredTexture::_check_compress_stex(Ref<LayeredTextureImport> r_texture_import) { +void ResourceImporterLayeredTexture::_check_compress_ctex(Ref<LayeredTextureImport> r_texture_import) { String extension = get_save_extension(); ERR_FAIL_NULL(r_texture_import->csource); if (r_texture_import->compress_mode != COMPRESS_VRAM_COMPRESSED) { diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 58e5c47d8d..5791914a9b 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -87,7 +87,7 @@ protected: static ResourceImporterLayeredTexture *singleton; public: - void _check_compress_stex(Ref<LayeredTextureImport> r_texture_import); + void _check_compress_ctex(Ref<LayeredTextureImport> r_texture_import); static ResourceImporterLayeredTexture *get_singleton() { return singleton; } virtual String get_importer_name() const override; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index e672fe2dee..1dec4b00bb 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -225,7 +225,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo } } -void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) { +void ResourceImporterTexture::save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) { switch (p_compress_mode) { case COMPRESS_LOSSLESS: { bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png") || @@ -317,7 +317,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image } } -void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) { +void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) { FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE); ERR_FAIL_NULL(f); f->store_8('G'); @@ -394,7 +394,7 @@ void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String Image::UsedChannels used_channels = image->detect_used_channels(csource); - save_to_stex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality); + save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality); memdelete(f); } @@ -540,19 +540,19 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String if (!bptc_ldr && can_s3tc && is_ldr) { image_compress_mode = Image::COMPRESS_S3TC; } - _save_stex(image, p_save_path + ".s3tc.ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + _save_ctex(image, p_save_path + ".s3tc.ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("s3tc"); formats_imported.push_back("s3tc"); } if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2")) { - _save_stex(image, p_save_path + ".etc2.ctex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); + _save_ctex(image, p_save_path + ".etc2.ctex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("etc2"); formats_imported.push_back("etc2"); } if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc")) { - _save_stex(image, p_save_path + ".etc.ctex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); + _save_ctex(image, p_save_path + ".etc.ctex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back("etc"); formats_imported.push_back("etc"); } @@ -562,7 +562,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } } else { //import normally - _save_stex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + _save_ctex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); } if (r_metadata) { diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index bd43eaef58..b3a68260fc 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -74,10 +74,10 @@ protected: static ResourceImporterTexture *singleton; static const char *compression_formats[]; - void _save_stex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel); + void _save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel); public: - static void save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality); + static void save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality); static ResourceImporterTexture *get_singleton() { return singleton; } virtual String get_importer_name() const override; diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 72cc33048c..9f1daac69f 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -128,7 +128,7 @@ void ImportDock::set_edit_path(const String &p_path) { for (const Pair<String, String> &E : importer_names) { import_as->add_item(E.first); - import_as->set_item_metadata(import_as->get_item_count() - 1, E.second); + import_as->set_item_metadata(-1, E.second); if (E.second == importer_name) { import_as->select(import_as->get_item_count() - 1); } @@ -149,7 +149,7 @@ void ImportDock::set_edit_path(const String &p_path) { void ImportDock::_add_keep_import_option(const String &p_importer_name) { import_as->add_separator(); import_as->add_item(TTR("Keep File (No Import)")); - import_as->set_item_metadata(import_as->get_item_count() - 1, "keep"); + import_as->set_item_metadata(-1, "keep"); if (p_importer_name == "keep") { import_as->select(import_as->get_item_count() - 1); } @@ -286,7 +286,7 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { for (const Pair<String, String> &E : importer_names) { import_as->add_item(E.first); - import_as->set_item_metadata(import_as->get_item_count() - 1, E.second); + import_as->set_item_metadata(-1, E.second); if (E.second == params->importer->get_importer_name()) { import_as->select(import_as->get_item_count() - 1); } diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index a766650cd9..77594dde78 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -473,7 +473,6 @@ void LocalizationEditor::_bind_methods() { LocalizationEditor::LocalizationEditor() { undo_redo = EditorNode::get_undo_redo(); - updating_translations = false; localization_changed = "localization_changed"; TabContainer *translations = memnew(TabContainer); diff --git a/editor/localization_editor.h b/editor/localization_editor.h index bde1b894e2..3424ba7c55 100644 --- a/editor/localization_editor.h +++ b/editor/localization_editor.h @@ -56,7 +56,7 @@ class LocalizationEditor : public VBoxContainer { EditorFileDialog *pot_generate_dialog; UndoRedo *undo_redo; - bool updating_translations; + bool updating_translations = false; String localization_changed; void _translation_file_open(); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index d5e7c312d9..02cc95e14a 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -50,7 +50,7 @@ void PluginConfigDialog::_on_confirmed() { String path = "res://addons/" + subfolder_edit->get_text(); if (!_edit_mode) { - DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (!d || d->make_dir_recursive(path) != OK) { return; } diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 5a2696fff1..22e0a3dabb 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -292,15 +292,14 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) _commit_action(); return true; } else { - Vector<Vector2> vertices2 = _get_polygon(insert.polygon); - pre_move_edit = vertices2; + pre_move_edit = vertices; edited_point = PosVertex(insert.polygon, insert.vertex + 1, xform.affine_inverse().xform(insert.pos)); - vertices2.insert(edited_point.vertex, edited_point.pos); + vertices.insert(edited_point.vertex, edited_point.pos); selected_point = Vertex(edited_point.polygon, edited_point.vertex); edge_point = PosVertex(); undo_redo->create_action(TTR("Insert Point")); - _action_set_polygon(insert.polygon, vertices2); + _action_set_polygon(insert.polygon, vertices); _commit_action(); return true; } diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index fba6d8e57f..ab8e2ca54a 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -897,11 +897,6 @@ void AnimationPlayerEditor::_update_player() { } void AnimationPlayerEditor::_update_animation_list_icons() { - List<StringName> animlist; - if (player) { - player->get_animation_list(&animlist); - } - for (int i = 0; i < animation->get_item_count(); i++) { String name = animation->get_item_text(i); @@ -1675,11 +1670,11 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug onion_skinning->set_tooltip(TTR("Onion Skinning Options")); onion_skinning->get_popup()->add_separator(TTR("Directions")); onion_skinning->get_popup()->add_check_item(TTR("Past"), ONION_SKINNING_PAST); - onion_skinning->get_popup()->set_item_checked(onion_skinning->get_popup()->get_item_count() - 1, true); + onion_skinning->get_popup()->set_item_checked(-1, true); onion_skinning->get_popup()->add_check_item(TTR("Future"), ONION_SKINNING_FUTURE); onion_skinning->get_popup()->add_separator(TTR("Depth")); onion_skinning->get_popup()->add_radio_check_item(TTR("1 step"), ONION_SKINNING_1_STEP); - onion_skinning->get_popup()->set_item_checked(onion_skinning->get_popup()->get_item_count() - 1, true); + onion_skinning->get_popup()->set_item_checked(-1, true); onion_skinning->get_popup()->add_radio_check_item(TTR("2 steps"), ONION_SKINNING_2_STEPS); onion_skinning->get_popup()->add_radio_check_item(TTR("3 steps"), ONION_SKINNING_3_STEPS); onion_skinning->get_popup()->add_separator(); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 2f94176e2a..bd0c1afd19 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -346,29 +346,21 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv state_machine_draw->update(); } - //put ibeam (text cursor) over names to make it clearer that they are editable if (mm.is_valid()) { state_machine_draw->grab_focus(); - bool over_text_now = false; String new_over_node = StringName(); int new_over_node_what = -1; if (tool_select->is_pressed()) { - for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order - - if (node_rects[i].name.has_point(mm->get_position())) { - over_text_now = true; - break; - } - + for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order. if (node_rects[i].node.has_point(mm->get_position())) { new_over_node = node_rects[i].node_name; if (node_rects[i].play.has_point(mm->get_position())) { new_over_node_what = 0; - } - if (node_rects[i].edit.has_point(mm->get_position())) { + } else if (node_rects[i].edit.has_point(mm->get_position())) { new_over_node_what = 1; } + break; } } } @@ -378,16 +370,6 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv over_node_what = new_over_node_what; state_machine_draw->update(); } - - if (over_text != over_text_now) { - if (over_text_now) { - state_machine_draw->set_default_cursor_shape(CURSOR_IBEAM); - } else { - state_machine_draw->set_default_cursor_shape(CURSOR_ARROW); - } - - over_text = over_text_now; - } } Ref<InputEventPanGesture> pan_gesture = p_event; @@ -397,6 +379,23 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } } +Control::CursorShape AnimationNodeStateMachineEditor::get_cursor_shape(const Point2 &p_pos) const { + // Put ibeam (text cursor) over names to make it clearer that they are editable. + Transform2D xform = panel->get_transform() * state_machine_draw->get_transform(); + Point2 pos = xform.xform_inv(p_pos); + Control::CursorShape cursor_shape = get_default_cursor_shape(); + + for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order. + if (node_rects[i].node.has_point(pos)) { + if (node_rects[i].name.has_point(pos)) { + cursor_shape = Control::CURSOR_IBEAM; + } + break; + } + } + return cursor_shape; +} + void AnimationNodeStateMachineEditor::_file_opened(const String &p_file) { file_loaded = ResourceLoader::load(p_file); if (file_loaded.is_valid()) { @@ -1287,6 +1286,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { panel = memnew(PanelContainer); panel->set_clip_contents(true); + panel->set_mouse_filter(Control::MOUSE_FILTER_PASS); add_child(panel); panel->set_v_size_flags(SIZE_EXPAND_FILL); @@ -1295,6 +1295,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { state_machine_draw->connect("gui_input", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_gui_input)); state_machine_draw->connect("draw", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_draw)); state_machine_draw->set_focus_mode(FOCUS_ALL); + state_machine_draw->set_mouse_filter(Control::MOUSE_FILTER_PASS); state_machine_play_pos = memnew(Control); state_machine_draw->add_child(state_machine_play_pos); @@ -1347,8 +1348,6 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { open_file->connect("file_selected", callable_mp(this, &AnimationNodeStateMachineEditor::_file_opened)); undo_redo = EditorNode::get_undo_redo(); - over_text = false; - over_node_what = -1; dragging_selected_attempt = false; connecting = false; diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index 208bd27f8e..03991d00f9 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -138,7 +138,6 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { StringName selected_transition_from; StringName selected_transition_to; - bool over_text; StringName over_node; int over_node_what; @@ -185,6 +184,7 @@ public: static AnimationNodeStateMachineEditor *get_singleton() { return singleton; } virtual bool can_edit(const Ref<AnimationNode> &p_node) override; virtual void edit(const Ref<AnimationNode> &p_node) override; + virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override; AnimationNodeStateMachineEditor(); }; diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 50f253b167..1468d63daf 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -577,6 +577,7 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { void EditorAssetLibrary::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { + add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("AssetLib"))); error_label->raise(); } break; @@ -1145,7 +1146,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const String name = cat["name"]; int id = cat["id"]; categories->add_item(name); - categories->set_item_metadata(categories->get_item_count() - 1, id); + categories->set_item_metadata(-1, id); category_map[cat["id"]] = name; } } @@ -1377,7 +1378,6 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { initial_loading = true; VBoxContainer *library_main = memnew(VBoxContainer); - add_child(library_main); HBoxContainer *search_hb = memnew(HBoxContainer); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 75f97efdbc..d713e70251 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -60,12 +60,12 @@ // Min and Max are power of two in order to play nicely with successive increment. // That way, we can naturally reach a 100% zoom from boundaries. -#define MIN_ZOOM 1. / 128 -#define MAX_ZOOM 128 +constexpr real_t MIN_ZOOM = 1. / 128; +constexpr real_t MAX_ZOOM = 128; #define RULER_WIDTH (15 * EDSCALE) -#define SCALE_HANDLE_DISTANCE 25 -#define MOVE_HANDLE_DISTANCE 25 +constexpr real_t SCALE_HANDLE_DISTANCE = 25; +constexpr real_t MOVE_HANDLE_DISTANCE = 25; class SnapDialog : public ConfirmationDialog { GDCLASS(SnapDialog, ConfirmationDialog); @@ -489,12 +489,12 @@ void CanvasItemEditor::unhandled_key_input(const Ref<InputEvent> &p_ev) { viewport->update(); } - if (k->is_pressed() && !k->is_ctrl_pressed() && !k->is_echo()) { - if ((grid_snap_active || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->matches_event(p_ev)) { + if (k->is_pressed() && !k->is_ctrl_pressed() && !k->is_echo() && (grid_snap_active || _is_grid_visible())) { + if (multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->matches_event(p_ev)) { // Multiply the grid size grid_step_multiplier = MIN(grid_step_multiplier + 1, 12); viewport->update(); - } else if ((grid_snap_active || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->matches_event(p_ev)) { + } else if (divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->matches_event(p_ev)) { // Divide the grid size Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1); if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0) { @@ -938,6 +938,60 @@ void CanvasItemEditor::_reset_create_position() { node_create_position = Point2(); } +bool CanvasItemEditor::_is_grid_visible() const { + switch (grid_visibility) { + case GRID_VISIBILITY_SHOW: + return true; + case GRID_VISIBILITY_SHOW_WHEN_SNAPPING: + return grid_snap_active; + case GRID_VISIBILITY_HIDE: + return false; + } + ERR_FAIL_V_MSG(true, "Unexpected grid_visibility value"); +} + +void CanvasItemEditor::_prepare_grid_menu() { + for (int i = GRID_VISIBILITY_SHOW; i <= GRID_VISIBILITY_HIDE; i++) { + grid_menu->set_item_checked(i, i == grid_visibility); + } +} + +void CanvasItemEditor::_on_grid_menu_id_pressed(int p_id) { + switch (p_id) { + case GRID_VISIBILITY_SHOW: + case GRID_VISIBILITY_SHOW_WHEN_SNAPPING: + case GRID_VISIBILITY_HIDE: + grid_visibility = (GridVisibility)p_id; + viewport->update(); + view_menu->get_popup()->hide(); + return; + } + + // Toggle grid: go to the least restrictive option possible. + if (grid_snap_active) { + switch (grid_visibility) { + case GRID_VISIBILITY_SHOW: + case GRID_VISIBILITY_SHOW_WHEN_SNAPPING: + grid_visibility = GRID_VISIBILITY_HIDE; + break; + case GRID_VISIBILITY_HIDE: + grid_visibility = GRID_VISIBILITY_SHOW_WHEN_SNAPPING; + break; + } + } else { + switch (grid_visibility) { + case GRID_VISIBILITY_SHOW: + grid_visibility = GRID_VISIBILITY_SHOW_WHEN_SNAPPING; + break; + case GRID_VISIBILITY_SHOW_WHEN_SNAPPING: + case GRID_VISIBILITY_HIDE: + grid_visibility = GRID_VISIBILITY_SHOW; + break; + } + } + viewport->update(); +} + bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> b = p_event; Ref<InputEventMouseMotion> m = p_event; @@ -1139,6 +1193,8 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve } } } + snap_target[0] = SNAP_TARGET_NONE; + snap_target[1] = SNAP_TARGET_NONE; drag_type = DRAG_NONE; viewport->update(); return true; @@ -2160,7 +2216,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; if (drag_type == DRAG_NONE) { - if (b.is_valid() && + if (b.is_valid() && b->is_pressed() && ((b->get_button_index() == MouseButton::RIGHT && b->is_alt_pressed() && tool == TOOL_SELECT) || (b->get_button_index() == MouseButton::LEFT && tool == TOOL_LIST_SELECT))) { // Popup the selection menu list @@ -2726,7 +2782,7 @@ void CanvasItemEditor::_draw_rulers() { // The rule transform Transform2D ruler_transform = Transform2D(); - if (show_grid || grid_snap_active) { + if (grid_snap_active || _is_grid_visible()) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (snap_relative && selection.size() > 0) { ruler_transform.translate(_get_encompassing_rect_from_list(selection).position); @@ -2806,7 +2862,7 @@ void CanvasItemEditor::_draw_rulers() { } void CanvasItemEditor::_draw_grid() { - if (show_grid || grid_snap_active) { + if (_is_grid_visible()) { // Draw the grid Vector2 real_grid_offset; const List<CanvasItem *> selection = _get_edited_canvas_items(); @@ -4137,12 +4193,6 @@ void CanvasItemEditor::_update_override_camera_button(bool p_game_running) { void CanvasItemEditor::_popup_callback(int p_op) { last_option = MenuOption(p_op); switch (p_op) { - case SHOW_GRID: { - show_grid = !show_grid; - int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); - view_menu->get_popup()->set_item_checked(idx, show_grid); - viewport->update(); - } break; case SHOW_ORIGIN: { show_origin = !show_origin; int idx = view_menu->get_popup()->get_item_index(SHOW_ORIGIN); @@ -4615,7 +4665,7 @@ Dictionary CanvasItemEditor::get_state() const { state["snap_node_center"] = snap_node_center; state["snap_other_nodes"] = snap_other_nodes; state["snap_guides"] = snap_guides; - state["show_grid"] = show_grid; + state["grid_visibility"] = grid_visibility; state["show_origin"] = show_origin; state["show_viewport"] = show_viewport; state["show_rulers"] = show_rulers; @@ -4717,10 +4767,8 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { smartsnap_config_popup->set_item_checked(idx, snap_guides); } - if (state.has("show_grid")) { - show_grid = state["show_grid"]; - int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); - view_menu->get_popup()->set_item_checked(idx, show_grid); + if (state.has("grid_visibility")) { + grid_visibility = (GridVisibility)(int)(state["grid_visibility"]); } if (state.has("show_origin")) { @@ -5130,7 +5178,19 @@ CanvasItemEditor::CanvasItemEditor() { p = view_menu->get_popup(); p->set_hide_on_checkable_item_selection(false); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), Key::NUMBERSIGN), SHOW_GRID); + + grid_menu = memnew(PopupMenu); + grid_menu->connect("about_to_popup", callable_mp(this, &CanvasItemEditor::_prepare_grid_menu)); + grid_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_on_grid_menu_id_pressed)); + grid_menu->set_name("GridMenu"); + grid_menu->add_radio_check_item(TTR("Show"), GRID_VISIBILITY_SHOW); + grid_menu->add_radio_check_item(TTR("Show When Snapping"), GRID_VISIBILITY_SHOW_WHEN_SNAPPING); + grid_menu->add_radio_check_item(TTR("Hide"), GRID_VISIBILITY_HIDE); + grid_menu->add_separator(); + grid_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/toggle_grid", TTR("Toggle Grid"), KeyModifierMask::CMD | Key::APOSTROPHE)); + p->add_child(grid_menu); + p->add_submenu_item(TTR("Grid"), "GridMenu"); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), Key::H), SHOW_HELPERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), Key::Y), SHOW_GUIDES); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index e7c265ee02..1a9d49a4a8 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -116,7 +116,6 @@ private: SNAP_RELATIVE, SNAP_CONFIGURE, SNAP_USE_PIXEL, - SHOW_GRID, SHOW_HELPERS, SHOW_RULERS, SHOW_GUIDES, @@ -175,6 +174,12 @@ private: DRAG_KEY_MOVE }; + enum GridVisibility { + GRID_VISIBILITY_SHOW, + GRID_VISIBILITY_SHOW_WHEN_SNAPPING, + GRID_VISIBILITY_HIDE, + }; + bool selection_menu_additive_selection; Tool tool = TOOL_SELECT; @@ -190,7 +195,7 @@ private: HBoxContainer *hbc_context_menu; Transform2D transform; - bool show_grid = false; + GridVisibility grid_visibility = GRID_VISIBILITY_SHOW_WHEN_SNAPPING; bool show_rulers = true; bool show_guides = true; bool show_origin = true; @@ -314,6 +319,7 @@ private: MenuButton *skeleton_menu; Button *override_camera_button; MenuButton *view_menu; + PopupMenu *grid_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; @@ -390,6 +396,9 @@ private: void _node_created(Node *p_node); void _reset_create_position(); void _update_editor_settings(); + bool _is_grid_visible() const; + void _prepare_grid_menu(); + void _on_grid_menu_id_pressed(int p_id); UndoRedo *undo_redo; diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp index 501becac57..c8d5aa3fdc 100644 --- a/editor/plugins/debugger_editor_plugin.cpp +++ b/editor/plugins/debugger_editor_plugin.cpp @@ -63,30 +63,24 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(MenuButton *p_debug_menu) { PopupMenu *p = debug_menu->get_popup(); p->set_hide_on_checkable_item_selection(false); p->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG); - p->set_item_tooltip( - p->get_item_count() - 1, + p->set_item_tooltip(-1, TTR("When this option is enabled, using one-click deploy will make the executable attempt to connect to this computer's IP so the running project can be debugged.\nThis option is intended to be used for remote debugging (typically with a mobile device).\nYou don't need to enable it to use the GDScript debugger locally.")); p->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network Filesystem")), RUN_FILE_SERVER); - p->set_item_tooltip( - p->get_item_count() - 1, + p->set_item_tooltip(-1, TTR("When this option is enabled, using one-click deploy for Android will only export an executable without the project data.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploying will use the USB cable for faster performance. This option speeds up testing for projects with large assets.")); p->add_separator(); p->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS); - p->set_item_tooltip( - p->get_item_count() - 1, + p->set_item_tooltip(-1, TTR("When this option is enabled, collision shapes and raycast nodes (for 2D and 3D) will be visible in the running project.")); p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION); - p->set_item_tooltip( - p->get_item_count() - 1, + p->set_item_tooltip(-1, TTR("When this option is enabled, navigation meshes and polygons will be visible in the running project.")); p->add_separator(); p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Synchronize Scene Changes")), RUN_LIVE_DEBUG); - p->set_item_tooltip( - p->get_item_count() - 1, + p->set_item_tooltip(-1, TTR("When this option is enabled, any changes made to the scene in the editor will be replicated in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled.")); p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Synchronize Script Changes")), RUN_RELOAD_SCRIPTS); - p->set_item_tooltip( - p->get_item_count() - 1, + p->set_item_tooltip(-1, TTR("When this option is enabled, any script that is saved will be reloaded in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled.")); // Multi-instance, start/stop diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h new file mode 100644 index 0000000000..8ed72b1c42 --- /dev/null +++ b/editor/plugins/gdextension_export_plugin.h @@ -0,0 +1,138 @@ +/*************************************************************************/ +/* gdextension_export_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef GDEXTENSION_EXPORT_PLUGIN_H +#define GDEXTENSION_EXPORT_PLUGIN_H + +#include "editor/editor_export.h" + +class GDExtensionExportPlugin : public EditorExportPlugin { +protected: + virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); +}; + +void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { + if (p_type != "NativeExtension") { + return; + } + + Ref<ConfigFile> config; + config.instantiate(); + + Error err = config->load(p_path); + + if (err != OK) { + return; + } + + if (!config->has_section_key("configuration", "entry_symbol")) { + return; + } + + String entry_symbol = config->get_value("configuration", "entry_symbol"); + + List<String> libraries; + + config->get_section_keys("libraries", &libraries); + + for (const String &E : libraries) { + Vector<String> tags = E.split("."); + bool all_tags_met = true; + for (int i = 0; i < tags.size(); i++) { + String tag = tags[i].strip_edges(); + if (!p_features.has(tag)) { + all_tags_met = false; + break; + } + } + + if (all_tags_met) { + String library_path = config->get_value("libraries", E); + if (!library_path.begins_with("res://")) { + print_line("Skipping export of out-of-project library " + library_path); + continue; + } + add_shared_object(library_path, tags); + + if (p_features.has("iOS") && (library_path.ends_with(".a") || library_path.ends_with(".xcframework"))) { + String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n" + "extern void add_ios_init_callback(void (*cb)());\n" + "\n" + "extern \"C\" void $ENTRY();\n" + "void $ENTRY_init() {\n" + " if (&$ENTRY) register_dynamic_symbol((char *)\"$ENTRY\", (void *)$ENTRY);\n" + "}\n" + "struct $ENTRY_struct {\n" + " $ENTRY_struct() {\n" + " add_ios_init_callback($ENTRY_init);\n" + " }\n" + "};\n" + "$ENTRY_struct $ENTRY_struct_instance;\n\n"; + additional_code = additional_code.replace("$ENTRY", entry_symbol); + add_ios_cpp_code(additional_code); + + String linker_flags = "-Wl,-U,_" + entry_symbol; + add_ios_linker_flags(linker_flags); + } + break; + } + } + + List<String> dependencies; + + config->get_section_keys("dependencies", &dependencies); + for (const String &E : libraries) { + Vector<String> tags = E.split("."); + bool all_tags_met = true; + for (int i = 0; i < tags.size(); i++) { + String tag = tags[i].strip_edges(); + if (!p_features.has(tag)) { + all_tags_met = false; + break; + } + } + + if (all_tags_met) { + Dictionary dependency = config->get_value("dependencies", E); + for (const Variant *key = dependency.next(nullptr); key; key = dependency.next(key)) { + String library_path = *key; + String target_path = dependency[*key]; + if (!library_path.begins_with("res://")) { + print_line("Skipping export of out-of-project library " + library_path); + continue; + } + add_shared_object(library_path, tags, target_path); + } + break; + } + } +} + +#endif // GDEXTENSION_EXPORT_PLUGIN_H diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 64540ac157..8f285cb7f9 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -447,16 +447,16 @@ MeshInstance3DEditor::MeshInstance3DEditor() { options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("MeshInstance3D"), SNAME("EditorIcons"))); options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); - options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a StaticBody3D and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection.")); + options->get_popup()->set_item_tooltip(-1, TTR("Creates a StaticBody3D and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection.")); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE); - options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection.")); + options->get_popup()->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection.")); options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE); - options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection.")); + options->get_popup()->set_item_tooltip(-1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection.")); options->get_popup()->add_item(TTR("Create Simplified Convex Collision Sibling"), MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE); - options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy.")); + options->get_popup()->set_item_tooltip(-1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy.")); options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES); - options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision.")); + options->get_popup()->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision.")); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH); options->get_popup()->add_separator(); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 8aa8ba1f00..51e2f6ff00 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -3177,13 +3177,8 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { continue; } - Vector2 dir; - dir[j] = 1.0; - Vector2 ta, tb; int j_n1 = (j + 1) % 3; int j_n2 = (j + 2) % 3; - ta[j_n1] = 1.0; - tb[j_n2] = 1.0; for (int k = 0; k < 4; k++) { Vector3 from = aabb.position, to = aabb.position; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 3927aaa438..39e2e0bc9b 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -56,31 +56,31 @@ #include "scene/resources/packed_scene.h" #include "scene/resources/surface_tool.h" -#define DISTANCE_DEFAULT 4 +constexpr real_t DISTANCE_DEFAULT = 4; -#define GIZMO_ARROW_SIZE 0.35 -#define GIZMO_RING_HALF_WIDTH 0.1 -#define GIZMO_PLANE_SIZE 0.2 -#define GIZMO_PLANE_DST 0.3 -#define GIZMO_CIRCLE_SIZE 1.1 -#define GIZMO_SCALE_OFFSET (GIZMO_CIRCLE_SIZE + 0.3) -#define GIZMO_ARROW_OFFSET (GIZMO_CIRCLE_SIZE + 0.3) +constexpr real_t GIZMO_ARROW_SIZE = 0.35; +constexpr real_t GIZMO_RING_HALF_WIDTH = 0.1; +constexpr real_t GIZMO_PLANE_SIZE = 0.2; +constexpr real_t GIZMO_PLANE_DST = 0.3; +constexpr real_t GIZMO_CIRCLE_SIZE = 1.1; +constexpr real_t GIZMO_SCALE_OFFSET = GIZMO_CIRCLE_SIZE + 0.3; +constexpr real_t GIZMO_ARROW_OFFSET = GIZMO_CIRCLE_SIZE + 0.3; -#define ZOOM_FREELOOK_MIN 0.01 -#define ZOOM_FREELOOK_MULTIPLIER 1.08 -#define ZOOM_FREELOOK_INDICATOR_DELAY_S 1.5 +constexpr real_t ZOOM_FREELOOK_MIN = 0.01; +constexpr real_t ZOOM_FREELOOK_MULTIPLIER = 1.08; +constexpr real_t ZOOM_FREELOOK_INDICATOR_DELAY_S = 1.5; #ifdef REAL_T_IS_DOUBLE -#define ZOOM_FREELOOK_MAX 1'000'000'000'000 +constexpr double ZOOM_FREELOOK_MAX = 1'000'000'000'000; #else -#define ZOOM_FREELOOK_MAX 10'000 +constexpr float ZOOM_FREELOOK_MAX = 10'000; #endif -#define MIN_Z 0.01 -#define MAX_Z 1000000.0 +constexpr real_t MIN_Z = 0.01; +constexpr real_t MAX_Z = 1000000.0; -#define MIN_FOV 0.01 -#define MAX_FOV 179 +constexpr real_t MIN_FOV = 0.01; +constexpr real_t MAX_FOV = 179; void ViewportRotationControl::_notification(int p_what) { switch (p_what) { @@ -145,7 +145,7 @@ void ViewportRotationControl::_draw_axis(const Axis2D &p_axis) { // Draw the axis letter for the positive axes. const String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z"); - draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha)); + draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(Math::round(-4.0 * EDSCALE), Math::round(5.0 * EDSCALE)), axis_name, "", get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha)); } else { // Draw an outline around the negative axes. draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c); @@ -2690,27 +2690,27 @@ void Node3DEditorViewport::_notification(int p_what) { } } -static void draw_indicator_bar(Control &surface, real_t fill, const Ref<Texture2D> icon, const Ref<Font> font, int font_size, const String &text) { +static void draw_indicator_bar(Control &p_surface, real_t p_fill, const Ref<Texture2D> p_icon, const Ref<Font> p_font, int p_font_size, const String &p_text, const Color &p_color) { // Adjust bar size from control height - const Vector2 surface_size = surface.get_size(); + const Vector2 surface_size = p_surface.get_size(); const real_t h = surface_size.y / 2.0; const real_t y = (surface_size.y - h) / 2.0; const Rect2 r(10 * EDSCALE, y, 6 * EDSCALE, h); - const real_t sy = r.size.y * fill; + const real_t sy = r.size.y * p_fill; // Note: because this bar appears over the viewport, it has to stay readable for any background color // Draw both neutral dark and bright colors to account this - surface.draw_rect(r, Color(1, 1, 1, 0.2)); - surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6)); - surface.draw_rect(r.grow(1), Color(0, 0, 0, 0.7), false, Math::round(EDSCALE)); + p_surface.draw_rect(r, p_color * Color(1, 1, 1, 0.2)); + p_surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), p_color * Color(1, 1, 1, 0.6)); + p_surface.draw_rect(r.grow(1), Color(0, 0, 0, 0.7), false, Math::round(EDSCALE)); - const Vector2 icon_size = icon->get_size(); + const Vector2 icon_size = p_icon->get_size(); const Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2 * EDSCALE); - surface.draw_texture(icon, icon_pos); + p_surface.draw_texture(p_icon, icon_pos, p_color); // Draw text below the bar (for speed/zoom information). - surface.draw_string(font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, font_size); + p_surface.draw_string(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, p_color, Math::round(2 * EDSCALE), Color(0, 0, 0)); } void Node3DEditorViewport::_draw() { @@ -2828,7 +2828,8 @@ void Node3DEditorViewport::_draw() { get_theme_icon(SNAME("ViewportSpeed"), SNAME("EditorIcons")), get_theme_font(SNAME("font"), SNAME("Label")), get_theme_font_size(SNAME("font_size"), SNAME("Label")), - vformat("%s u/s", String::num(freelook_speed).pad_decimals(precision))); + vformat("%s u/s", String::num(freelook_speed).pad_decimals(precision)), + Color(1.0, 0.95, 0.7)); } } else { @@ -2850,7 +2851,8 @@ void Node3DEditorViewport::_draw() { get_theme_icon(SNAME("ViewportZoom"), SNAME("EditorIcons")), get_theme_font(SNAME("font"), SNAME("Label")), get_theme_font_size(SNAME("font_size"), SNAME("Label")), - vformat("%s u", String::num(cursor.distance).pad_decimals(precision))); + vformat("%s u", String::num(cursor.distance).pad_decimals(precision)), + Color(0.7, 0.95, 1.0)); } } } diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index b7aef7f1bb..eafc53c72b 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -39,7 +39,8 @@ void ResourcePreloaderEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { load->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } break; } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index d506a1f3ab..2da5978fab 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1881,7 +1881,7 @@ void ScriptEditor::_update_members_overview() { String name = functions[i].get_slice(":", 0); if (filter.is_empty() || filter.is_subsequence_ofn(name)) { members_overview->add_item(name); - members_overview->set_item_metadata(members_overview->get_item_count() - 1, functions[i].get_slice(":", 1).to_int() - 1); + members_overview->set_item_metadata(-1, functions[i].get_slice(":", 1).to_int() - 1); } } @@ -2139,7 +2139,7 @@ void ScriptEditor::_update_script_names() { for (int i = 0; i < sedata_filtered.size(); i++) { script_list->add_item(sedata_filtered[i].name, sedata_filtered[i].icon); if (sedata_filtered[i].tool) { - script_list->set_item_icon_modulate(script_list->get_item_count() - 1, tool_color); + script_list->set_item_icon_modulate(-1, tool_color); } int index = script_list->get_item_count() - 1; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 10b6129864..30ca1c605f 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -579,7 +579,7 @@ void ScriptTextEditor::_update_bookmark_list() { } bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - `" + line + "`"); - bookmarks_menu->set_item_metadata(bookmarks_menu->get_item_count() - 1, bookmark_list[i]); + bookmarks_menu->set_item_metadata(-1, bookmark_list[i]); } } @@ -731,7 +731,7 @@ void ScriptTextEditor::_update_breakpoint_list() { } breakpoints_menu->add_item(String::num((int)breakpoint_list[i] + 1) + " - `" + line + "`"); - breakpoints_menu->set_item_metadata(breakpoints_menu->get_item_count() - 1, breakpoint_list[i]); + breakpoints_menu->set_item_metadata(-1, breakpoint_list[i]); } } diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 382138a995..dbe6ca192c 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -435,8 +435,16 @@ void ShaderEditor::_menu_option(int p_option) { } void ShaderEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { - _check_for_external_edit(); + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + PopupMenu *popup = help_menu->get_popup(); + popup->set_item_icon(popup->get_item_index(HELP_DOCS), get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); + } break; + + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { + _check_for_external_edit(); + } break; } } @@ -647,7 +655,7 @@ void ShaderEditor::_update_bookmark_list() { } bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - \"" + line + "\""); - bookmarks_menu->set_item_metadata(bookmarks_menu->get_item_count() - 1, bookmark_list[i]); + bookmarks_menu->set_item_metadata(-1, bookmark_list[i]); } } @@ -772,7 +780,7 @@ ShaderEditor::ShaderEditor() { help_menu = memnew(MenuButton); help_menu->set_text(TTR("Help")); help_menu->set_switch_on_hover(true); - help_menu->get_popup()->add_icon_item(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Online Docs"), HELP_DOCS); + help_menu->get_popup()->add_item(TTR("Online Docs"), HELP_DOCS); help_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditor::_menu_option)); add_child(main_container); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index c8db16d3be..87b5b829e0 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -204,15 +204,22 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) { // to allow performing this action anywhere, even if the cursor isn't // hovering the texture in the workspace. if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) { - _sheet_zoom_in(); + _sheet_zoom_on_position(scale_ratio, mb->get_position()); // Don't scroll up after zooming in. - accept_event(); + split_sheet_scroll->accept_event(); } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) { - _sheet_zoom_out(); + _sheet_zoom_on_position(1 / scale_ratio, mb->get_position()); // Don't scroll down after zooming out. - accept_event(); + split_sheet_scroll->accept_event(); } } + + const Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { + const Vector2 dragged = Input::get_singleton()->warp_mouse_motion(mm, split_sheet_scroll->get_global_rect()); + split_sheet_scroll->set_h_scroll(split_sheet_scroll->get_h_scroll() - dragged.x); + split_sheet_scroll->set_v_scroll(split_sheet_scroll->get_v_scroll() - dragged.y); + } } void SpriteFramesEditor::_sheet_add_frames() { @@ -243,20 +250,25 @@ void SpriteFramesEditor::_sheet_add_frames() { undo_redo->commit_action(); } +void SpriteFramesEditor::_sheet_zoom_on_position(float p_zoom, const Vector2 &p_position) { + const float old_zoom = sheet_zoom; + sheet_zoom = CLAMP(sheet_zoom * p_zoom, min_sheet_zoom, max_sheet_zoom); + + const Size2 texture_size = split_sheet_preview->get_texture()->get_size(); + split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom); + + Vector2 offset = Vector2(split_sheet_scroll->get_h_scroll(), split_sheet_scroll->get_v_scroll()); + offset = (offset + p_position) / old_zoom * sheet_zoom - p_position; + split_sheet_scroll->set_h_scroll(offset.x); + split_sheet_scroll->set_v_scroll(offset.y); +} + void SpriteFramesEditor::_sheet_zoom_in() { - if (sheet_zoom < max_sheet_zoom) { - sheet_zoom *= scale_ratio; - Size2 texture_size = split_sheet_preview->get_texture()->get_size(); - split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom); - } + _sheet_zoom_on_position(scale_ratio, Vector2()); } void SpriteFramesEditor::_sheet_zoom_out() { - if (sheet_zoom > min_sheet_zoom) { - sheet_zoom /= scale_ratio; - Size2 texture_size = split_sheet_preview->get_texture()->get_size(); - split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom); - } + _sheet_zoom_on_position(1 / scale_ratio, Vector2()); } void SpriteFramesEditor::_sheet_zoom_reset() { @@ -310,7 +322,8 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) { void SpriteFramesEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { load->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons"))); load_sheet->set_icon(get_theme_icon(SNAME("SpriteSheet"), SNAME("EditorIcons"))); copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"))); @@ -328,11 +341,9 @@ void SpriteFramesEditor::_notification(int p_what) { split_sheet_zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons"))); split_sheet_zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons"))); split_sheet_zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons"))); - [[fallthrough]]; - } - case NOTIFICATION_THEME_CHANGED: { split_sheet_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); } break; + case NOTIFICATION_READY: { add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up. } break; @@ -847,7 +858,7 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) { at = at->get_atlas(); } - tree->set_item_tooltip(tree->get_item_count() - 1, tooltip); + tree->set_item_tooltip(-1, tooltip); } if (sel == i) { tree->select(tree->get_item_count() - 1); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 461c8dd41a..872a88e262 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -143,6 +143,7 @@ class SpriteFramesEditor : public HSplitContainer { void _sheet_preview_input(const Ref<InputEvent> &p_event); void _sheet_scroll_input(const Ref<InputEvent> &p_event); void _sheet_add_frames(); + void _sheet_zoom_on_position(float p_zoom, const Vector2 &p_position); void _sheet_zoom_in(); void _sheet_zoom_out(); void _sheet_zoom_reset(); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 940f269803..34f3ec73c0 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -179,7 +179,7 @@ void TextEditor::_update_bookmark_list() { } bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - \"" + line + "\""); - bookmarks_menu->set_item_metadata(bookmarks_menu->get_item_count() - 1, bookmark_list[i]); + bookmarks_menu->set_item_metadata(-1, bookmark_list[i]); } } diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp index 0f8c8c616c..086588f5a5 100644 --- a/editor/plugins/tiles/atlas_merging_dialog.cpp +++ b/editor/plugins/tiles/atlas_merging_dialog.cpp @@ -241,7 +241,7 @@ void AtlasMergingDialog::update_tile_set(Ref<TileSet> p_tile_set) { if (texture.is_valid()) { String item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id); atlas_merging_atlases_list->add_item(item_text, texture); - atlas_merging_atlases_list->set_item_metadata(atlas_merging_atlases_list->get_item_count() - 1, source_id); + atlas_merging_atlases_list->set_item_metadata(-1, source_id); } } } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 4a0fc0b29f..8d8c65f2c4 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -188,7 +188,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { } sources_list->add_item(item_text, texture); - sources_list->set_item_metadata(sources_list->get_item_count() - 1, source_id); + sources_list->set_item_metadata(-1, source_id); } if (sources_list->get_item_count() > 0) { diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index 49e589c9ef..8b0b184f54 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -182,7 +182,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) { } sources_list->add_item(item_text, texture); - sources_list->set_item_metadata(sources_list->get_item_count() - 1, source_id); + sources_list->set_item_metadata(-1, source_id); } // Set again the current selected item if needed. diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 17db955cc7..9963ac0232 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -1128,9 +1128,6 @@ ProjectExportDialog::ProjectExportDialog() { // Script export parameters. - updating_script_key = false; - updating_enc_filters = false; - VBoxContainer *sec_vb = memnew(VBoxContainer); sec_vb->set_name(TTR("Encryption")); @@ -1153,7 +1150,7 @@ ProjectExportDialog::ProjectExportDialog() { enc_ex_filters = memnew(LineEdit); enc_ex_filters->connect("text_changed", callable_mp(this, &ProjectExportDialog::_enc_filters_changed)); sec_vb->add_margin_child( - TTR("Filters to exclude files/folders\n(comma-separated, e.g: *.stex, *.import, music/*)"), + TTR("Filters to exclude files/folders\n(comma-separated, e.g: *.ctex, *.import, music/*)"), enc_ex_filters); script_key = memnew(LineEdit); @@ -1195,8 +1192,6 @@ ProjectExportDialog::ProjectExportDialog() { // Export buttons, dialogs and errors. - updating = false; - get_cancel_button()->set_text(TTR("Close")); get_ok_button()->set_text(TTR("Export PCK/ZIP...")); export_button = add_button(TTR("Export Project..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export"); diff --git a/editor/project_export.h b/editor/project_export.h index 569563ba55..057fd31168 100644 --- a/editor/project_export.h +++ b/editor/project_export.h @@ -71,7 +71,7 @@ private: CheckButton *runnable; Button *button_export; - bool updating; + bool updating = false; AcceptDialog *error_dialog; ConfirmationDialog *delete_confirm; @@ -152,8 +152,8 @@ private: void _update_feature_list(); void _custom_features_changed(const String &p_text); - bool updating_script_key; - bool updating_enc_filters; + bool updating_script_key = false; + bool updating_enc_filters = false; void _enc_pck_changed(bool p_pressed); void _enc_directory_changed(bool p_pressed); void _enc_filters_changed(const String &p_text); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 78f6fe58d0..d32f935b54 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -147,7 +147,7 @@ private: } String _test_path() { - DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String valid_path, valid_install_path; if (d->change_dir(project_path->get_text()) == OK) { valid_path = project_path->get_text(); @@ -165,7 +165,6 @@ private: if (valid_path.is_empty()) { set_message(TTR("The path specified doesn't exist."), MESSAGE_ERROR); - memdelete(d); get_ok_button()->set_disabled(true); return ""; } @@ -179,7 +178,6 @@ private: if (valid_install_path.is_empty()) { set_message(TTR("The path specified doesn't exist."), MESSAGE_ERROR, INSTALL_PATH); - memdelete(d); get_ok_button()->set_disabled(true); return ""; } @@ -194,7 +192,6 @@ private: unzFile pkg = unzOpen2(valid_path.utf8().get_data(), &io); if (!pkg) { set_message(TTR("Error opening package file (it's not in ZIP format)."), MESSAGE_ERROR); - memdelete(d); get_ok_button()->set_disabled(true); unzClose(pkg); return ""; @@ -215,7 +212,6 @@ private: if (ret == UNZ_END_OF_LIST_OF_FILE) { set_message(TTR("Invalid \".zip\" project file; it doesn't contain a \"project.godot\" file."), MESSAGE_ERROR); - memdelete(d); get_ok_button()->set_disabled(true); unzClose(pkg); return ""; @@ -242,14 +238,12 @@ private: if (!is_folder_empty) { set_message(TTR("Please choose an empty folder."), MESSAGE_WARNING, INSTALL_PATH); - memdelete(d); get_ok_button()->set_disabled(true); return ""; } } else { set_message(TTR("Please choose a \"project.godot\" or \".zip\" file."), MESSAGE_ERROR); - memdelete(d); install_path_container->hide(); get_ok_button()->set_disabled(true); return ""; @@ -257,7 +251,6 @@ private: } else if (valid_path.ends_with("zip")) { set_message(TTR("This directory already contains a Godot project."), MESSAGE_ERROR, INSTALL_PATH); - memdelete(d); get_ok_button()->set_disabled(true); return ""; } @@ -282,7 +275,6 @@ private: if (!is_folder_empty) { set_message(TTR("The selected path is not empty. Choosing an empty folder is highly recommended."), MESSAGE_WARNING); - memdelete(d); get_ok_button()->set_disabled(false); return valid_path; } @@ -290,7 +282,6 @@ private: set_message(""); set_message("", MESSAGE_SUCCESS, INSTALL_PATH); - memdelete(d); get_ok_button()->set_disabled(false); return valid_path; } @@ -389,7 +380,7 @@ private: return; } - DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (d->change_dir(project_path->get_text()) == OK) { if (!d->dir_exists(project_name_no_edges)) { if (d->make_dir(project_name_no_edges) == OK) { @@ -408,8 +399,6 @@ private: dialog_error->popup_centered(); } } - - memdelete(d); } void _text_changed(const String &p_text) { @@ -551,14 +540,11 @@ private: if (path.is_empty() || path == zip_root || !zip_root.is_subsequence_of(path)) { // } else if (path.ends_with("/")) { // a dir - path = path.substr(0, path.length() - 1); String rel_path = path.substr(zip_root.length()); - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); da->make_dir(dir.plus_file(rel_path)); - memdelete(da); - } else { Vector<uint8_t> data; data.resize(info.uncompressed_size); @@ -620,9 +606,8 @@ private: void _remove_created_folder() { if (!created_folder_path.is_empty()) { - DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); d->remove(created_folder_path); - memdelete(d); create_dir->set_disabled(false); created_folder_path = ""; @@ -725,10 +710,9 @@ public: project_path->set_text(fav_dir); fdialog->set_current_dir(fav_dir); } else { - DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); project_path->set_text(d->get_current_dir()); fdialog->set_current_dir(d->get_current_dir()); - memdelete(d); } String proj = TTR("New Game Project"); project_name->set_text(proj); @@ -1911,6 +1895,11 @@ void ProjectManager::_notification(int p_what) { // to search without having to reach for their mouse search_box->grab_focus(); } + + if (asset_library) { + // Removes extra border margins. + asset_library->add_theme_style_override("panel", memnew(StyleBoxEmpty)); + } } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -2411,12 +2400,11 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) { return; } Set<String> folders_set; - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < p_files.size(); i++) { String file = p_files[i]; folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir()); } - memdelete(da); if (folders_set.size() > 0) { PackedStringArray folders; for (Set<String>::Element *E = folders_set.front(); E; E = E->next()) { @@ -2425,7 +2413,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) { bool confirm = true; if (folders.size() == 1) { - DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (dir->change_dir(folders[0]) == OK) { dir->list_dir_begin(); String file = dir->get_next(); @@ -2437,7 +2425,6 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) { } dir->list_dir_end(); } - memdelete(dir); } if (confirm) { multi_scan_ask->get_ok_button()->disconnect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders)); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index dd4b963fc0..52fb0d4f4e 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -1771,9 +1771,6 @@ void CustomPropertyEditor::_bind_methods() { } CustomPropertyEditor::CustomPropertyEditor() { - read_only = false; - updating = false; - value_vbox = memnew(VBoxContainer); add_child(value_vbox); diff --git a/editor/property_editor.h b/editor/property_editor.h index c4287dc115..73306e0bc2 100644 --- a/editor/property_editor.h +++ b/editor/property_editor.h @@ -119,7 +119,7 @@ class CustomPropertyEditor : public PopupPanel { TextureRect *texture_preview; ColorPicker *color_picker; TextEdit *text_edit; - bool read_only; + bool read_only = false; bool picking_viewport; GridContainer *checks20gc; CheckBox *checks20[20]; @@ -132,7 +132,7 @@ class CustomPropertyEditor : public PopupPanel { Object *owner; - bool updating; + bool updating = false; PropertyValueEvaluator *evaluator; diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index 453ecb6b24..1ac15a0a9d 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -589,7 +589,6 @@ PropertySelector::PropertySelector() { search_options->connect("cell_selected", callable_mp(this, &PropertySelector::_item_selected)); search_options->set_hide_root(true); search_options->set_hide_folding(true); - virtuals_only = false; help_bit = memnew(EditorHelpBit); vbc->add_margin_child(TTR("Description:"), help_bit); diff --git a/editor/property_selector.h b/editor/property_selector.h index 1e8c6300a0..7e629a847e 100644 --- a/editor/property_selector.h +++ b/editor/property_selector.h @@ -56,7 +56,7 @@ class PropertySelector : public ConfirmationDialog { String base_type; ObjectID script; Object *instance; - bool virtuals_only; + bool virtuals_only = false; Vector<Variant::Type> type_filter; diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index 4e64aba1db..53da945868 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -245,8 +245,6 @@ void EditorQuickOpen::_bind_methods() { } EditorQuickOpen::EditorQuickOpen() { - allow_multi_select = false; - VBoxContainer *vbc = memnew(VBoxContainer); vbc->connect("theme_changed", callable_mp(this, &EditorQuickOpen::_theme_changed)); add_child(vbc); diff --git a/editor/quick_open.h b/editor/quick_open.h index dc485a7c86..f50f09604c 100644 --- a/editor/quick_open.h +++ b/editor/quick_open.h @@ -42,7 +42,7 @@ class EditorQuickOpen : public ConfirmationDialog { LineEdit *search_box; Tree *search_options; StringName base_type; - bool allow_multi_select; + bool allow_multi_select = false; Vector<String> files; OAHashMap<String, Ref<Texture2D>> icons; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 571b87a0aa..8d7916685a 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2551,7 +2551,7 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_ menu_properties->clear(); for (const String &p : valid_properties) { menu_properties->add_item(capitalize ? p.capitalize() : p); - menu_properties->set_item_metadata(menu_properties->get_item_count() - 1, p); + menu_properties->set_item_metadata(-1, p); } menu_properties->reset_size(); @@ -3497,8 +3497,6 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec menu_subresources->set_name("Sub-Resources"); menu_subresources->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false)); menu->add_child(menu_subresources); - first_enter = true; - restore_script_editor_on_drag = false; menu_properties = memnew(PopupMenu); add_child(menu_properties); @@ -3512,9 +3510,6 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec set_process_input(true); set_process(true); - profile_allow_editing = true; - profile_allow_script_editing = true; - EDITOR_DEF("interface/editors/show_scene_tree_root_selection", true); EDITOR_DEF("interface/editors/derive_script_globals_by_name", true); EDITOR_DEF("_use_favorites_root_selection", false); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 2a98c469dc..938f83725d 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -105,7 +105,7 @@ class SceneTreeDock : public VBoxContainer { Vector<ObjectID> subresources; - bool restore_script_editor_on_drag; + bool restore_script_editor_on_drag = false; bool reset_create_dialog = false; int current_option; @@ -166,7 +166,7 @@ class SceneTreeDock : public VBoxContainer { PopupMenu *menu_properties; ConfirmationDialog *clear_inherit_confirm; - bool first_enter; + bool first_enter = true; void _create(); void _do_create(Node *p_parent); @@ -261,8 +261,8 @@ class SceneTreeDock : public VBoxContainer { void _create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap); void _create_remap_for_resource(RES p_resource, Map<RES, RES> &r_remap); - bool profile_allow_editing; - bool profile_allow_script_editing; + bool profile_allow_editing = true; + bool profile_allow_script_editing = true; static void _update_configuration_warning(); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index c6a8a928db..3b8c540592 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -1197,17 +1197,11 @@ void SceneTreeEditor::_bind_methods() { } SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_open_instance) { - connect_to_script_mode = false; - connecting_signal = false; undo_redo = nullptr; - tree_dirty = true; selected = nullptr; - marked_selectable = false; - marked_children_selectable = false; can_rename = p_can_rename; can_open_instance = p_can_open_instance; - display_foreign = false; editor_selection = nullptr; if (p_label) { @@ -1249,11 +1243,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope add_child(warning); warning->set_title(TTR("Node Configuration Warning!")); - show_enabled_subscene = false; - last_hash = 0; - pending_test_update = false; - updating_tree = false; blocked = 0; update_timer = memnew(Timer); diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index f700182681..2466b8576a 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -65,8 +65,8 @@ class SceneTreeEditor : public Control { AcceptDialog *warning; bool auto_expand_selected = true; - bool connect_to_script_mode; - bool connecting_signal; + bool connect_to_script_mode = false; + bool connecting_signal = false; int blocked; @@ -92,18 +92,18 @@ class SceneTreeEditor : public Control { bool can_rename; bool can_open_instance; - bool updating_tree; - bool show_enabled_subscene; + bool updating_tree = false; + bool show_enabled_subscene = false; void _renamed(); UndoRedo *undo_redo; Set<Node *> marked; - bool marked_selectable; - bool marked_children_selectable; - bool display_foreign; - bool tree_dirty; - bool pending_test_update; + bool marked_selectable = false; + bool marked_children_selectable = false; + bool display_foreign = false; + bool tree_dirty = true; + bool pending_test_update = false; static void _bind_methods(); void _cell_button_pressed(Object *p_item, int p_column, int p_id); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index bf43e11cdb..baafef8639 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -247,23 +247,22 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must return TTR("Path is not local."); } - DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); - if (d->change_dir(p.get_base_dir()) != OK) { - memdelete(d); - return TTR("Base path is invalid."); + { + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (da->change_dir(p.get_base_dir()) != OK) { + return TTR("Base path is invalid."); + } } - memdelete(d); - // Check if file exists. - DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES); - if (f->dir_exists(p)) { - memdelete(f); - return TTR("A directory with the same name exists."); - } else if (p_file_must_exist && !f->file_exists(p)) { - memdelete(f); - return TTR("File does not exist."); + { + // Check if file exists. + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (da->dir_exists(p)) { + return TTR("A directory with the same name exists."); + } else if (p_file_must_exist && !da->file_exists(p)) { + return TTR("File does not exist."); + } } - memdelete(f); // Check file extension. String extension = p.get_extension(); @@ -556,13 +555,12 @@ void ScriptCreateDialog::_path_changed(const String &p_path) { } // Check if file exists. - DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges()); - if (f->file_exists(p)) { + if (da->file_exists(p)) { is_new_script_created = false; _msg_path_valid(true, TTR("File exists, it will be reused.")); } - memdelete(f); is_path_valid = true; _update_dialog(); @@ -643,7 +641,7 @@ void ScriptCreateDialog::_update_template_menu() { if (!templates_found.is_empty()) { if (!separator) { template_menu->add_separator(); - template_menu->set_item_text(template_menu->get_item_count() - 1, display_name); + template_menu->set_item_text(-1, display_name); separator = true; } for (ScriptLanguage::ScriptTemplate &t : templates_found) { @@ -838,7 +836,7 @@ Vector<ScriptLanguage::ScriptTemplate> ScriptCreateDialog::_get_user_templates(c String dir_path = p_dir.plus_file(p_object); - DirAccess *d = DirAccess::open(dir_path); + DirAccessRef d = DirAccess::open(dir_path); if (d) { d->list_dir_begin(); String file = d->get_next(); @@ -849,7 +847,6 @@ Vector<ScriptLanguage::ScriptTemplate> ScriptCreateDialog::_get_user_templates(c file = d->get_next(); } d->list_dir_end(); - memdelete(d); } return user_templates; } @@ -1029,7 +1026,6 @@ ScriptCreateDialog::ScriptCreateDialog() { hb->add_child(parent_browse_button); gc->add_child(memnew(Label(TTR("Inherits:")))); gc->add_child(hb); - is_browsing_parent = false; /* Class Name */ @@ -1040,8 +1036,6 @@ ScriptCreateDialog::ScriptCreateDialog() { gc->add_child(class_name); /* Templates */ - - is_using_templates = true; gc->add_child(memnew(Label(TTR("Template:")))); HBoxContainer *template_hb = memnew(HBoxContainer); template_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -1082,7 +1076,6 @@ ScriptCreateDialog::ScriptCreateDialog() { Label *label = memnew(Label(TTR("Path:"))); gc->add_child(label); gc->add_child(hb); - re_check_path = false; path_controls[0] = label; path_controls[1] = hb; @@ -1119,17 +1112,4 @@ ScriptCreateDialog::ScriptCreateDialog() { set_hide_on_ok(false); set_title(TTR("Attach Node Script")); - - is_parent_name_valid = false; - is_class_name_valid = false; - is_path_valid = false; - - has_named_classes = false; - supports_built_in = false; - can_inherit_from_file = false; - is_built_in = false; - built_in_enabled = true; - load_enabled = true; - - is_new_script_created = true; } diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h index 5c0f51812f..d7c43f322c 100644 --- a/editor/script_create_dialog.h +++ b/editor/script_create_dialog.h @@ -66,25 +66,23 @@ class ScriptCreateDialog : public ConfirmationDialog { VBoxContainer *path_vb; AcceptDialog *alert; CreateDialog *select_class; - bool path_valid; - bool create_new; - bool is_browsing_parent; + bool is_browsing_parent = false; String template_inactive_message; String initial_bp; - bool is_new_script_created; - bool is_path_valid; - bool has_named_classes; - bool supports_built_in; - bool can_inherit_from_file; - bool is_parent_name_valid; - bool is_class_name_valid; - bool is_built_in; - bool is_using_templates; - bool built_in_enabled; - bool load_enabled; + bool is_new_script_created = true; + bool is_path_valid = false; + bool has_named_classes = false; + bool supports_built_in = false; + bool can_inherit_from_file = false; + bool is_parent_name_valid = false; + bool is_class_name_valid = false; + bool is_built_in = false; + bool is_using_templates = true; + bool built_in_enabled = true; + bool load_enabled = true; int current_language; int default_language; - bool re_check_path; + bool re_check_path = false; Control *path_controls[2]; Control *name_controls[2]; diff --git a/main/main.cpp b/main/main.cpp index 97794ece1a..f0e74c3bb7 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -273,7 +273,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" -h, --help Display this help message.\n"); OS::get_singleton()->print(" --version Display the version string.\n"); OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n"); - OS::get_singleton()->print(" --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n"); + OS::get_singleton()->print(" -q, --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n"); OS::get_singleton()->print("\n"); OS::get_singleton()->print("Run options:\n"); @@ -282,7 +282,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n"); OS::get_singleton()->print(" --debug-server <uri> Start the editor debug server (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007)\n"); #endif - OS::get_singleton()->print(" -q, --quit Quit after the first iteration.\n"); + OS::get_singleton()->print(" --quit Quit after the first iteration.\n"); OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n"); OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n"); OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n"); @@ -319,9 +319,8 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n"); OS::get_singleton()->print(" --gpu-index <device_index> Use a specific GPU (run with --verbose to get available device list).\n"); - OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping)\n"); - + OS::get_singleton()->print(" --tablet-driver <driver> Pen tablet input driver.\n"); OS::get_singleton()->print(" --headless Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script.\n"); OS::get_singleton()->print("\n"); @@ -334,21 +333,22 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n"); OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n"); OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n"); - OS::get_singleton()->print(" --tablet-driver Pen tablet input driver.\n"); OS::get_singleton()->print("\n"); OS::get_singleton()->print("Debug options:\n"); OS::get_singleton()->print(" -d, --debug Debug (local stdout debugger).\n"); OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n"); OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n"); - OS::get_singleton()->print(" --vk-layers Enable Vulkan Validation layers for debugging.\n"); -#ifdef DEBUG_ENABLED + OS::get_singleton()->print(" --gpu-profile Show a GPU profile of the tasks that took the most time during frame rendering.\n"); + OS::get_singleton()->print(" --vk-layers Enable Vulkan validation layers for debugging.\n"); +#if DEBUG_ENABLED OS::get_singleton()->print(" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n"); #endif OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n"); #if defined(DEBUG_ENABLED) OS::get_singleton()->print(" --debug-collisions Show collision shapes when running the scene.\n"); OS::get_singleton()->print(" --debug-navigation Show navigation polygons when running the scene.\n"); + OS::get_singleton()->print(" --debug-stringnames Print all StringName allocations to stdout when the engine quits.\n"); #endif OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n"); OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n"); @@ -356,7 +356,6 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n"); OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n"); OS::get_singleton()->print(" --print-fps Print the frames per second to the stdout.\n"); - OS::get_singleton()->print(" --profile-gpu Show a simple profile of the tasks that took more time during frame rendering.\n"); OS::get_singleton()->print("\n"); OS::get_singleton()->print("Standalone tools:\n"); @@ -644,7 +643,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (I->get() == "-v" || I->get() == "--verbose") { // verbose output OS::get_singleton()->_verbose_stdout = true; - } else if (I->get() == "--quiet") { // quieter output + } else if (I->get() == "-q" || I->get() == "--quiet") { // quieter output quiet_stdout = true; @@ -787,7 +786,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph Engine::singleton->gpu_idx = I->next()->get().to_int(); N = I->next()->next(); } else { - OS::get_singleton()->print("Missing gpu index argument, aborting.\n"); + OS::get_singleton()->print("Missing GPU index argument, aborting.\n"); goto error; } } else if (I->get() == "--vk-layers") { @@ -978,7 +977,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } else if (I->get() == "-u" || I->get() == "--upwards") { // scan folders upwards upwards = true; - } else if (I->get() == "-q" || I->get() == "--quit") { // Auto quit at the end of the first main loop iteration + } else if (I->get() == "--quit") { // Auto quit at the end of the first main loop iteration auto_quit = true; } else if (I->get().ends_with("project.godot")) { String path; @@ -2099,9 +2098,8 @@ bool Main::start() { checked_paths.insert(path); // Create the module documentation directory if it doesn't exist - DirAccess *da = DirAccess::create_for_path(path); + DirAccessRef da = DirAccess::create_for_path(path); err = da->make_dir_recursive(path); - memdelete(da); ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create directory: " + path + ": " + itos(err)); print_line("Loading docs from: " + path); @@ -2112,9 +2110,8 @@ bool Main::start() { String index_path = doc_tool_path.plus_file("doc/classes"); // Create the main documentation directory if it doesn't exist - DirAccess *da = DirAccess::create_for_path(index_path); + DirAccessRef da = DirAccess::create_for_path(index_path); err = da->make_dir_recursive(index_path); - memdelete(da); ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create index directory: " + index_path + ": " + itos(err)); print_line("Loading classes from: " + index_path); @@ -2249,7 +2246,7 @@ bool Main::start() { bool embed_subwindows = GLOBAL_DEF("display/window/subwindows/embed_subwindows", true); if (OS::get_singleton()->is_single_window() || (!project_manager && !editor && embed_subwindows)) { - sml->get_root()->set_embed_subwindows_hint(true); + sml->get_root()->set_embedding_subwindows(true); } ResourceLoader::add_custom_loaders(); ResourceSaver::add_custom_savers(); @@ -2431,7 +2428,7 @@ bool Main::start() { "interface/editor/single_window_mode"); if (editor_embed_subwindows) { - sml->get_root()->set_embed_subwindows_hint(true); + sml->get_root()->set_embedding_subwindows(true); } } #endif @@ -2452,15 +2449,13 @@ bool Main::start() { int sep = local_game_path.rfind("/"); if (sep == -1) { - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); local_game_path = da->get_current_dir().plus_file(local_game_path); - memdelete(da); } else { - DirAccess *da = DirAccess::open(local_game_path.substr(0, sep)); + DirAccessRef da = DirAccess::open(local_game_path.substr(0, sep)); if (da) { local_game_path = da->get_current_dir().plus_file( local_game_path.substr(sep + 1, local_game_path.length())); - memdelete(da); } } } diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/osx_template.app/Contents/Info.plist index 43399ec6ce..542146cdb8 100644 --- a/misc/dist/osx_template.app/Contents/Info.plist +++ b/misc/dist/osx_template.app/Contents/Info.plist @@ -10,8 +10,6 @@ <string>$name</string> <key>CFBundleDisplayName</key> <string>$name</string> - <key>CFBundleGetInfoString</key> - <string>$info</string> <key>CFBundleIconFile</key> <string>icon.icns</string> <key>CFBundleIdentifier</key> diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/osx_tools.app/Contents/Info.plist index 221c4b7a81..886df87cc6 100644 --- a/misc/dist/osx_tools.app/Contents/Info.plist +++ b/misc/dist/osx_tools.app/Contents/Info.plist @@ -8,8 +8,6 @@ <string>Godot</string> <key>CFBundleName</key> <string>Godot</string> - <key>CFBundleGetInfoString</key> - <string>(c) 2007-2022 Juan Linietsky, Ariel Manzur & Godot Engine contributors</string> <key>CFBundleIconFile</key> <string>Godot.icns</string> <key>CFBundleIdentifier</key> diff --git a/misc/dist/shell/_godot.zsh-completion b/misc/dist/shell/_godot.zsh-completion index 8548b18cb0..aaa5fe0a06 100644 --- a/misc/dist/shell/_godot.zsh-completion +++ b/misc/dist/shell/_godot.zsh-completion @@ -30,10 +30,11 @@ _arguments \ '(-h --help)'{-h,--help}'[display the full help message]' \ '--version[display the version string]' \ '(-v --verbose)'{-v,--verbose}'[use verbose stdout mode]' \ - '--quiet[quiet mode, silences stdout messages (errors are still displayed)]' \ + '(-q --quiet)'{-q,--quiet}'[quiet mode, silences stdout messages (errors are still displayed)]' \ '(-e --editor)'{-e,--editor}'[start the editor instead of running the scene]' \ '(-p --project-manager)'{-p,--project-manager}'[start the project manager, even if a project is auto-detected]' \ - '(-q --quit)'{-q,--quit}'[quit after the first iteration]' \ + '--debug-server[start the editor debug server]:editor debugger listen address' \ + '--quit[quit after the first iteration]' \ '(-l --language)'{-l,--language}'[use a specific locale (<locale> being a two-letter code)]:two-letter locale code' \ "--path[path to a project (<directory> must contain a 'project.godot' file)]:path to directory with 'project.godot' file:_dirs" \ '(-u --upwards)'{-u,--upwards}'[scan folders upwards for project.godot file]' \ @@ -42,7 +43,12 @@ _arguments \ '--remote-fs[use a remote filesystem]:remote filesystem address' \ '--remote-fs-password[password for remote filesystem]:remote filesystem password' \ '--audio-driver[set the audio driver]:audio driver name' \ - "--video-driver[set the video driver]:video driver name:((Vulkan\:'Vulkan renderer' GLES2\:'OpenGL ES 2.0 renderer'))" \ + '--display-driver[set the display driver]:display driver name' \ + "--rendering-driver[set the rendering driver]:rendering driver name:((vulkan\:'Vulkan renderer' opengl3\:'OpenGL ES 3.0 renderer' dummy\:'Dummy renderer'))" \ + "--gpu-index[use a specific GPU (run with --verbose to get available device list)]:device index" \ + '--text-driver[set the text driver]:text driver name' \ + '--tablet-driver[set the pen tablet input driver]:tablet driver name' \ + '--headless[enable headless mode (--display-driver headless --audio-driver Dummy), useful for servers and with --script]' \ '(-f --fullscreen)'{-f,--fullscreen}'[request fullscreen mode]' \ '(-m --maximized)'{-m,--maximized}'[request a maximized window]' \ '(-w --windowed)'{-w,--windowed}'[request windowed mode]' \ @@ -50,12 +56,17 @@ _arguments \ '--resolution[request window resolution]:resolution in WxH format' \ '--position[request window position]:position in X,Y format' \ '--headless[enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script]' \ + '--single-window[use a single window (no separate subwindows)]' \ '(-d --debug)'{-d,--debug}'[debug (local stdout debugger)]' \ '(-b --breakpoints)'{-b,--breakpoints}'[specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)]:breakpoint list' \ '--profiling[enable profiling in the script debugger]' \ + '--gpu-profile[show a GPU profile of the tasks that took the most time during frame rendering]' \ + '--vk-layers[enable Vulkan validation layers for debugging]' \ + '--gpu-abort[abort on GPU errors (usually validation layer errors)]' \ '--remote-debug[enable remote debugging]:remote debugger address' \ '--debug-collisions[show collision shapes when running the scene]' \ '--debug-navigation[show navigation polygons when running the scene]' \ + '--debug-stringnames[print all StringName allocations to stdout when the engine quits]' \ '--frame-delay[simulate high CPU load (delay each frame by the given number of milliseconds)]:number of milliseconds' \ '--time-scale[force time scale (higher values are faster, 1.0 is normal speed)]:time scale' \ '--disable-render-loop[disable render loop so rendering only occurs when called explicitly from script]' \ @@ -64,10 +75,11 @@ _arguments \ '--print-fps[print the frames per second to the stdout]' \ '(-s, --script)'{-s,--script}'[run a script]:path to script:_files' \ '--check-only[only parse for errors and quit (use with --script)]' \ - '--export[export the project using the given preset and matching release template]:export preset name' \ - '--export-debug[same as --export, but using the debug template]:export preset name' \ - '--export-pack[same as --export, but only export the game pack for the given preset]:export preset name' \ - '--doctool[dump the engine API reference to the given path in XML format, merging if existing files are found]:path to base Godot build directory:_dirs' \ + '--export[export the project using the given preset and matching release template]:export preset name then path' \ + '--export-debug[same as --export, but using the debug template]:export preset name then path' \ + '--export-pack[same as --export, but only export the game pack for the given preset]:export preset name then path' \ + '--doctool[dump the engine API reference to the given path in XML format, merging if existing files are found]:path to base Godot build directory (optional):_dirs' \ '--no-docbase[disallow dumping the base types (used with --doctool)]' \ '--build-solutions[build the scripting solutions (e.g. for C# projects)]' \ - '--test[run a unit test]:unit test name' + '--dump-extension-api[generate JSON dump of the Godot API for GDExtension bindings named "extension_api.json" in the current folder]' \ + '--test[run all unit tests; run with "--test --help" for more information]' diff --git a/misc/dist/shell/godot.bash-completion b/misc/dist/shell/godot.bash-completion index 56bf23a268..7927d26171 100644 --- a/misc/dist/shell/godot.bash-completion +++ b/misc/dist/shell/godot.bash-completion @@ -36,6 +36,7 @@ _complete_godot_options() { --quiet --editor --project-manager +--debug-server --quit --language --path @@ -45,7 +46,12 @@ _complete_godot_options() { --remote-fs --remote-fs-password --audio-driver ---video-driver +--display-driver +--rendering-driver +--gpu-index +--text-driver +--tablet-driver +--headless --fullscreen --maximized --windowed @@ -53,12 +59,17 @@ _complete_godot_options() { --resolution --position --headless +--single-window --debug --breakpoints --profiling +--gpu-profile +--vk-layers +--gpu-abort --remote-debug --debug-collisions --debug-navigation +--debug-stringnames --frame-delay --time-scale --disable-render-loop @@ -73,6 +84,7 @@ _complete_godot_options() { --doctool --no-docbase --build-solutions +--dump-extension-api --test " -- "$1")) } @@ -98,10 +110,10 @@ _complete_godot_bash() { local IFS=$' \n\t' # shellcheck disable=SC2207 COMPREPLY=($(compgen -W "unsafe safe separate" -- "$cur")) - elif [[ $prev == "--video-driver" ]]; then + elif [[ $prev == "--rendering-driver" ]]; then local IFS=$' \n\t' # shellcheck disable=SC2207 - COMPREPLY=($(compgen -W "Vulkan GLES2" -- "$cur")) + COMPREPLY=($(compgen -W "vulkan opengl3 dummy" -- "$cur")) elif [[ $prev == "--path" || $prev == "--doctool" ]]; then local IFS=$'\n\t' # shellcheck disable=SC2207 diff --git a/misc/dist/shell/godot.fish b/misc/dist/shell/godot.fish index 6aa3f38f1f..c05aa74017 100644 --- a/misc/dist/shell/godot.fish +++ b/misc/dist/shell/godot.fish @@ -23,10 +23,11 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -function godot_video_driver_args +function godot_rendering_driver_args # Use a function instead of a fixed string to customize the argument descriptions. - echo -e "Vulkan\tVulkan renderer" - echo -e "GLES2\tOpenGL ES 2.0 renderer" + echo -e "vulkan\tVulkan renderer" + echo -e "opengl3\tOpenGL ES 3.0 renderer" + echo -e "dummy\tDummy renderer" end # Erase existing completions for Godot. @@ -36,12 +37,13 @@ complete -c godot -e complete -c godot -s h -l help -d "Display the full help message" complete -c godot -l version -d "Display the version string" complete -c godot -s v -l verbose -d "Use verbose stdout mode" -complete -c godot -l quiet -d "Quiet mode, silences stdout messages (errors are still displayed)" +complete -c godot -s q -l quiet -d "Quiet mode, silences stdout messages (errors are still displayed)" # Run options: complete -c godot -s e -l editor -d "Start the editor instead of running the scene" complete -c godot -s p -l project-manager -d "Start the project manager, even if a project is auto-detected" -complete -c godot -s q -l quit -d "Quit after the first iteration" +complete -c godot -l debug-server -d "Start the editor debug server (<protocol>://<host/IP>[:<port>] address)" -x +complete -c godot -l quit -d "Quit after the first iteration" complete -c godot -s l -l language -d "Use a specific locale (<locale> being a two-letter code)" -x complete -c godot -l path -d "Path to a project (<directory> must contain a 'project.godot' file)" -r complete -c godot -s u -l upwards -d "Scan folders upwards for project.godot file" @@ -50,7 +52,12 @@ complete -c godot -l render-thread -d "Set the render thread mode" -x -a "unsafe complete -c godot -l remote-fs -d "Use a remote filesystem (<host/IP>[:<port>] address)" -x complete -c godot -l remote-fs-password -d "Password for remote filesystem" -x complete -c godot -l audio-driver -d "Set the audio driver" -x -complete -c godot -l video-driver -d "Set the video driver" -x -a "(godot_video_driver_args)" +complete -c godot -l display-driver -d "Set the display driver" -x +complete -c godot -l rendering-driver -d "Set the rendering driver" -x -a "(godot_rendering_driver_args)" +complete -c godot -l gpu-index -d "Use a specific GPU (run with --verbose to get available device list)" -x +complete -c godot -l text-driver -d "Set the text driver" -x +complete -c godot -l tablet-driver -d "Set the pen tablet input driver" -x +complete -c godot -l headless -d "Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script" # Display options: complete -c godot -s f -l fullscreen -d "Request fullscreen mode" @@ -60,14 +67,19 @@ complete -c godot -s t -l always-on-top -d "Request an always-on-top window" complete -c godot -l resolution -d "Request window resolution" -x complete -c godot -l position -d "Request window position" -x complete -c godot -l headless -d "Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script" +complete -c godot -l single-window -d "Use a single window (no separate subwindows)" # Debug options: complete -c godot -s d -l debug -d "Debug (local stdout debugger)" complete -c godot -s b -l breakpoints -d "Specify the breakpoint list as source::line comma-separated pairs, no spaces (use %20 instead)" -x complete -c godot -l profiling -d "Enable profiling in the script debugger" +complete -c godot -l gpu-profile -d "Show a GPU profile of the tasks that took the most time during frame rendering" +complete -c godot -l vk-layers -d "Enable Vulkan validation layers for debugging" +complete -c godot -l gpu-abort -d "Abort on GPU errors (usually validation layer errors)" complete -c godot -l remote-debug -d "Enable remote debugging" complete -c godot -l debug-collisions -d "Show collision shapes when running the scene" complete -c godot -l debug-navigation -d "Show navigation polygons when running the scene" +complete -c godot -l debug-stringnames -d "Print all StringName allocations to stdout when the engine quits" complete -c godot -l frame-delay -d "Simulate high CPU load (delay each frame by the given number of milliseconds)" -x complete -c godot -l time-scale -d "Force time scale (higher values are faster, 1.0 is normal speed)" -x complete -c godot -l disable-render-loop -d "Disable render loop so rendering only occurs when called explicitly from script" @@ -84,4 +96,5 @@ complete -c godot -l export-pack -d "Same as --export, but only export the game complete -c godot -l doctool -d "Dump the engine API reference to the given path in XML format, merging if existing files are found" -r complete -c godot -l no-docbase -d "Disallow dumping the base types (used with --doctool)" complete -c godot -l build-solutions -d "Build the scripting solutions (e.g. for C# projects)" -complete -c godot -l test -d "Run a unit test" -x +complete -c godot -l dump-extension-api -d "Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder" +complete -c godot -l test -d "Run all unit tests; run with '--test --help' for more information" -x diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 137df52215..be9bf9538f 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -303,17 +303,19 @@ void CSGShape3D::_update_shape() { ERR_CONTINUE(mat < -1 || mat >= face_count.size()); int idx = mat == -1 ? face_count.size() - 1 : mat; - Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]); + if (n->faces[i].smooth) { + Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]); - for (int j = 0; j < 3; j++) { - Vector3 v = n->faces[i].vertices[j]; - Vector3 add; - if (vec_map.lookup(v, add)) { - add += p.normal; - } else { - add = p.normal; + for (int j = 0; j < 3; j++) { + Vector3 v = n->faces[i].vertices[j]; + Vector3 add; + if (vec_map.lookup(v, add)) { + add += p.normal; + } else { + add = p.normal; + } + vec_map.set(v, add); } - vec_map.set(v, add); } face_count.write[idx]++; @@ -1530,6 +1532,9 @@ CSGBrush *CSGTorus3D::_build_brush() { for (int i = 0; i < sides; i++) { float inci = float(i) / sides; float inci_n = float((i + 1)) / sides; + if (i == sides - 1) { + inci_n = 0; + } float angi = inci * Math_TAU; float angi_n = inci_n * Math_TAU; @@ -1540,6 +1545,9 @@ CSGBrush *CSGTorus3D::_build_brush() { for (int j = 0; j < ring_sides; j++) { float incj = float(j) / ring_sides; float incj_n = float((j + 1)) / ring_sides; + if (j == ring_sides - 1) { + incj_n = 0; + } float angj = incj * Math_TAU; float angj_n = incj_n * Math_TAU; diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index c422c3bd6b..7bfe849106 100644 --- a/modules/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp @@ -225,8 +225,8 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, ERR_FAIL_COND_V(!(flags & DDSD_LINEARSIZE), RES()); for (uint32_t i = 1; i < mipmaps; i++) { - w = MAX(1, w >> 1); - h = MAX(1, h >> 1); + w = MAX(1u, w >> 1); + h = MAX(1u, h >> 1); uint32_t bsize = MAX(info.divisor, w) / info.divisor * MAX(info.divisor, h) / info.divisor * info.block_size; //printf("%i x %i - block: %i\n",w,h,bsize); size += bsize; diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index a4b3bfdbd0..68b3a41b9a 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -1244,7 +1244,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d } break; } - push_constant.ray_count = CLAMP(push_constant.ray_count, 16, 8192); + push_constant.ray_count = CLAMP(push_constant.ray_count, 16u, 8192u); int max_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/lightmapping/bake_performance/region_size"))); int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_pass"); @@ -1375,7 +1375,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d } push_constant.atlas_size[0] = probe_positions.size(); - push_constant.ray_count = CLAMP(push_constant.ray_count, 16, 8192); + push_constant.ray_count = CLAMP(push_constant.ray_count, 16u, 8192u); int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_probe_pass"); int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1; diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs index ed758cc137..e2f4d2f5fd 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -107,7 +107,7 @@ namespace GodotTools.Export ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir); // The Godot exporter expects us to pass the abi in the tags parameter - exporter.AddSharedObject(soFilePath, tags: new[] { abi }); + exporter.AddSharedObject(soFilePath, tags: new[] { abi }, ""); } } } @@ -134,7 +134,7 @@ namespace GodotTools.Export if (platform == OS.Platforms.MacOS) { - exporter.AddSharedObject(tempOutputFilePath, tags: null); + exporter.AddSharedObject(tempOutputFilePath, tags: null, ""); } else { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index ee218cb1f8..d4b623b2ea 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -511,8 +511,9 @@ namespace Godot /// Returns the result of the spherical linear interpolation between /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>. /// - /// This method also handles interpolating the lengths if the input vectors have different lengths. - /// For the special case of one or both input vectors having zero length, this method behaves like [method lerp]. + /// This method also handles interpolating the lengths if the input vectors + /// have different lengths. For the special case of one or both input vectors + /// having zero length, this method behaves like <see cref="Lerp"/>. /// </summary> /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 45e5287610..eddfa76f10 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -551,8 +551,9 @@ namespace Godot /// Returns the result of the spherical linear interpolation between /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>. /// - /// This method also handles interpolating the lengths if the input vectors have different lengths. - /// For the special case of one or both input vectors having zero length, this method behaves like [method lerp]. + /// This method also handles interpolating the lengths if the input vectors + /// have different lengths. For the special case of one or both input vectors + /// having zero length, this method behaves like <see cref="Lerp"/>. /// </summary> /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 4cd4772d2c..424b74906f 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -643,9 +643,8 @@ bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const // Create destination directory if needed if (!DirAccess::exists(dst_dir)) { - DirAccess *da = DirAccess::create_for_path(dst_dir); + DirAccessRef da = DirAccess::create_for_path(dst_dir); Error err = da->make_dir_recursive(dst_dir); - memdelete(da); if (err != OK) { ERR_PRINT("Failed to create destination directory for the API assemblies. Error: " + itos(err) + "."); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index b89171543f..39f9153f0d 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -760,8 +760,9 @@ OpenXRInterface::OpenXRInterface() { } OpenXRInterface::~OpenXRInterface() { - // should already have been called but just in case... - uninitialize(); + if (is_initialized()) { + uninitialize(); + } if (openxr_api) { openxr_api->set_xr_interface(nullptr); diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index 96b83bf25a..79ef2de929 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -78,7 +78,7 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin return; } float fw, fh; - picture->viewbox(nullptr, nullptr, &fw, &fh); + picture->size(&fw, &fh); uint32_t width = MIN(fw * p_scale, 16 * 1024); uint32_t height = MIN(fh * p_scale, 16 * 1024); diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 1b4512dc60..7fd9cd42ed 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -704,7 +704,7 @@ String TextServerAdvanced::tag_to_name(int32_t p_tag) const { /* Font Glyph Rendering */ /*************************************************************************/ -_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const { +_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const { FontTexturePosition ret; ret.index = -1; @@ -769,8 +769,11 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_ } texsize = next_power_of_2(texsize); - - texsize = MIN(texsize, 4096); + if (p_msdf) { + texsize = MIN(texsize, 2048); + } else { + texsize = MIN(texsize, 1024); + } FontTexture tex; tex.texture_w = texsize; @@ -935,10 +938,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( int mw = w + p_rect_margin * 2; int mh = h + p_rect_margin * 2; - ERR_FAIL_COND_V(mw > 4096, FontGlyph()); - ERR_FAIL_COND_V(mh > 4096, FontGlyph()); + ERR_FAIL_COND_V(mw > 1024, FontGlyph()); + ERR_FAIL_COND_V(mh > 1024, FontGlyph()); - FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh); + FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true); ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph()); FontTexture &tex = p_data->textures.write[tex_pos.index]; @@ -1013,13 +1016,13 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma int mw = w + p_rect_margin * 2; int mh = h + p_rect_margin * 2; - ERR_FAIL_COND_V(mw > 4096, FontGlyph()); - ERR_FAIL_COND_V(mh > 4096, FontGlyph()); + ERR_FAIL_COND_V(mw > 1024, FontGlyph()); + ERR_FAIL_COND_V(mh > 1024, FontGlyph()); int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2; Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; - FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh); + FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false); ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph()); // Fit character in char texture. @@ -1155,6 +1158,16 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d } } + if (p_font_data->embolden != 0.f) { + FT_Pos strength = p_font_data->embolden * p_size.x * 4; // 26.6 fractional units (1 / 64). + FT_Outline_Embolden(&fd->face->glyph->outline, strength); + } + + if (p_font_data->transform != Transform2D()) { + FT_Matrix mat = { FT_Fixed(p_font_data->transform[0][0] * 65536), FT_Fixed(p_font_data->transform[0][1] * 65536), FT_Fixed(p_font_data->transform[1][0] * 65536), FT_Fixed(p_font_data->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536). + FT_Outline_Transform(&fd->face->glyph->outline, &mat); + } + if (!outline) { if (!p_font_data->msdf) { error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); @@ -1874,6 +1887,44 @@ TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positionin return fd->subpixel_positioning; } +void TextServerAdvanced::font_set_embolden(RID p_font_rid, float p_strength) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + if (fd->embolden != p_strength) { + _font_clear_cache(fd); + fd->embolden = p_strength; + } +} + +float TextServerAdvanced::font_get_embolden(RID p_font_rid) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, 0.f); + + MutexLock lock(fd->mutex); + return fd->embolden; +} + +void TextServerAdvanced::font_set_transform(RID p_font_rid, Transform2D p_transform) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + if (fd->transform != p_transform) { + _font_clear_cache(fd); + fd->transform = p_transform; + } +} + +Transform2D TextServerAdvanced::font_get_transform(RID p_font_rid) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, Transform2D()); + + MutexLock lock(fd->mutex); + return fd->transform; +} + void TextServerAdvanced::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) { FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); @@ -2275,6 +2326,20 @@ void TextServerAdvanced::font_remove_glyph(RID p_font_rid, const Vector2i &p_siz fd->cache[size]->glyph_map.erase(p_glyph); } +float TextServerAdvanced::_get_extra_advance(RID p_font_rid, int p_font_size) const { + const FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, 0.0); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, p_font_size); + + if (fd->embolden != 0.0) { + return fd->embolden * float(size.x) / 64.0; + } else { + return 0.0; + } +} + Vector2 TextServerAdvanced::font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const { FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); @@ -2289,12 +2354,17 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(RID p_font_rid, int p_size, i const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; + Vector2 ea; + if (fd->embolden != 0.0) { + ea.x = fd->embolden * float(size.x) / 64.0; + } + if (fd->msdf) { - return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size; + return (gl[p_glyph].advance + ea) * (float)p_size / (float)fd->msdf_source_size; } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - return gl[p_glyph].advance.round(); + return (gl[p_glyph].advance + ea).round(); } else { - return gl[p_glyph].advance; + return gl[p_glyph].advance + ea; } } @@ -4420,9 +4490,9 @@ Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char float scale = font_get_scale(p_font, p_font_size); if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (subpos) { - gl.advance = glyph_pos[0].x_advance / (64.0 / scale); + gl.advance = glyph_pos[0].x_advance / (64.0 / scale) + _get_extra_advance(p_font, p_font_size); } else { - gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale)); + gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale) + _get_extra_advance(p_font, p_font_size)); } } else { gl.advance = -Math::round(glyph_pos[0].y_advance / (64.0 / scale)); @@ -4499,6 +4569,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star float scale = font_get_scale(f, fs); float sp_sp = font_get_spacing(f, fs, SPACING_SPACE); float sp_gl = font_get_spacing(f, fs, SPACING_GLYPH); + float ea = _get_extra_advance(f, fs); bool subpos = (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_HALF) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_AUTO && fs <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE); ERR_FAIL_COND(hb_font == nullptr); @@ -4577,9 +4648,9 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star if (gl.index != 0) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (subpos) { - gl.advance = glyph_pos[i].x_advance / (64.0 / scale); + gl.advance = glyph_pos[i].x_advance / (64.0 / scale) + ea; } else { - gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale)); + gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale) + ea); } } else { gl.advance = -Math::round(glyph_pos[i].y_advance / (64.0 / scale)); diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 7841a15cd3..e5958fc162 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -177,6 +177,8 @@ class TextServerAdvanced : public TextServer { TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; Dictionary variation_coordinates; float oversampling = 0.f; + float embolden = 0.f; + Transform2D transform; uint32_t style_flags = 0; String font_name; @@ -208,7 +210,7 @@ class TextServerAdvanced : public TextServer { } }; - _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const; + _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const; #ifdef MODULE_MSDFGEN_ENABLED _FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; #endif @@ -240,6 +242,8 @@ class TextServerAdvanced : public TextServer { } } + _FORCE_INLINE_ float _get_extra_advance(RID p_font_rid, int p_font_size) const; + // Shaped text cache data. struct ShapedTextDataAdvanced : public ShapedTextData { @@ -383,6 +387,12 @@ public: virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override; virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override; + virtual void font_set_embolden(RID p_font_rid, float p_strength) override; + virtual float font_get_embolden(RID p_font_rid) const override; + + virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override; + virtual Transform2D font_get_transform(RID p_font_rid) const override; + virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index e6f9bcf131..0d7a9d0db8 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -155,7 +155,7 @@ String TextServerFallback::tag_to_name(int32_t p_tag) const { /* Font Glyph Rendering */ /*************************************************************************/ -_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const { +_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const { FontTexturePosition ret; ret.index = -1; @@ -221,7 +221,11 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_ texsize = next_power_of_2(texsize); - texsize = MIN(texsize, 4096); + if (p_msdf) { + texsize = MIN(texsize, 2048); + } else { + texsize = MIN(texsize, 1024); + } FontTexture tex; tex.texture_w = texsize; @@ -386,10 +390,10 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( int mw = w + p_rect_margin * 2; int mh = h + p_rect_margin * 2; - ERR_FAIL_COND_V(mw > 4096, FontGlyph()); - ERR_FAIL_COND_V(mh > 4096, FontGlyph()); + ERR_FAIL_COND_V(mw > 1024, FontGlyph()); + ERR_FAIL_COND_V(mh > 1024, FontGlyph()); - FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh); + FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true); ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph()); FontTexture &tex = p_data->textures.write[tex_pos.index]; @@ -464,13 +468,13 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma int mw = w + p_rect_margin * 2; int mh = h + p_rect_margin * 2; - ERR_FAIL_COND_V(mw > 4096, FontGlyph()); - ERR_FAIL_COND_V(mh > 4096, FontGlyph()); + ERR_FAIL_COND_V(mw > 1024, FontGlyph()); + ERR_FAIL_COND_V(mh > 1024, FontGlyph()); int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2; Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; - FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh); + FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false); ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph()); // Fit character in char texture. @@ -586,6 +590,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d flags |= FT_LOAD_COLOR; } + glyph_index = FT_Get_Char_Index(fd->face, glyph_index); + FT_Fixed v, h; FT_Get_Advance(fd->face, glyph_index, flags, &h); FT_Get_Advance(fd->face, glyph_index, flags | FT_LOAD_VERTICAL_LAYOUT, &v); @@ -606,6 +612,16 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d } } + if (p_font_data->embolden != 0.f) { + FT_Pos strength = p_font_data->embolden * p_size.x * 4; // 26.6 fractional units (1 / 64). + FT_Outline_Embolden(&fd->face->glyph->outline, strength); + } + + if (p_font_data->transform != Transform2D()) { + FT_Matrix mat = { FT_Fixed(p_font_data->transform[0][0] * 65536), FT_Fixed(p_font_data->transform[0][1] * 65536), FT_Fixed(p_font_data->transform[1][0] * 65536), FT_Fixed(p_font_data->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536). + FT_Outline_Transform(&fd->face->glyph->outline, &mat); + } + if (!outline) { if (!p_font_data->msdf) { error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); @@ -1044,6 +1060,44 @@ TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positionin return fd->subpixel_positioning; } +void TextServerFallback::font_set_embolden(RID p_font_rid, float p_strength) { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + if (fd->embolden != p_strength) { + _font_clear_cache(fd); + fd->embolden = p_strength; + } +} + +float TextServerFallback::font_get_embolden(RID p_font_rid) const { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, 0.f); + + MutexLock lock(fd->mutex); + return fd->embolden; +} + +void TextServerFallback::font_set_transform(RID p_font_rid, Transform2D p_transform) { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + if (fd->transform != p_transform) { + _font_clear_cache(fd); + fd->transform = p_transform; + } +} + +Transform2D TextServerFallback::font_get_transform(RID p_font_rid) const { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, Transform2D()); + + MutexLock lock(fd->mutex); + return fd->transform; +} + void TextServerFallback::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) { FontDataFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); @@ -1459,12 +1513,17 @@ Vector2 TextServerFallback::font_get_glyph_advance(RID p_font_rid, int p_size, i const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; + Vector2 ea; + if (fd->embolden != 0.0) { + ea.x = fd->embolden * float(size.x) / 64.0; + } + if (fd->msdf) { - return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size; + return (gl[p_glyph].advance + ea) * (float)p_size / (float)fd->msdf_source_size; } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - return gl[p_glyph].advance.round(); + return (gl[p_glyph].advance + ea).round(); } else { - return gl[p_glyph].advance; + return gl[p_glyph].advance + ea; } } diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 91afd02ae9..d4c7b5666e 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -142,6 +142,8 @@ class TextServerFallback : public TextServer { TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; Dictionary variation_coordinates; float oversampling = 0.f; + float embolden = 0.f; + Transform2D transform; uint32_t style_flags = 0; String font_name; @@ -172,7 +174,7 @@ class TextServerFallback : public TextServer { } }; - _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const; + _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const; #ifdef MODULE_MSDFGEN_ENABLED _FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; #endif @@ -294,6 +296,12 @@ public: virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override; virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override; + virtual void font_set_embolden(RID p_font_rid, float p_strength) override; + virtual float font_get_embolden(RID p_font_rid) const override; + + virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override; + virtual Transform2D font_get_transform(RID p_font_rid) const override; + virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index 6fae049056..a2e59c9cdf 100644 --- a/modules/visual_script/editor/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -4725,8 +4725,6 @@ VisualScriptEditor::VisualScriptEditor() { undo_redo = EditorNode::get_singleton()->get_undo_redo(); - updating_members = false; - set_process_input(true); default_value_edit = memnew(CustomPropertyEditor); diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index e178f5cf72..5b355a71df 100644 --- a/modules/visual_script/editor/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -148,7 +148,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _update_graph_connections(); void _update_graph(int p_only_id = -1); - bool updating_members; + bool updating_members = false; void _update_members(); String _sanitized_variant_text(const StringName &property_name); diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index a79e6df521..fef159bf87 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -176,7 +176,7 @@ PropertyInfo VisualScriptExpression::get_output_value_port_info(int p_idx) const } String VisualScriptExpression::get_caption() const { - return TTR("Expression"); + return RTR("Expression"); } String VisualScriptExpression::get_text() const { diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index fd1861abc4..d28744a09f 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -70,7 +70,7 @@ PropertyInfo VisualScriptReturn::get_output_value_port_info(int p_idx) const { } String VisualScriptReturn::get_caption() const { - return TTR("Return"); + return RTR("Return"); } String VisualScriptReturn::get_text() const { @@ -201,11 +201,11 @@ PropertyInfo VisualScriptCondition::get_output_value_port_info(int p_idx) const } String VisualScriptCondition::get_caption() const { - return TTR("Condition"); + return RTR("Condition"); } String VisualScriptCondition::get_text() const { - return TTR("if (cond) is:"); + return RTR("if (cond) is:"); } void VisualScriptCondition::_bind_methods() { @@ -281,11 +281,11 @@ PropertyInfo VisualScriptWhile::get_output_value_port_info(int p_idx) const { } String VisualScriptWhile::get_caption() const { - return TTR("While"); + return RTR("While"); } String VisualScriptWhile::get_text() const { - return TTR("while (cond):"); + return RTR("while (cond):"); } void VisualScriptWhile::_bind_methods() { @@ -364,11 +364,11 @@ PropertyInfo VisualScriptIterator::get_output_value_port_info(int p_idx) const { } String VisualScriptIterator::get_caption() const { - return TTR("Iterator"); + return RTR("Iterator"); } String VisualScriptIterator::get_text() const { - return TTR("for (elem) in (input):"); + return RTR("for (elem) in (input):"); } void VisualScriptIterator::_bind_methods() { @@ -478,11 +478,11 @@ PropertyInfo VisualScriptSequence::get_output_value_port_info(int p_idx) const { } String VisualScriptSequence::get_caption() const { - return TTR("Sequence"); + return RTR("Sequence"); } String VisualScriptSequence::get_text() const { - return TTR("in order:"); + return RTR("in order:"); } void VisualScriptSequence::set_steps(int p_steps) { @@ -587,11 +587,11 @@ PropertyInfo VisualScriptSwitch::get_output_value_port_info(int p_idx) const { } String VisualScriptSwitch::get_caption() const { - return TTR("Switch"); + return RTR("Switch"); } String VisualScriptSwitch::get_text() const { - return TTR("'input' is:"); + return RTR("'input' is:"); } class VisualScriptNodeInstanceSwitch : public VisualScriptNodeInstance { @@ -720,14 +720,14 @@ PropertyInfo VisualScriptTypeCast::get_output_value_port_info(int p_idx) const { } String VisualScriptTypeCast::get_caption() const { - return TTR("Type Cast"); + return RTR("Type Cast"); } String VisualScriptTypeCast::get_text() const { if (!script.is_empty()) { - return vformat(TTR("Is %s?"), script.get_file()); + return vformat(RTR("Is %s?"), script.get_file()); } else { - return vformat(TTR("Is %s?"), base_type); + return vformat(RTR("Is %s?"), base_type); } } diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index a63f3edc0d..2c9d23e457 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -33,6 +33,7 @@ #include "core/config/engine.h" #include "core/io/resource_loader.h" #include "core/os/os.h" +#include "core/templates/local_vector.h" #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "visual_script_nodes.h" @@ -261,13 +262,13 @@ String VisualScriptFunctionCall::get_text() const { String text; if (call_mode == CALL_MODE_BASIC_TYPE) { - text = vformat(TTR("On %s"), Variant::get_type_name(basic_type)); + text = vformat(RTR("On %s"), Variant::get_type_name(basic_type)); } else if (call_mode == CALL_MODE_INSTANCE) { - text = vformat(TTR("On %s"), base_type); + text = vformat(RTR("On %s"), base_type); } else if (call_mode == CALL_MODE_NODE_PATH) { text = "[" + String(base_path.simplified()) + "]"; } else if (call_mode == CALL_MODE_SELF) { - text = TTR("On Self"); + text = RTR("On Self"); } else if (call_mode == CALL_MODE_SINGLETON) { text = String(singleton) + ":" + String(function) + "()"; } @@ -1032,18 +1033,18 @@ PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) cons } String VisualScriptPropertySet::get_caption() const { - static const char *opname[ASSIGN_OP_MAX] = { - TTRC("Set %s"), - TTRC("Add %s"), - TTRC("Subtract %s"), - TTRC("Multiply %s"), - TTRC("Divide %s"), - TTRC("Mod %s"), - TTRC("ShiftLeft %s"), - TTRC("ShiftRight %s"), - TTRC("BitAnd %s"), - TTRC("BitOr %s"), - TTRC("BitXor %s") + static const LocalVector<String> opname = { + RTR("Set %s"), + RTR("Add %s"), + RTR("Subtract %s"), + RTR("Multiply %s"), + RTR("Divide %s"), + RTR("Mod %s"), + RTR("ShiftLeft %s"), + RTR("ShiftRight %s"), + RTR("BitAnd %s"), + RTR("BitOr %s"), + RTR("BitXor %s"), }; String prop = property; @@ -1051,7 +1052,7 @@ String VisualScriptPropertySet::get_caption() const { prop += "." + String(index); } - return vformat(TTRGET(opname[assign_op]), prop); + return vformat(opname[assign_op], prop); } String VisualScriptPropertySet::get_text() const { @@ -1059,13 +1060,13 @@ String VisualScriptPropertySet::get_text() const { return ""; } if (call_mode == CALL_MODE_BASIC_TYPE) { - return vformat(TTR("On %s"), Variant::get_type_name(basic_type)); + return vformat(RTR("On %s"), Variant::get_type_name(basic_type)); } else if (call_mode == CALL_MODE_INSTANCE) { - return vformat(TTR("On %s"), base_type); + return vformat(RTR("On %s"), base_type); } else if (call_mode == CALL_MODE_NODE_PATH) { return " [" + String(base_path.simplified()) + "]"; } else { - return TTR("On Self"); + return RTR("On Self"); } } @@ -1776,18 +1777,18 @@ String VisualScriptPropertyGet::get_caption() const { prop += "." + String(index); } - return vformat(TTR("Get %s"), prop); + return vformat(RTR("Get %s"), prop); } String VisualScriptPropertyGet::get_text() const { if (call_mode == CALL_MODE_BASIC_TYPE) { - return vformat(TTR("On %s"), Variant::get_type_name(basic_type)); + return vformat(RTR("On %s"), Variant::get_type_name(basic_type)); } else if (call_mode == CALL_MODE_INSTANCE) { - return vformat(TTR("On %s"), base_type); + return vformat(RTR("On %s"), base_type); } else if (call_mode == CALL_MODE_NODE_PATH) { return " [" + String(base_path.simplified()) + "]"; } else { - return TTR("On Self"); + return RTR("On Self"); } } @@ -2303,7 +2304,7 @@ PropertyInfo VisualScriptEmitSignal::get_output_value_port_info(int p_idx) const } String VisualScriptEmitSignal::get_caption() const { - return vformat(TTR("Emit %s"), name); + return vformat(RTR("Emit %s"), name); } void VisualScriptEmitSignal::set_signal(const StringName &p_type) { diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 204b416c7d..b65b9f090a 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -204,7 +204,7 @@ PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const { } String VisualScriptFunction::get_caption() const { - return TTR("Function"); + return RTR("Function"); } String VisualScriptFunction::get_text() const { @@ -767,7 +767,7 @@ PropertyInfo VisualScriptComposeArray::get_output_value_port_info(int p_idx) con } String VisualScriptComposeArray::get_caption() const { - return TTR("Compose Array"); + return RTR("Compose Array"); } String VisualScriptComposeArray::get_text() const { @@ -1186,11 +1186,11 @@ PropertyInfo VisualScriptSelect::get_output_value_port_info(int p_idx) const { } String VisualScriptSelect::get_caption() const { - return TTR("Select"); + return RTR("Select"); } String VisualScriptSelect::get_text() const { - return TTR("a if cond, else b"); + return RTR("a if cond, else b"); } void VisualScriptSelect::set_typed(Variant::Type p_op) { @@ -1284,7 +1284,7 @@ PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) cons } String VisualScriptVariableGet::get_caption() const { - return vformat(TTR("Get %s"), variable); + return vformat(RTR("Get %s"), variable); } void VisualScriptVariableGet::set_variable(StringName p_variable) { @@ -1394,7 +1394,7 @@ PropertyInfo VisualScriptVariableSet::get_output_value_port_info(int p_idx) cons } String VisualScriptVariableSet::get_caption() const { - return vformat(TTR("Set %s"), variable); + return vformat(RTR("Set %s"), variable); } void VisualScriptVariableSet::set_variable(StringName p_variable) { @@ -1501,7 +1501,7 @@ PropertyInfo VisualScriptConstant::get_output_value_port_info(int p_idx) const { } String VisualScriptConstant::get_caption() const { - return TTR("Constant"); + return RTR("Constant"); } void VisualScriptConstant::set_constant_type(Variant::Type p_type) { @@ -1628,7 +1628,7 @@ PropertyInfo VisualScriptPreload::get_output_value_port_info(int p_idx) const { } String VisualScriptPreload::get_caption() const { - return TTR("Preload"); + return RTR("Preload"); } void VisualScriptPreload::set_preload(const Ref<Resource> &p_preload) { @@ -1708,7 +1708,7 @@ PropertyInfo VisualScriptIndexGet::get_output_value_port_info(int p_idx) const { } String VisualScriptIndexGet::get_caption() const { - return TTR("Get Index"); + return RTR("Get Index"); } class VisualScriptNodeInstanceIndexGet : public VisualScriptNodeInstance { @@ -1775,7 +1775,7 @@ PropertyInfo VisualScriptIndexSet::get_output_value_port_info(int p_idx) const { } String VisualScriptIndexSet::get_caption() const { - return TTR("Set Index"); + return RTR("Set Index"); } class VisualScriptNodeInstanceIndexSet : public VisualScriptNodeInstance { @@ -1836,7 +1836,7 @@ PropertyInfo VisualScriptGlobalConstant::get_output_value_port_info(int p_idx) c } String VisualScriptGlobalConstant::get_caption() const { - return TTR("Global Constant"); + return RTR("Global Constant"); } void VisualScriptGlobalConstant::set_global_constant(int p_which) { @@ -1922,7 +1922,7 @@ PropertyInfo VisualScriptClassConstant::get_output_value_port_info(int p_idx) co } String VisualScriptClassConstant::get_caption() const { - return TTR("Class Constant"); + return RTR("Class Constant"); } void VisualScriptClassConstant::set_class_constant(const StringName &p_which) { @@ -2047,7 +2047,7 @@ PropertyInfo VisualScriptBasicTypeConstant::get_output_value_port_info(int p_idx } String VisualScriptBasicTypeConstant::get_caption() const { - return TTR("Basic Constant"); + return RTR("Basic Constant"); } String VisualScriptBasicTypeConstant::get_text() const { @@ -2212,7 +2212,7 @@ PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) con } String VisualScriptMathConstant::get_caption() const { - return TTR("Math Constant"); + return RTR("Math Constant"); } void VisualScriptMathConstant::set_math_constant(MathConstant p_which) { @@ -2304,7 +2304,7 @@ PropertyInfo VisualScriptEngineSingleton::get_output_value_port_info(int p_idx) } String VisualScriptEngineSingleton::get_caption() const { - return TTR("Get Engine Singleton"); + return RTR("Get Engine Singleton"); } void VisualScriptEngineSingleton::set_singleton(const String &p_string) { @@ -2414,7 +2414,7 @@ PropertyInfo VisualScriptSceneNode::get_output_value_port_info(int p_idx) const } String VisualScriptSceneNode::get_caption() const { - return TTR("Get Scene Node"); + return RTR("Get Scene Node"); } void VisualScriptSceneNode::set_node_path(const NodePath &p_path) { @@ -2605,7 +2605,7 @@ PropertyInfo VisualScriptSceneTree::get_output_value_port_info(int p_idx) const } String VisualScriptSceneTree::get_caption() const { - return TTR("Get Scene Tree"); + return RTR("Get Scene Tree"); } class VisualScriptNodeInstanceSceneTree : public VisualScriptNodeInstance { @@ -2692,7 +2692,7 @@ PropertyInfo VisualScriptResourcePath::get_output_value_port_info(int p_idx) con } String VisualScriptResourcePath::get_caption() const { - return TTR("Resource Path"); + return RTR("Resource Path"); } void VisualScriptResourcePath::set_resource_path(const String &p_path) { @@ -2774,7 +2774,7 @@ PropertyInfo VisualScriptSelf::get_output_value_port_info(int p_idx) const { } String VisualScriptSelf::get_caption() const { - return TTR("Get Self"); + return RTR("Get Self"); } class VisualScriptNodeInstanceSelf : public VisualScriptNodeInstance { @@ -2944,7 +2944,7 @@ String VisualScriptCustomNode::get_caption() const { if (GDVIRTUAL_CALL(_get_caption, ret)) { return ret; } - return TTR("CustomNode"); + return RTR("CustomNode"); } String VisualScriptCustomNode::get_text() const { @@ -3138,7 +3138,7 @@ PropertyInfo VisualScriptSubCall::get_output_value_port_info(int p_idx) const { } String VisualScriptSubCall::get_caption() const { - return TTR("SubCall"); + return RTR("SubCall"); } String VisualScriptSubCall::get_text() const { @@ -3349,7 +3349,7 @@ PropertyInfo VisualScriptConstructor::get_output_value_port_info(int p_idx) cons } String VisualScriptConstructor::get_caption() const { - return vformat(TTR("Construct %s"), Variant::get_type_name(type)); + return vformat(RTR("Construct %s"), Variant::get_type_name(type)); } String VisualScriptConstructor::get_category() const { @@ -3466,7 +3466,7 @@ PropertyInfo VisualScriptLocalVar::get_output_value_port_info(int p_idx) const { } String VisualScriptLocalVar::get_caption() const { - return TTR("Get Local Var"); + return RTR("Get Local Var"); } String VisualScriptLocalVar::get_category() const { @@ -3569,7 +3569,7 @@ PropertyInfo VisualScriptLocalVarSet::get_output_value_port_info(int p_idx) cons } String VisualScriptLocalVarSet::get_caption() const { - return TTR("Set Local Var"); + return RTR("Set Local Var"); } String VisualScriptLocalVarSet::get_text() const { @@ -3693,7 +3693,7 @@ PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) cons } String VisualScriptInputAction::get_caption() const { - return vformat(TTR("Action %s"), name); + return vformat(RTR("Action %s"), name); } String VisualScriptInputAction::get_category() const { @@ -3847,7 +3847,7 @@ PropertyInfo VisualScriptDeconstruct::get_output_value_port_info(int p_idx) cons } String VisualScriptDeconstruct::get_caption() const { - return vformat(TTR("Deconstruct %s"), Variant::get_type_name(type)); + return vformat(RTR("Deconstruct %s"), Variant::get_type_name(type)); } String VisualScriptDeconstruct::get_category() const { diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index fbd5ad35ab..dcd8815394 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -68,7 +68,7 @@ PropertyInfo VisualScriptYield::get_output_value_port_info(int p_idx) const { } String VisualScriptYield::get_caption() const { - return yield_mode == YIELD_RETURN ? TTR("Yield") : TTR("Wait"); + return yield_mode == YIELD_RETURN ? RTR("Yield") : RTR("Wait"); } String VisualScriptYield::get_text() const { @@ -77,13 +77,13 @@ String VisualScriptYield::get_text() const { return ""; break; case YIELD_FRAME: - return TTR("Next Frame"); + return RTR("Next Frame"); break; case YIELD_PHYSICS_FRAME: - return TTR("Next Physics Frame"); + return RTR("Next Physics Frame"); break; case YIELD_WAIT: - return vformat(TTR("%s sec(s)"), rtos(wait_time)); + return vformat(RTR("%s sec(s)"), rtos(wait_time)); break; } @@ -335,13 +335,18 @@ PropertyInfo VisualScriptYieldSignal::get_output_value_port_info(int p_idx) cons } String VisualScriptYieldSignal::get_caption() const { - static const char *cname[3] = { - TTRC("WaitSignal"), - TTRC("WaitNodeSignal"), - TTRC("WaitInstanceSignal"), - }; - - return TTRGET(cname[call_mode]); + switch (call_mode) { + case CALL_MODE_SELF: { + return RTR("WaitSignal"); + } break; + case CALL_MODE_NODE_PATH: { + return RTR("WaitNodeSignal"); + } break; + case CALL_MODE_INSTANCE: { + return RTR("WaitInstanceSignal"); + } break; + } + return String(); } String VisualScriptYieldSignal::get_text() const { diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index ca6a45cb83..df3693ba61 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -1387,6 +1387,7 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> & Vector<String> string_table; String package_name = p_preset->get("package/name"); + Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized"); for (uint32_t i = 0; i < string_count; i++) { uint32_t offset = decode_uint32(&r_manifest[string_table_begins + i * 4]); @@ -1401,9 +1402,8 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> & } else { String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_"); - String prop = "application/config/name_" + lang; - if (ProjectSettings::get_singleton()->has_setting(prop)) { - str = ProjectSettings::get_singleton()->get(prop); + if (appnames.has(lang)) { + str = appnames[lang]; } else { str = get_project_name(package_name); } @@ -2256,9 +2256,9 @@ String EditorExportPlatformAndroid::get_apk_expansion_fullpath(const Ref<EditorE return fullpath; } -Error EditorExportPlatformAndroid::save_apk_expansion_file(const Ref<EditorExportPreset> &p_preset, const String &p_path) { +Error EditorExportPlatformAndroid::save_apk_expansion_file(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) { String fullpath = get_apk_expansion_fullpath(p_preset, p_path); - Error err = save_pack(p_preset, fullpath); + Error err = save_pack(p_preset, p_debug, fullpath); return err; } @@ -2576,7 +2576,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP CustomExportData user_data; user_data.assets_directory = assets_directory; user_data.debug = p_debug; - err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so); + err = export_project_files(p_preset, p_debug, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so); if (err != OK) { EditorNode::add_io_error(TTR("Could not export project files to gradle project\n")); return err; @@ -2589,7 +2589,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP } } else { print_verbose("Saving apk expansion file.."); - err = save_apk_expansion_file(p_preset, p_path); + err = save_apk_expansion_file(p_preset, p_debug, p_path); if (err != OK) { EditorNode::add_io_error(TTR("Could not write expansion package file!")); return err; @@ -2915,10 +2915,10 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP APKExportData ed; ed.ep = &ep; ed.apk = unaligned_apk; - err = export_project_files(p_preset, ignore_apk_file, &ed, save_apk_so); + err = export_project_files(p_preset, p_debug, ignore_apk_file, &ed, save_apk_so); } else { if (apk_expansion) { - err = save_apk_expansion_file(p_preset, p_path); + err = save_apk_expansion_file(p_preset, p_debug, p_path); if (err != OK) { EditorNode::add_io_error(TTR("Could not write expansion package file!")); return err; @@ -2927,7 +2927,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP APKExportData ed; ed.ep = &ep; ed.apk = unaligned_apk; - err = export_project_files(p_preset, save_apk_file, &ed, save_apk_so); + err = export_project_files(p_preset, p_debug, save_apk_file, &ed, save_apk_so); } } diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index a4eb608b19..0f267cf13a 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -210,7 +210,7 @@ public: String get_apk_expansion_fullpath(const Ref<EditorExportPreset> &p_preset, const String &p_path); - Error save_apk_expansion_file(const Ref<EditorExportPreset> &p_preset, const String &p_path); + Error save_apk_expansion_file(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); void get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, int p_flags, Vector<uint8_t> &r_command_line_flags); diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp index 9598d2f9fd..ab915a5f85 100644 --- a/platform/android/export/gradle_export_util.cpp +++ b/platform/android/export/gradle_export_util.cpp @@ -75,11 +75,10 @@ String _get_android_orientation_label(DisplayServer::ScreenOrientation screen_or // Utility method used to create a directory. Error create_directory(const String &p_dir) { if (!DirAccess::exists(p_dir)) { - DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES); ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'."); Error err = filesystem_da->make_dir_recursive(p_dir); ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'."); - memdelete(filesystem_da); } return OK; } @@ -161,6 +160,7 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset return ERR_CANT_OPEN; } da->list_dir_begin(); + Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized"); while (true) { String file = da->get_next(); if (file.is_empty()) { @@ -171,10 +171,9 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset continue; } String locale = file.replace("values-", "").replace("-r", "_"); - String property_name = "application/config/name_" + locale; String locale_directory = "res://android/build/res/" + file + "/godot_project_name_string.xml"; - if (ProjectSettings::get_singleton()->has_setting(property_name)) { - String locale_project_name = ProjectSettings::get_singleton()->get(property_name); + if (appnames.has(locale)) { + String locale_project_name = appnames[locale]; String processed_xml_string = vformat(godot_project_name_xml_string, _android_xml_escape(locale_project_name)); print_verbose("Storing project name for locale " + locale + " under " + locale_directory); store_string_at_path(locale_directory, processed_xml_string); diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index 32e03998da..c238d1b361 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -4,7 +4,7 @@ ext.versions = [ minSdk : 19, // Also update 'platform/android/java/lib/AndroidManifest.xml#minSdkVersion' & 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION' targetSdk : 30, // Also update 'platform/android/java/lib/AndroidManifest.xml#targetSdkVersion' & 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION' buildTools : '30.0.3', - kotlinVersion : '1.5.10', + kotlinVersion : '1.6.10', fragmentVersion : '1.3.6', javaVersion : 11, ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated. @@ -86,13 +86,12 @@ ext.getGodotEditorVersion = { -> return editorVersion } -ext.getGodotLibraryVersion = { -> +ext.generateGodotLibraryVersion = { List<String> requiredKeys -> // Attempt to read the version from the `version.py` file. String libraryVersion = "" File versionFile = new File("../../../version.py") if (versionFile.isFile()) { - List<String> requiredKeys = ["major", "minor", "patch", "status", "module_config"] def map = [:] List<String> lines = versionFile.readLines() @@ -121,6 +120,16 @@ ext.getGodotLibraryVersion = { -> return libraryVersion } +ext.getGodotLibraryVersion = { -> + List<String> requiredKeys = ["major", "minor", "patch", "status", "module_config"] + return generateGodotLibraryVersion(requiredKeys) +} + +ext.getGodotPublishVersion = { -> + List<String> requiredKeys = ["major", "minor", "patch", "status"] + return generateGodotLibraryVersion(requiredKeys) +} + final String VALUE_SEPARATOR_REGEX = "\\|" // get the list of ABIs the project should be exported to diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index ac008edbed..83bc68c992 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -1,4 +1,6 @@ +apply plugin: 'io.github.gradle-nexus.publish-plugin' apply from: 'app/config.gradle' +apply from: 'scripts/publish-root.gradle' buildscript { apply from: 'app/config.gradle' @@ -6,10 +8,12 @@ buildscript { repositories { google() mavenCentral() + maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath libraries.androidGradlePlugin classpath libraries.kotlinGradlePlugin + classpath 'io.github.gradle-nexus:publish-plugin:1.1.0' } } diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle index fbed4ed078..120a40a31d 100644 --- a/platform/android/java/lib/build.gradle +++ b/platform/android/java/lib/build.gradle @@ -1,6 +1,13 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' +ext { + PUBLISH_VERSION = getGodotPublishVersion() + PUBLISH_ARTIFACT_ID = 'godot' +} + +apply from: "../scripts/publish-module.gradle" + dependencies { implementation libraries.kotlinStdLib implementation libraries.androidxFragment @@ -21,6 +28,8 @@ android { manifestPlaceholders = [godotLibraryVersion: getGodotLibraryVersion()] } + namespace = "org.godotengine.godot" + compileOptions { sourceCompatibility versions.javaVersion targetCompatibility versions.javaVersion @@ -111,4 +120,12 @@ android { // Schedule the tasks so the generated libs are present before the aar file is packaged. tasks["merge${buildType}JniLibFolders"].dependsOn taskName } + + // TODO: Enable when issues with AGP 7.1+ are resolved (https://github.com/GodotVR/godot_openxr/issues/187). +// publishing { +// singleVariant("release") { +// withSourcesJar() +// withJavadocJar() +// } +// } } diff --git a/platform/android/java/scripts/publish-module.gradle b/platform/android/java/scripts/publish-module.gradle new file mode 100644 index 0000000000..6b2aea5caf --- /dev/null +++ b/platform/android/java/scripts/publish-module.gradle @@ -0,0 +1,74 @@ +apply plugin: 'maven-publish' +apply plugin: 'signing' + +group = ossrhGroupId +version = PUBLISH_VERSION + +afterEvaluate { + publishing { + publications { + release(MavenPublication) { + // The coordinates of the library, being set from variables that + // we'll set up later + groupId ossrhGroupId + artifactId PUBLISH_ARTIFACT_ID + version PUBLISH_VERSION + + // Two artifacts, the `aar` (or `jar`) and the sources + if (project.plugins.findPlugin("com.android.library")) { + from components.release + } else { + from components.java + } + + // Mostly self-explanatory metadata + pom { + name = PUBLISH_ARTIFACT_ID + description = 'Godot Engine Android Library' + url = 'https://godotengine.org/' + licenses { + license { + name = 'MIT License' + url = 'https://github.com/godotengine/godot/blob/master/LICENSE.txt' + } + } + developers { + developer { + id = 'm4gr3d' + name = 'Fredia Huya-Kouadio' + email = 'fhuyakou@gmail.com' + } + developer { + id = 'reduz' + name = 'Juan Linietsky' + email = 'reduzio@gmail.com' + } + developer { + id = 'akien-mga' + name = 'Rémi Verschelde' + email = 'rverschelde@gmail.com' + } + // Add all other devs here... + } + + // Version control info - if you're using GitHub, follow the + // format as seen here + scm { + connection = 'scm:git:github.com/godotengine/godot.git' + developerConnection = 'scm:git:ssh://github.com/godotengine/godot.git' + url = 'https://github.com/godotengine/godot/tree/master' + } + } + } + } + } +} + +signing { + useInMemoryPgpKeys( + rootProject.ext["signing.keyId"], + rootProject.ext["signing.key"], + rootProject.ext["signing.password"], + ) + sign publishing.publications +} diff --git a/platform/android/java/scripts/publish-root.gradle b/platform/android/java/scripts/publish-root.gradle new file mode 100644 index 0000000000..ae88487c34 --- /dev/null +++ b/platform/android/java/scripts/publish-root.gradle @@ -0,0 +1,39 @@ +// Create variables with empty default values +ext["signing.keyId"] = '' +ext["signing.password"] = '' +ext["signing.key"] = '' +ext["ossrhGroupId"] = '' +ext["ossrhUsername"] = '' +ext["ossrhPassword"] = '' +ext["sonatypeStagingProfileId"] = '' + +File secretPropsFile = project.rootProject.file('local.properties') +if (secretPropsFile.exists()) { + // Read local.properties file first if it exists + Properties p = new Properties() + new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) } + p.each { name, value -> ext[name] = value } +} else { + // Use system environment variables + ext["ossrhGroupId"] = System.getenv('OSSRH_GROUP_ID') + ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME') + ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD') + ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID') + ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') + ext["signing.password"] = System.getenv('SIGNING_PASSWORD') + ext["signing.key"] = System.getenv('SIGNING_KEY') +} + +// Set up Sonatype repository +nexusPublishing { + repositories { + sonatype { + stagingProfileId = sonatypeStagingProfileId + username = ossrhUsername + password = ossrhPassword + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + } + } +} + diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp index 2eaf5e47ac..ac5886e620 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/iphone/export/export_plugin.cpp @@ -92,13 +92,10 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); Vector<PluginConfigIOS> found_plugins = get_plugins(); for (int i = 0; i < found_plugins.size(); i++) { @@ -139,8 +136,11 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with Retina display r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with Retina HD display @@ -200,8 +200,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n"; } else if (lines[i].find("$name") != -1) { strnew += lines[i].replace("$name", p_config.pkg_name) + "\n"; - } else if (lines[i].find("$info") != -1) { - strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n"; } else if (lines[i].find("$bundle_identifier") != -1) { strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n"; } else if (lines[i].find("$short_version") != -1) { @@ -210,8 +208,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n"; } else if (lines[i].find("$signature") != -1) { strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n"; - } else if (lines[i].find("$copyright") != -1) { - strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n"; } else if (lines[i].find("$team_id") != -1) { strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n"; } else if (lines[i].find("$default_build_config") != -1) { @@ -534,7 +530,7 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr String json_description = "{\"images\":["; String sizes; - DirAccess *da = DirAccess::open(p_iconset_dir); + DirAccessRef da = DirAccess::open(p_iconset_dir); ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'."); for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) { @@ -574,7 +570,6 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr } if (err) { - memdelete(da); String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'."); ERR_PRINT(err_str.utf8().get_data()); return err; @@ -592,7 +587,6 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr json_description += String("}"); } json_description += "]}"; - memdelete(da); FileAccess *json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE); ERR_FAIL_COND_V(!json_file, ERR_CANT_CREATE); @@ -678,7 +672,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor } Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) { - DirAccess *da = DirAccess::open(p_dest_dir); + DirAccessRef da = DirAccess::open(p_dest_dir); ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'."); for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) { @@ -716,7 +710,6 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp err = da->copy(loading_screen_file, p_dest_dir + info.export_name); } if (err) { - memdelete(da); String err_str = String("Failed to export loading screen (") + info.preset_key + ") from path '" + loading_screen_file + "'."; ERR_PRINT(err_str.utf8().get_data()); return err; @@ -764,7 +757,6 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp } } } - memdelete(da); return OK; } @@ -970,21 +962,15 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese } Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) { - DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'."); - String binary_name = p_out_dir.get_file().get_basename(); - DirAccess *da = DirAccess::create_for_path(p_asset); + DirAccessRef da = DirAccess::create_for_path(p_asset); if (!da) { - memdelete(filesystem_da); ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + "."); } bool file_exists = da->file_exists(p_asset); bool dir_exists = da->dir_exists(p_asset); if (!file_exists && !dir_exists) { - memdelete(da); - memdelete(filesystem_da); return ERR_FILE_NOT_FOUND; } @@ -1044,19 +1030,18 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String destination = p_out_dir.plus_file(asset_path); } + DirAccessRef filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'."); + if (!filesystem_da->dir_exists(destination_dir)) { Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); if (make_dir_err) { - memdelete(da); - memdelete(filesystem_da); return make_dir_err; } } Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination); - memdelete(da); if (err) { - memdelete(filesystem_da); return err; } IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed }; @@ -1121,8 +1106,6 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String } } - memdelete(filesystem_da); - return OK; } @@ -1427,29 +1410,29 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p return ERR_FILE_BAD_PATH; } - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - if (da) { - String current_dir = da->get_current_dir(); - - // remove leftovers from last export so they don't interfere - // in case some files are no longer needed - if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) { - da->erase_contents_recursive(); - } - if (da->change_dir(dest_dir + binary_name) == OK) { - da->erase_contents_recursive(); - } + { + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + if (da) { + String current_dir = da->get_current_dir(); + + // remove leftovers from last export so they don't interfere + // in case some files are no longer needed + if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) { + da->erase_contents_recursive(); + } + if (da->change_dir(dest_dir + binary_name) == OK) { + da->erase_contents_recursive(); + } - da->change_dir(current_dir); + da->change_dir(current_dir); - if (!da->dir_exists(dest_dir + binary_name)) { - Error err = da->make_dir(dest_dir + binary_name); - if (err) { - memdelete(da); - return err; + if (!da->dir_exists(dest_dir + binary_name)) { + Error err = da->make_dir(dest_dir + binary_name); + if (err) { + return err; + } } } - memdelete(da); } if (ep.step("Making .pck", 0)) { @@ -1457,7 +1440,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p } String pack_path = dest_dir + binary_name + ".pck"; Vector<SharedObject> libraries; - Error err = save_pack(p_preset, pack_path, &libraries); + Error err = save_pack(p_preset, p_debug, pack_path, &libraries); if (err) { return err; } @@ -1470,9 +1453,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p print_line("Static framework: " + library_to_use); String pkg_name; - if (p_preset->get("application/name") != "") { - pkg_name = p_preset->get("application/name"); // app_name - } else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") { + if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") { pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name")); } else { pkg_name = "Unnamed"; @@ -1507,7 +1488,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p Vector<IOSExportAsset> assets; - DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir); + DirAccessRef tmp_app_path = DirAccess::create_for_path(dest_dir); ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE); print_line("Unzipping..."); @@ -1586,7 +1567,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p if (dir_err) { ERR_PRINT("Can't create '" + dir_name + "'."); unzClose(src_pkg_zip); - memdelete(tmp_app_path); return ERR_CANT_CREATE; } } @@ -1596,7 +1576,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p if (!f) { ERR_PRINT("Can't write '" + file + "'."); unzClose(src_pkg_zip); - memdelete(tmp_app_path); return ERR_CANT_CREATE; }; f->store_buffer(data.ptr(), data.size()); @@ -1619,28 +1598,48 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p if (!found_library) { ERR_PRINT("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive."); - memdelete(tmp_app_path); return ERR_FILE_NOT_FOUND; } + Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized"); + Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized"); + Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized"); + Dictionary photolibrary_usage_descriptions = p_preset->get("privacy/photolibrary_usage_description_localized"); + Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); if (translations.size() > 0) { { String fname = dest_dir + binary_name + "/en.lproj"; tmp_app_path->make_dir_recursive(fname); FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + f->store_line("/* Localized versions of Info.plist keys */"); + f->store_line(""); f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";"); + f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";"); + f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";"); + f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";"); } for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); if (tr.is_valid()) { - String fname = dest_dir + binary_name + "/" + tr->get_locale() + ".lproj"; + String lang = tr->get_locale(); + String fname = dest_dir + binary_name + "/" + lang + ".lproj"; tmp_app_path->make_dir_recursive(fname); FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); - String prop = "application/config/name_" + tr->get_locale(); - if (ProjectSettings::get_singleton()->has_setting(prop)) { - f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";"); + f->store_line("/* Localized versions of Info.plist keys */"); + f->store_line(""); + if (appnames.has(lang)) { + f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";"); + } + if (camera_usage_descriptions.has(lang)) { + f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";"); + } + if (microphone_usage_descriptions.has(lang)) { + f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";"); + } + if (photolibrary_usage_descriptions.has(lang)) { + f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";"); } } } @@ -1656,7 +1655,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p Error lib_copy_err = tmp_app_path->copy(static_lib_path, dest_lib_file_path); if (lib_copy_err != OK) { ERR_PRINT("Can't copy '" + static_lib_path + "'."); - memdelete(tmp_app_path); return lib_copy_err; } } @@ -1667,7 +1665,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p if (!tmp_app_path->dir_exists(iconset_dir)) { err = tmp_app_path->make_dir_recursive(iconset_dir); } - memdelete(tmp_app_path); if (err) { return err; } @@ -1677,43 +1674,43 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p return err; } - bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard"); + { + bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard"); - String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/"; - String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/"; + String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/"; + String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/"; - DirAccess *launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - if (!launch_screen_da) { - return ERR_CANT_CREATE; - } + if (!launch_screen_da) { + return ERR_CANT_CREATE; + } - if (use_storyboard) { - print_line("Using Launch Storyboard"); + if (use_storyboard) { + print_line("Using Launch Storyboard"); - if (launch_screen_da->change_dir(launch_image_path) == OK) { - launch_screen_da->erase_contents_recursive(); - launch_screen_da->remove(launch_image_path); - } + if (launch_screen_da->change_dir(launch_image_path) == OK) { + launch_screen_da->erase_contents_recursive(); + launch_screen_da->remove(launch_image_path); + } - err = _export_loading_screen_file(p_preset, splash_image_path); - } else { - print_line("Using Launch Images"); + err = _export_loading_screen_file(p_preset, splash_image_path); + } else { + print_line("Using Launch Images"); - const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard"; + const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard"; - launch_screen_da->remove(launch_screen_path); + launch_screen_da->remove(launch_screen_path); - if (launch_screen_da->change_dir(splash_image_path) == OK) { - launch_screen_da->erase_contents_recursive(); - launch_screen_da->remove(splash_image_path); - } + if (launch_screen_da->change_dir(splash_image_path) == OK) { + launch_screen_da->erase_contents_recursive(); + launch_screen_da->remove(splash_image_path); + } - err = _export_loading_screen_images(p_preset, launch_image_path); + err = _export_loading_screen_images(p_preset, launch_image_path); + } } - memdelete(launch_screen_da); - if (err) { return err; } @@ -1732,15 +1729,17 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p memdelete(f); #ifdef OSX_ENABLED - if (ep.step("Code-signing dylibs", 2)) { - return ERR_SKIP; + { + if (ep.step("Code-signing dylibs", 2)) { + return ERR_SKIP; + } + DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs"); + ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN); + CodesignData codesign_data(p_preset, p_debug); + err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data); + memdelete(dylibs_dir); + ERR_FAIL_COND_V(err, err); } - DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs"); - ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN); - CodesignData codesign_data(p_preset, p_debug); - err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data); - memdelete(dylibs_dir); - ERR_FAIL_COND_V(err, err); if (ep.step("Making .xcarchive", 3)) { return ERR_SKIP; diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index 56cb49318c..1d990b5625 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -259,11 +259,9 @@ Error OSIPhone::shell_open(String p_uri) { } void OSIPhone::set_user_data_dir(String p_dir) { - DirAccess *da = DirAccess::open(p_dir); - + DirAccessRef da = DirAccess::open(p_dir); user_data_dir = da->get_current_dir(); printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data()); - memdelete(da); } String OSIPhone::get_user_data_dir() const { diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp index bea54ae1cb..0442a1eaeb 100644 --- a/platform/javascript/api/javascript_tools_editor_plugin.cpp +++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp @@ -124,7 +124,7 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z } void JavaScriptToolsEditorPlugin::_zip_recursive(String p_path, String p_base_path, zipFile p_zip) { - DirAccess *dir = DirAccess::open(p_path); + DirAccessRef dir = DirAccess::open(p_path); if (!dir) { WARN_PRINT("Unable to open directory for zipping: " + p_path); return; diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index 2caf369354..a38040922d 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -34,7 +34,7 @@ #include "drivers/gles3/rasterizer_gles3.h" #endif #include "platform/javascript/os_javascript.h" -#include "servers/rendering/rasterizer_dummy.h" +#include "servers/rendering/dummy/rasterizer_dummy.h" #include <emscripten.h> #include <png.h> diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp index c7e503732d..4448acccc2 100644 --- a/platform/javascript/export/export_plugin.cpp +++ b/platform/javascript/export/export_plugin.cpp @@ -252,7 +252,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> & // Custom offline page const String offline_page = p_preset->get("progressive_web_app/offline_page"); if (!offline_page.is_empty()) { - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); const String offline_dest = dir.plus_file(name + ".offline.html"); err = da->copy(ProjectSettings::get_singleton()->globalize_path(offline_page), offline_dest); if (err != OK) { @@ -440,23 +440,23 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese // Export pck and shared objects Vector<SharedObject> shared_objects; String pck_path = base_path + ".pck"; - Error error = save_pack(p_preset, pck_path, &shared_objects); + Error error = save_pack(p_preset, p_debug, pck_path, &shared_objects); if (error != OK) { EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + pck_path); return error; } - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - for (int i = 0; i < shared_objects.size(); i++) { - String dst = base_dir.plus_file(shared_objects[i].path.get_file()); - error = da->copy(shared_objects[i].path, dst); - if (error != OK) { - EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + shared_objects[i].path.get_file()); - memdelete(da); - return error; + + { + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + for (int i = 0; i < shared_objects.size(); i++) { + String dst = base_dir.plus_file(shared_objects[i].path.get_file()); + error = da->copy(shared_objects[i].path, dst); + if (error != OK) { + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + shared_objects[i].path.get_file()); + return error; + } } } - memdelete(da); - da = nullptr; // Extract templates. error = _extract_template(template_path, base_dir, base_name, pwa); diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 140368987c..86874687ad 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -535,9 +535,8 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) { // Issue an error if "mv" failed to move the given resource to the trash can. if (err != OK || retval != 0) { ERR_PRINT("move_to_trash: Could not move the resource \"" + path + "\" to the trash can \"" + trash_path + "/files\""); - DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); err = dir_access->rename(renamed_path, path); - memdelete(dir_access); ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename \"" + renamed_path + "\" back to its original name: \"" + path + "\""); return FAILED; } diff --git a/platform/osx/export/codesign.cpp b/platform/osx/export/codesign.cpp index 1a2ad2bee6..b609a21c44 100644 --- a/platform/osx/export/codesign.cpp +++ b/platform/osx/export/codesign.cpp @@ -1208,7 +1208,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const String id; String main_exe = p_exe_path; - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (!da) { r_error_msg = TTR("Can't get filesystem access."); ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CodeSign: Can't get filesystem access."); @@ -1522,7 +1522,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const } Error CodeSign::codesign(bool p_use_hardened_runtime, bool p_force, const String &p_path, const String &p_ent_path, String &r_error_msg) { - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (!da) { r_error_msg = TTR("Can't get filesystem access."); ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CodeSign: Can't get filesystem access."); diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 4d0fc9add6..890e66ffd5 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -72,8 +72,6 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); @@ -81,18 +79,30 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/location_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the location information"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/location_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/address_book_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the address book"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/address_book_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/calendar_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the calendar"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/calendar_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photos_library_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the photo library"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photos_library_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/desktop_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Desktop folder"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/desktop_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/documents_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Documents folder"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/documents_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/downloads_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Downloads folder"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/downloads_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/network_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use network volumes"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/network_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/removable_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), "")); @@ -316,9 +326,7 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset if (lines[i].find("$binary") != -1) { strnew += lines[i].replace("$binary", p_binary) + "\n"; } else if (lines[i].find("$name") != -1) { - strnew += lines[i].replace("$name", p_binary) + "\n"; - } else if (lines[i].find("$info") != -1) { - strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n"; + strnew += lines[i].replace("$name", ProjectSettings::get_singleton()->get("application/config/name")) + "\n"; } else if (lines[i].find("$bundle_identifier") != -1) { strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n"; } else if (lines[i].find("$short_version") != -1) { @@ -450,7 +458,7 @@ Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset return OK; } -Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path) { +Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn) { bool force_builtin_codesign = EditorSettings::get_singleton()->get("export/macos/force_builtin_codesign"); bool ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); @@ -459,10 +467,10 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese #ifdef MODULE_REGEX_ENABLED #ifdef OSX_ENABLED - if (p_preset->get("codesign/timestamp")) { + if (p_preset->get("codesign/timestamp") && p_warn) { WARN_PRINT("Timestamping is not compatible with ad-hoc signature, and was disabled!"); } - if (p_preset->get("codesign/hardened_runtime")) { + if (p_preset->get("codesign/hardened_runtime") && p_warn) { WARN_PRINT("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!"); } #endif @@ -482,14 +490,18 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese List<String> args; if (p_preset->get("codesign/timestamp")) { if (ad_hoc) { - WARN_PRINT("Timestamping is not compatible with ad-hoc signature, and was disabled!"); + if (p_warn) { + WARN_PRINT("Timestamping is not compatible with ad-hoc signature, and was disabled!"); + } } else { args.push_back("--timestamp"); } } if (p_preset->get("codesign/hardened_runtime")) { if (ad_hoc) { - WARN_PRINT("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!"); + if (p_warn) { + WARN_PRINT("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!"); + } } else { args.push_back("--options"); args.push_back("runtime"); @@ -569,7 +581,7 @@ Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset } if (extensions_to_sign.find(current_file.get_extension()) > -1) { - Error code_sign_error{ _code_sign(p_preset, current_file_path, p_ent_path) }; + Error code_sign_error{ _code_sign(p_preset, current_file_path, p_ent_path, false) }; if (code_sign_error != OK) { return code_sign_error; } @@ -613,7 +625,7 @@ Error EditorExportPlatformOSX::_copy_and_sign_files(DirAccessRef &dir_access, co // If it is a directory, find and sign all dynamic libraries. err = _code_sign_directory(p_preset, p_in_app_path, p_ent_path, p_should_error_on_non_code_sign); } else { - err = _code_sign(p_preset, p_in_app_path, p_ent_path); + err = _code_sign(p_preset, p_in_app_path, p_ent_path, false); } } return err; @@ -713,9 +725,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64"; String pkg_name; - if (p_preset->get("application/name") != "") { - pkg_name = p_preset->get("application/name"); // app_name - } else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") { + if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") { pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name")); } else { pkg_name = "Unnamed"; @@ -781,24 +791,112 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources"); } + Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized"); + Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized"); + Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized"); + Dictionary location_usage_descriptions = p_preset->get("privacy/location_usage_description_localized"); + Dictionary address_book_usage_descriptions = p_preset->get("privacy/address_book_usage_description_localized"); + Dictionary calendar_usage_descriptions = p_preset->get("privacy/calendar_usage_description_localized"); + Dictionary photos_library_usage_descriptions = p_preset->get("privacy/photos_library_usage_description_localized"); + Dictionary desktop_folder_usage_descriptions = p_preset->get("privacy/desktop_folder_usage_description_localized"); + Dictionary documents_folder_usage_descriptions = p_preset->get("privacy/documents_folder_usage_description_localized"); + Dictionary downloads_folder_usage_descriptions = p_preset->get("privacy/downloads_folder_usage_description_localized"); + Dictionary network_volumes_usage_descriptions = p_preset->get("privacy/network_volumes_usage_description_localized"); + Dictionary removable_volumes_usage_descriptions = p_preset->get("privacy/removable_volumes_usage_description_localized"); + Dictionary copyrights = p_preset->get("application/copyright_localized"); + Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); if (translations.size() > 0) { { String fname = tmp_app_path_name + "/Contents/Resources/en.lproj"; tmp_app_dir->make_dir_recursive(fname); FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + f->store_line("/* Localized versions of Info.plist keys */"); + f->store_line(""); f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";"); + if (!((String)p_preset->get("privacy/microphone_usage_description")).is_empty()) { + f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/camera_usage_description")).is_empty()) { + f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/location_usage_description")).is_empty()) { + f->store_line("NSLocationUsageDescription = \"" + p_preset->get("privacy/location_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/address_book_usage_description")).is_empty()) { + f->store_line("NSContactsUsageDescription = \"" + p_preset->get("privacy/address_book_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/calendar_usage_description")).is_empty()) { + f->store_line("NSCalendarsUsageDescription = \"" + p_preset->get("privacy/calendar_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/photos_library_usage_description")).is_empty()) { + f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photos_library_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/desktop_folder_usage_description")).is_empty()) { + f->store_line("NSDesktopFolderUsageDescription = \"" + p_preset->get("privacy/desktop_folder_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/documents_folder_usage_description")).is_empty()) { + f->store_line("NSDocumentsFolderUsageDescription = \"" + p_preset->get("privacy/documents_folder_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/downloads_folder_usage_description")).is_empty()) { + f->store_line("NSDownloadsFolderUsageDescription = \"" + p_preset->get("privacy/downloads_folder_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/network_volumes_usage_description")).is_empty()) { + f->store_line("NSNetworkVolumesUsageDescription = \"" + p_preset->get("privacy/network_volumes_usage_description").operator String() + "\";"); + } + if (!((String)p_preset->get("privacy/removable_volumes_usage_description")).is_empty()) { + f->store_line("NSRemovableVolumesUsageDescription = \"" + p_preset->get("privacy/removable_volumes_usage_description").operator String() + "\";"); + } + f->store_line("NSHumanReadableCopyright = \"" + p_preset->get("application/copyright").operator String() + "\";"); } for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); if (tr.is_valid()) { - String fname = tmp_app_path_name + "/Contents/Resources/" + tr->get_locale() + ".lproj"; + String lang = tr->get_locale(); + String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj"; tmp_app_dir->make_dir_recursive(fname); FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); - String prop = "application/config/name_" + tr->get_locale(); - if (ProjectSettings::get_singleton()->has_setting(prop)) { - f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";"); + f->store_line("/* Localized versions of Info.plist keys */"); + f->store_line(""); + if (appnames.has(lang)) { + f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";"); + } + if (microphone_usage_descriptions.has(lang)) { + f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";"); + } + if (camera_usage_descriptions.has(lang)) { + f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";"); + } + if (location_usage_descriptions.has(lang)) { + f->store_line("NSLocationUsageDescription = \"" + location_usage_descriptions[lang].operator String() + "\";"); + } + if (address_book_usage_descriptions.has(lang)) { + f->store_line("NSContactsUsageDescription = \"" + address_book_usage_descriptions[lang].operator String() + "\";"); + } + if (calendar_usage_descriptions.has(lang)) { + f->store_line("NSCalendarsUsageDescription = \"" + calendar_usage_descriptions[lang].operator String() + "\";"); + } + if (photos_library_usage_descriptions.has(lang)) { + f->store_line("NSPhotoLibraryUsageDescription = \"" + photos_library_usage_descriptions[lang].operator String() + "\";"); + } + if (desktop_folder_usage_descriptions.has(lang)) { + f->store_line("NSDesktopFolderUsageDescription = \"" + desktop_folder_usage_descriptions[lang].operator String() + "\";"); + } + if (documents_folder_usage_descriptions.has(lang)) { + f->store_line("NSDocumentsFolderUsageDescription = \"" + documents_folder_usage_descriptions[lang].operator String() + "\";"); + } + if (downloads_folder_usage_descriptions.has(lang)) { + f->store_line("NSDownloadsFolderUsageDescription = \"" + downloads_folder_usage_descriptions[lang].operator String() + "\";"); + } + if (network_volumes_usage_descriptions.has(lang)) { + f->store_line("NSNetworkVolumesUsageDescription = \"" + network_volumes_usage_descriptions[lang].operator String() + "\";"); + } + if (removable_volumes_usage_descriptions.has(lang)) { + f->store_line("NSRemovableVolumesUsageDescription = \"" + removable_volumes_usage_descriptions[lang].operator String() + "\";"); + } + if (copyrights.has(lang)) { + f->store_line("NSHumanReadableCopyright = \"" + copyrights[lang].operator String() + "\";"); } } } @@ -952,7 +1050,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p String pack_path = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck"; Vector<SharedObject> shared_objects; - err = save_pack(p_preset, pack_path, &shared_objects); + err = save_pack(p_preset, p_debug, pack_path, &shared_objects); // See if we can code sign our new package. bool sign_enabled = p_preset->get("codesign/enable"); @@ -1119,7 +1217,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p String hlp_path = helpers[i]; err = da->copy(hlp_path, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file()); if (err == OK && sign_enabled) { - err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), hlp_ent_path); + err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), hlp_ent_path, false); } FileAccess::set_unix_permissions(tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), 0755); } @@ -1144,8 +1242,13 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < shared_objects.size(); i++) { String src_path = ProjectSettings::get_singleton()->globalize_path(shared_objects[i].path); - String path_in_app{ tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file() }; - err = _copy_and_sign_files(da, src_path, path_in_app, sign_enabled, p_preset, ent_path, true); + if (shared_objects[i].target.is_empty()) { + String path_in_app = tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file(); + err = _copy_and_sign_files(da, src_path, path_in_app, sign_enabled, p_preset, ent_path, true); + } else { + String path_in_app = tmp_app_path_name.plus_file(shared_objects[i].target).plus_file(src_path.get_file()); + err = _copy_and_sign_files(da, src_path, path_in_app, sign_enabled, p_preset, ent_path, false); + } if (err != OK) { break; } @@ -1163,7 +1266,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p if (sign_enabled) { for (int i = 0; i < dylibs_found.size(); i++) { if (err == OK) { - err = _code_sign(p_preset, tmp_app_path_name + "/" + dylibs_found[i], ent_path); + err = _code_sign(p_preset, tmp_app_path_name + "/" + dylibs_found[i], ent_path, false); } } } @@ -1188,7 +1291,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p if (ep.step(TTR("Code signing DMG"), 3)) { return ERR_SKIP; } - err = _code_sign(p_preset, p_path, ent_path); + err = _code_sign(p_preset, p_path, ent_path, false); } } else if (export_format == "zip") { // Create ZIP. diff --git a/platform/osx/export/export_plugin.h b/platform/osx/export/export_plugin.h index b85e9d662c..20cdd33f86 100644 --- a/platform/osx/export/export_plugin.h +++ b/platform/osx/export/export_plugin.h @@ -56,7 +56,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform { void _make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data); Error _notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path); - Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path); + Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn = true); Error _code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_should_error_on_non_code = true); Error _copy_and_sign_files(DirAccessRef &dir_access, const String &p_src_path, const String &p_in_app_path, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path, diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp index a76ff042b2..230e5c749c 100644 --- a/platform/uwp/export/export_plugin.cpp +++ b/platform/uwp/export/export_plugin.cpp @@ -416,7 +416,7 @@ Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_p EditorNode::progress_add_task("project_files", "Project Files", 100); packager.set_progress_task("project_files"); - err = export_project_files(p_preset, save_appx_file, &packager); + err = export_project_files(p_preset, p_debug, save_appx_file, &packager); EditorNode::progress_end_task("project_files"); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 27b4a2018f..d09ca52099 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -1917,16 +1917,14 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) { void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) - // TODO disabling for now - //context_vulkan->set_vsync_mode(p_window, p_vsync_mode); + context_vulkan->set_vsync_mode(p_window, p_vsync_mode); #endif } DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) - //TODO disabling for now - //return context_vulkan->get_vsync_mode(p_window); + return context_vulkan->get_vsync_mode(p_window); #endif return DisplayServer::VSYNC_ENABLED; } @@ -3598,12 +3596,11 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win return; } - //gl_manager->set_use_vsync(current_videomode.use_vsync); RasterizerGLES3::make_current(); } #endif - HHOOK mouse_monitor = SetWindowsHookEx(WH_MOUSE, ::MouseProc, nullptr, GetCurrentThreadId()); + mouse_monitor = SetWindowsHookEx(WH_MOUSE, ::MouseProc, nullptr, GetCurrentThreadId()); Point2i window_position( (screen_get_size(0).width - p_resolution.width) / 2, diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 390e6685b1..efde8d8a2b 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -79,6 +79,7 @@ void Camera2D::set_zoom(const Vector2 &p_zoom) { ERR_FAIL_COND_MSG(Math::is_zero_approx(p_zoom.x) || Math::is_zero_approx(p_zoom.y), "Zoom level must be different from 0 (can be negative)."); zoom = p_zoom; + zoom_scale = Vector2(1, 1) / zoom; Point2 old_smoothed_camera_pos = smoothed_camera_pos; _update_scroll(); smoothed_camera_pos = old_smoothed_camera_pos; @@ -103,8 +104,8 @@ Transform2D Camera2D::get_camera_transform() { if (!first) { if (anchor_mode == ANCHOR_MODE_DRAG_CENTER) { if (drag_horizontal_enabled && !Engine::get_singleton()->is_editor_hint() && !drag_horizontal_offset_changed) { - camera_pos.x = MIN(camera_pos.x, (new_camera_pos.x + screen_size.x * 0.5 * zoom.x * drag_margin[SIDE_LEFT])); - camera_pos.x = MAX(camera_pos.x, (new_camera_pos.x - screen_size.x * 0.5 * zoom.x * drag_margin[SIDE_RIGHT])); + camera_pos.x = MIN(camera_pos.x, (new_camera_pos.x + screen_size.x * 0.5 * zoom_scale.x * drag_margin[SIDE_LEFT])); + camera_pos.x = MAX(camera_pos.x, (new_camera_pos.x - screen_size.x * 0.5 * zoom_scale.x * drag_margin[SIDE_RIGHT])); } else { if (drag_horizontal_offset < 0) { camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[SIDE_RIGHT] * drag_horizontal_offset; @@ -116,8 +117,8 @@ Transform2D Camera2D::get_camera_transform() { } if (drag_vertical_enabled && !Engine::get_singleton()->is_editor_hint() && !drag_vertical_offset_changed) { - camera_pos.y = MIN(camera_pos.y, (new_camera_pos.y + screen_size.y * 0.5 * zoom.y * drag_margin[SIDE_TOP])); - camera_pos.y = MAX(camera_pos.y, (new_camera_pos.y - screen_size.y * 0.5 * zoom.y * drag_margin[SIDE_BOTTOM])); + camera_pos.y = MIN(camera_pos.y, (new_camera_pos.y + screen_size.y * 0.5 * zoom_scale.y * drag_margin[SIDE_TOP])); + camera_pos.y = MAX(camera_pos.y, (new_camera_pos.y - screen_size.y * 0.5 * zoom_scale.y * drag_margin[SIDE_BOTTOM])); } else { if (drag_vertical_offset < 0) { @@ -133,8 +134,8 @@ Transform2D Camera2D::get_camera_transform() { camera_pos = new_camera_pos; } - Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2()); - Rect2 screen_rect(-screen_offset + camera_pos, screen_size * zoom); + Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom_scale) : Point2()); + Rect2 screen_rect(-screen_offset + camera_pos, screen_size * zoom_scale); if (limit_smoothing_enabled) { if (screen_rect.position.x < limit[SIDE_LEFT]) { @@ -168,14 +169,14 @@ Transform2D Camera2D::get_camera_transform() { first = false; } - Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2()); + Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom_scale) : Point2()); real_t angle = get_global_rotation(); if (rotating) { screen_offset = screen_offset.rotated(angle); } - Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom); + Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom_scale); if (!smoothing_enabled || !limit_smoothing_enabled) { if (screen_rect.position.x < limit[SIDE_LEFT]) { @@ -202,7 +203,7 @@ Transform2D Camera2D::get_camera_transform() { camera_screen_center = screen_rect.get_center(); Transform2D xform; - xform.scale_basis(zoom); + xform.scale_basis(zoom_scale); if (rotating) { xform.set_rotation(angle); } diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 662bee3612..294a6fcb80 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -61,6 +61,7 @@ protected: RID canvas; Vector2 offset; Vector2 zoom = Vector2(1, 1); + Vector2 zoom_scale = Vector2(1, 1); AnchorMode anchor_mode = ANCHOR_MODE_DRAG_CENTER; bool rotating = false; bool current = false; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index 2716bb2e25..8cbcc9acf6 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -265,15 +265,15 @@ bool Line2D::get_antialiased() const { } void Line2D::_draw() { - if (_points.size() <= 1 || _width == 0.f) { + int len = _points.size(); + if (len <= 1 || _width == 0.f) { return; } // TODO Is this really needed? // Copy points for faster access Vector<Vector2> points; - points.resize(_points.size()); - int len = points.size(); + points.resize(len); { const Vector2 *points_read = _points.ptr(); for (int i = 0; i < len; ++i) { diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 9d26543243..dd88bda304 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -244,10 +244,9 @@ Point2 Node2D::get_global_position() const { } void Node2D::set_global_position(const Point2 &p_pos) { - Transform2D inv; CanvasItem *pi = get_parent_item(); if (pi) { - inv = pi->get_global_transform().affine_inverse(); + Transform2D inv = pi->get_global_transform().affine_inverse(); set_position(inv.xform(p_pos)); } else { set_position(p_pos); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 1fe4adb4db..f9986c2f30 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -295,14 +295,14 @@ void Polygon2D::_notification(int p_what) { } Vector<Color> colors; + colors.resize(len); + if (vertex_colors.size() == points.size()) { - colors.resize(len); const Color *color_r = vertex_colors.ptr(); for (int i = 0; i < len; i++) { colors.write[i] = color_r[i]; } } else { - colors.resize(len); for (int i = 0; i < len; i++) { colors.write[i] = color; } diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_dynamic_body_3d.cpp index 8ee777bcbf..eafb74f203 100644 --- a/scene/3d/soft_dynamic_body_3d.cpp +++ b/scene/3d/soft_dynamic_body_3d.cpp @@ -417,8 +417,8 @@ void SoftDynamicBody3D::_draw_soft_mesh() { PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid); } - if (!rendering_server_handler.is_ready(mesh_rid)) { - rendering_server_handler.prepare(mesh_rid, 0); + if (!rendering_server_handler->is_ready(mesh_rid)) { + rendering_server_handler->prepare(mesh_rid, 0); /// Necessary in order to render the mesh correctly (Soft body nodes are in global space) simulation_started = true; @@ -428,11 +428,11 @@ void SoftDynamicBody3D::_draw_soft_mesh() { _update_physics_server(); - rendering_server_handler.open(); - PhysicsServer3D::get_singleton()->soft_body_update_rendering_server(physics_rid, &rendering_server_handler); - rendering_server_handler.close(); + rendering_server_handler->open(); + PhysicsServer3D::get_singleton()->soft_body_update_rendering_server(physics_rid, rendering_server_handler); + rendering_server_handler->close(); - rendering_server_handler.commit_changes(); + rendering_server_handler->commit_changes(); } void SoftDynamicBody3D::_prepare_physics_server() { @@ -688,10 +688,12 @@ bool SoftDynamicBody3D::is_ray_pickable() const { SoftDynamicBody3D::SoftDynamicBody3D() : physics_rid(PhysicsServer3D::get_singleton()->soft_body_create()) { + rendering_server_handler = memnew(SoftDynamicBodyRenderingServerHandler); PhysicsServer3D::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); } SoftDynamicBody3D::~SoftDynamicBody3D() { + memdelete(rendering_server_handler); PhysicsServer3D::get_singleton()->free(physics_rid); } diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_dynamic_body_3d.h index c30ec701c7..e11e5c73df 100644 --- a/scene/3d/soft_dynamic_body_3d.h +++ b/scene/3d/soft_dynamic_body_3d.h @@ -36,7 +36,7 @@ class SoftDynamicBody3D; -class SoftDynamicBodyRenderingServerHandler : public RenderingServerHandler { +class SoftDynamicBodyRenderingServerHandler : public PhysicsServer3DRenderingServerHandler { friend class SoftDynamicBody3D; RID mesh; @@ -84,7 +84,7 @@ public: }; private: - SoftDynamicBodyRenderingServerHandler rendering_server_handler; + SoftDynamicBodyRenderingServerHandler *rendering_server_handler = nullptr; RID physics_rid; diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index f56e3caa4b..bda3868fbb 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -872,7 +872,7 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const { if (d == 0) { w[i] = 0; } else { - w[i] = MIN(d, 254) + 1; + w[i] = MIN(d, 254u) + 1; } } } diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 724714b93b..29a0681f9c 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -293,7 +293,7 @@ void Button::_notification(int p_what) { int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width; text_buf->set_width(clip_text ? text_clip : -1); - int text_width = clip_text ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x; + int text_width = MAX(1, clip_text ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x); if (_internal_margin[SIDE_LEFT] > 0) { text_clip -= _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("hseparation")); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index d8659b1f18..d2d1b5e9b7 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -3224,6 +3224,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size); ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_parent_area_size); ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position); + ClassDB::bind_method(D_METHOD("get_screen_position"), &Control::get_screen_position); ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect); ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect); ClassDB::bind_method(D_METHOD("set_focus_mode", "mode"), &Control::set_focus_mode); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 678229683f..e71ab64535 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -176,7 +176,7 @@ void FileDialog::update_dir() { if (dir_access->get_current_dir().is_network_share_path()) { _update_drives(false); drives->add_item(RTR("Network")); - drives->set_item_disabled(drives->get_item_count() - 1, true); + drives->set_item_disabled(-1, true); drives->select(drives->get_item_count() - 1); } else { drives->select(dir_access->get_current_drive()); @@ -919,9 +919,9 @@ void FileDialog::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir"), "set_current_dir", "get_current_dir"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file"), "set_current_file", "get_current_file"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path"), "set_current_path", "get_current_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*", PROPERTY_USAGE_NONE), "set_current_file", "get_current_file"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_path", "get_current_path"); ADD_SIGNAL(MethodInfo("file_selected", PropertyInfo(Variant::STRING, "path"))); ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"))); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 36a6b262b0..7a50efe40f 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -70,7 +70,6 @@ private: Button *makedir; Access access = ACCESS_RESOURCES; - //Button *action; VBoxContainer *vbox; FileMode mode; LineEdit *dir; diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp index 3bd21f96b2..40aca555db 100644 --- a/scene/gui/flow_container.cpp +++ b/scene/gui/flow_container.cpp @@ -39,6 +39,11 @@ struct _LineData { }; void FlowContainer::_resort() { + // Avoid resorting if invisible. + if (!is_visible_in_tree()) { + return; + } + int separation_horizontal = get_theme_constant(SNAME("hseparation")); int separation_vertical = get_theme_constant(SNAME("vseparation")); @@ -58,7 +63,7 @@ void FlowContainer::_resort() { // First pass for line wrapping and minimum size calculation. for (int i = 0; i < get_child_count(); i++) { Control *child = Object::cast_to<Control>(get_child(i)); - if (!child || !child->is_visible_in_tree()) { + if (!child || !child->is_visible()) { continue; } if (child->is_set_as_top_level()) { @@ -128,7 +133,7 @@ void FlowContainer::_resort() { for (int i = 0; i < get_child_count(); i++) { Control *child = Object::cast_to<Control>(get_child(i)); - if (!child || !child->is_visible_in_tree()) { + if (!child || !child->is_visible()) { continue; } if (child->is_set_as_top_level()) { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index ab21c747cf..1394b4192f 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1170,7 +1170,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { if (connecting) { force_connection_drag_end(); } else { - emit_signal(SNAME("popup_request"), get_screen_position() + b->get_position()); + emit_signal(SNAME("popup_request"), b->get_position()); } } } diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index e83524b06c..8c0f696a9f 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -83,6 +83,9 @@ int ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) { } void ItemList::set_item_text(int p_idx, const String &p_text) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].text = p_text; @@ -97,6 +100,9 @@ String ItemList::get_item_text(int p_idx) const { } void ItemList::set_item_text_direction(int p_idx, Control::TextDirection p_text_direction) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3); if (items[p_idx].text_direction != p_text_direction) { @@ -119,6 +125,9 @@ void ItemList::clear_item_opentype_features(int p_idx) { } void ItemList::set_item_opentype_feature(int p_idx, const String &p_name, int p_value) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); int32_t tag = TS->name_to_tag(p_name); if (!items[p_idx].opentype_features.has(tag) || (int)items[p_idx].opentype_features[tag] != p_value) { @@ -138,6 +147,9 @@ int ItemList::get_item_opentype_feature(int p_idx, const String &p_name) const { } void ItemList::set_item_language(int p_idx, const String &p_language) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); if (items[p_idx].language != p_language) { items.write[p_idx].language = p_language; @@ -152,6 +164,9 @@ String ItemList::get_item_language(int p_idx) const { } void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].tooltip_enabled = p_enabled; } @@ -162,6 +177,9 @@ bool ItemList::is_item_tooltip_enabled(int p_idx) const { } void ItemList::set_item_tooltip(int p_idx, const String &p_tooltip) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].tooltip = p_tooltip; @@ -175,6 +193,9 @@ String ItemList::get_item_tooltip(int p_idx) const { } void ItemList::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].icon = p_icon; @@ -189,6 +210,9 @@ Ref<Texture2D> ItemList::get_item_icon(int p_idx) const { } void ItemList::set_item_icon_transposed(int p_idx, const bool p_transposed) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].icon_transposed = p_transposed; @@ -203,6 +227,9 @@ bool ItemList::is_item_icon_transposed(int p_idx) const { } void ItemList::set_item_icon_region(int p_idx, const Rect2 &p_region) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].icon_region = p_region; @@ -217,6 +244,9 @@ Rect2 ItemList::get_item_icon_region(int p_idx) const { } void ItemList::set_item_icon_modulate(int p_idx, const Color &p_modulate) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].icon_modulate = p_modulate; @@ -230,6 +260,9 @@ Color ItemList::get_item_icon_modulate(int p_idx) const { } void ItemList::set_item_custom_bg_color(int p_idx, const Color &p_custom_bg_color) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].custom_bg = p_custom_bg_color; @@ -243,6 +276,9 @@ Color ItemList::get_item_custom_bg_color(int p_idx) const { } void ItemList::set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_color) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].custom_fg = p_custom_fg_color; @@ -256,6 +292,9 @@ Color ItemList::get_item_custom_fg_color(int p_idx) const { } void ItemList::set_item_tag_icon(int p_idx, const Ref<Texture2D> &p_tag_icon) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].tag_icon = p_tag_icon; @@ -270,6 +309,9 @@ Ref<Texture2D> ItemList::get_item_tag_icon(int p_idx) const { } void ItemList::set_item_selectable(int p_idx, bool p_selectable) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].selectable = p_selectable; @@ -281,6 +323,9 @@ bool ItemList::is_item_selectable(int p_idx) const { } void ItemList::set_item_disabled(int p_idx, bool p_disabled) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].disabled = p_disabled; @@ -293,6 +338,9 @@ bool ItemList::is_item_disabled(int p_idx) const { } void ItemList::set_item_metadata(int p_idx, const Variant &p_metadata) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].metadata = p_metadata; diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index b3804e73d9..37d75cea6a 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -240,6 +240,10 @@ void OptionButton::set_item_metadata(int p_idx, const Variant &p_metadata) { popup->set_item_metadata(p_idx, p_metadata); } +void OptionButton::set_item_tooltip(int p_idx, const String &p_tooltip) { + popup->set_item_tooltip(p_idx, p_tooltip); +} + void OptionButton::set_item_disabled(int p_idx, bool p_disabled) { popup->set_item_disabled(p_idx, p_disabled); } @@ -268,6 +272,10 @@ Variant OptionButton::get_item_metadata(int p_idx) const { return popup->get_item_metadata(p_idx); } +String OptionButton::get_item_tooltip(int p_idx) const { + return popup->get_item_tooltip(p_idx); +} + bool OptionButton::is_item_disabled(int p_idx) const { return popup->is_item_disabled(p_idx); } @@ -385,11 +393,13 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_item_disabled", "idx", "disabled"), &OptionButton::set_item_disabled); ClassDB::bind_method(D_METHOD("set_item_id", "idx", "id"), &OptionButton::set_item_id); ClassDB::bind_method(D_METHOD("set_item_metadata", "idx", "metadata"), &OptionButton::set_item_metadata); + ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &OptionButton::set_item_tooltip); ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &OptionButton::get_item_text); ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &OptionButton::get_item_icon); ClassDB::bind_method(D_METHOD("get_item_id", "idx"), &OptionButton::get_item_id); ClassDB::bind_method(D_METHOD("get_item_index", "id"), &OptionButton::get_item_index); ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &OptionButton::get_item_metadata); + ClassDB::bind_method(D_METHOD("get_item_tooltip", "idx"), &OptionButton::get_item_tooltip); ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &OptionButton::is_item_disabled); ClassDB::bind_method(D_METHOD("add_separator"), &OptionButton::add_separator); ClassDB::bind_method(D_METHOD("clear"), &OptionButton::clear); diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index 5352fe18a6..0a3c8cdb17 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -68,6 +68,7 @@ public: void set_item_id(int p_idx, int p_id); void set_item_metadata(int p_idx, const Variant &p_metadata); void set_item_disabled(int p_idx, bool p_disabled); + void set_item_tooltip(int p_idx, const String &p_tooltip); String get_item_text(int p_idx) const; Ref<Texture2D> get_item_icon(int p_idx) const; @@ -75,6 +76,7 @@ public: int get_item_index(int p_id) const; Variant get_item_metadata(int p_idx) const; bool is_item_disabled(int p_idx) const; + String get_item_tooltip(int p_idx) const; void set_item_count(int p_count); int get_item_count() const; diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 840c3d5c31..9fc1fb072c 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -999,9 +999,16 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, /* Methods to modify existing items. */ void PopupMenu::set_item_text(int p_idx, const String &p_text) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); + if (items[p_idx].text == p_text) { + return; + } items.write[p_idx].text = p_text; items.write[p_idx].xl_text = atr(p_text); + items.write[p_idx].dirty = true; _shape_item(p_idx); control->update(); @@ -1009,6 +1016,9 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) { } void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_text_direction) { + if (p_item < 0) { + p_item += get_item_count(); + } ERR_FAIL_INDEX(p_item, items.size()); ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3); if (items[p_item].text_direction != p_text_direction) { @@ -1019,6 +1029,9 @@ void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_tex } void PopupMenu::clear_item_opentype_features(int p_item) { + if (p_item < 0) { + p_item += get_item_count(); + } ERR_FAIL_INDEX(p_item, items.size()); items.write[p_item].opentype_features.clear(); items.write[p_item].dirty = true; @@ -1026,6 +1039,9 @@ void PopupMenu::clear_item_opentype_features(int p_item) { } void PopupMenu::set_item_opentype_feature(int p_item, const String &p_name, int p_value) { + if (p_item < 0) { + p_item += get_item_count(); + } ERR_FAIL_INDEX(p_item, items.size()); int32_t tag = TS->name_to_tag(p_name); if (!items[p_item].opentype_features.has(tag) || (int)items[p_item].opentype_features[tag] != p_value) { @@ -1036,6 +1052,9 @@ void PopupMenu::set_item_opentype_feature(int p_item, const String &p_name, int } void PopupMenu::set_item_language(int p_item, const String &p_language) { + if (p_item < 0) { + p_item += get_item_count(); + } ERR_FAIL_INDEX(p_item, items.size()); if (items[p_item].language != p_language) { items.write[p_item].language = p_language; @@ -1045,6 +1064,9 @@ void PopupMenu::set_item_language(int p_item, const String &p_language) { } void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].icon = p_icon; @@ -1053,6 +1075,9 @@ void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) { } void PopupMenu::set_item_checked(int p_idx, bool p_checked) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].checked = p_checked; @@ -1062,6 +1087,9 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) { } void PopupMenu::set_item_id(int p_idx, int p_id) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].id = p_id; @@ -1070,6 +1098,9 @@ void PopupMenu::set_item_id(int p_idx, int p_id) { } void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].accel = p_accel; items.write[p_idx].dirty = true; @@ -1079,6 +1110,9 @@ void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) { } void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].metadata = p_meta; control->update(); @@ -1086,6 +1120,9 @@ void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) { } void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].disabled = p_disabled; control->update(); @@ -1093,6 +1130,9 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) { } void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].submenu = p_submenu; control->update(); @@ -1201,6 +1241,9 @@ int PopupMenu::get_item_state(int p_idx) const { } void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].separator = p_separator; control->update(); @@ -1212,24 +1255,36 @@ bool PopupMenu::is_item_separator(int p_idx) const { } void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE; control->update(); } void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE; control->update(); } void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].tooltip = p_tooltip; control->update(); } void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); if (items[p_idx].shortcut.is_valid()) { _unref_shortcut(items[p_idx].shortcut); @@ -1246,6 +1301,9 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo } void PopupMenu::set_item_h_offset(int p_idx, int p_offset) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].h_ofs = p_offset; control->update(); @@ -1253,12 +1311,18 @@ void PopupMenu::set_item_h_offset(int p_idx, int p_offset) { } void PopupMenu::set_item_multistate(int p_idx, int p_state) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].state = p_state; control->update(); } void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) { + if (p_idx < 0) { + p_idx += get_item_count(); + } ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].shortcut_is_disabled = p_disabled; control->update(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index bad7be7d42..0a36176c98 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -902,9 +902,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o for (int i = 0; i < gl_size; i++) { Item *it = _get_item_at_pos(it_from, it_to, glyphs[i].start); int size = _find_outline_size(it, p_outline_size); - Color font_color = _find_outline_color(it, p_outline_color); + Color font_color = _find_color(it, p_base_color); + Color font_outline_color = _find_outline_color(it, p_outline_color); Color font_shadow_color = p_font_shadow_color; - if ((size <= 0 || font_color.a == 0) && (font_shadow_color.a == 0)) { + if ((size <= 0 || font_outline_color.a == 0) && (font_shadow_color.a == 0)) { gloff.x += glyphs[i].advance; continue; } @@ -950,11 +951,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o faded_visibility -= (float)(glyphs[i].start - fade->starting_index) / (float)fade->length; faded_visibility = faded_visibility < 0.0f ? 0.0f : faded_visibility; } - font_color.a = faded_visibility; + font_outline_color.a = faded_visibility; font_shadow_color.a = faded_visibility; } - bool visible = (font_color.a != 0) || (font_shadow_color.a != 0); + bool visible = (font_outline_color.a != 0) || (font_shadow_color.a != 0); for (int j = 0; j < fx_stack.size(); j++) { ItemFX *item_fx = fx_stack[j]; @@ -1024,18 +1025,20 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } // Draw glyph outlines. + const Color modulated_outline_color = font_outline_color * Color(1, 1, 1, font_color.a); + const Color modulated_shadow_color = font_shadow_color * Color(1, 1, 1, font_color.a); for (int j = 0; j < glyphs[i].repeat; j++) { if (visible) { bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (processed_glyphs_ol >= visible_glyphs)) || (trim_glyphs_rtl && (processed_glyphs_ol < total_glyphs - visible_glyphs)); if (!skip && frid != RID()) { - if (font_shadow_color.a > 0) { - TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, font_shadow_color); + if (modulated_shadow_color.a > 0) { + TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, modulated_shadow_color); } - if (font_shadow_color.a > 0 && p_shadow_outline_size > 0) { - TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, font_shadow_color); + if (modulated_shadow_color.a > 0 && p_shadow_outline_size > 0) { + TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, modulated_shadow_color); } - if (font_color.a != 0.0 && size > 0) { - TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, font_color); + if (modulated_outline_color.a != 0.0 && size > 0) { + TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, modulated_outline_color); } } processed_glyphs_ol++; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 05fda7128c..3c80e3f987 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4469,7 +4469,11 @@ int TextEdit::get_visible_line_count() const { int TextEdit::get_visible_line_count_in_range(int p_from_line, int p_to_line) const { ERR_FAIL_INDEX_V(p_from_line, text.size(), 0); ERR_FAIL_INDEX_V(p_to_line, text.size(), 0); - ERR_FAIL_COND_V(p_from_line > p_to_line, 0); + + // So we can handle inputs in whatever order + if (p_from_line > p_to_line) { + SWAP(p_from_line, p_to_line); + } /* Returns the total number of (lines + wrapped - hidden). */ if (!_is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) { diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index d2f5b52dbf..ec0821557b 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -866,7 +866,6 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_on_top", "on_top"), &CanvasItem::_set_on_top); ClassDB::bind_method(D_METHOD("_is_on_top"), &CanvasItem::_is_on_top); - //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform); ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width"), &CanvasItem::draw_line, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false)); @@ -899,6 +898,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("get_viewport_transform"), &CanvasItem::get_viewport_transform); ClassDB::bind_method(D_METHOD("get_viewport_rect"), &CanvasItem::get_viewport_rect); ClassDB::bind_method(D_METHOD("get_canvas_transform"), &CanvasItem::get_canvas_transform); + ClassDB::bind_method(D_METHOD("get_screen_transform"), &CanvasItem::get_screen_transform); ClassDB::bind_method(D_METHOD("get_local_mouse_position"), &CanvasItem::get_local_mouse_position); ClassDB::bind_method(D_METHOD("get_global_mouse_position"), &CanvasItem::get_global_mouse_position); ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasItem::get_canvas); @@ -995,12 +995,7 @@ Transform2D CanvasItem::get_viewport_transform() const { ERR_FAIL_COND_V(!is_inside_tree(), Transform2D()); if (canvas_layer) { - if (get_viewport()) { - return get_viewport()->get_final_transform() * canvas_layer->get_transform(); - } else { - return canvas_layer->get_transform(); - } - + return get_viewport()->get_final_transform() * canvas_layer->get_transform(); } else { return get_viewport()->get_final_transform() * get_viewport()->get_canvas_transform(); } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index de6aa2b139..ec33e5752e 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2033,6 +2033,17 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } } +void Viewport::_gui_cleanup_internal_state(Ref<InputEvent> p_event) { + ERR_FAIL_COND(p_event.is_null()); + + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid()) { + if (!mb->is_pressed()) { + gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask. + } + } +} + List<Control *>::Element *Viewport::_gui_add_root_control(Control *p_control) { gui.roots_order_dirty = true; return gui.roots.push_back(p_control); @@ -2695,6 +2706,9 @@ void Viewport::push_input(const Ref<InputEvent> &p_event, bool p_local_coords) { if (!is_input_handled()) { _gui_input_event(ev); + } else { + // Cleanup internal GUI state after accepting event during _input(). + _gui_cleanup_internal_state(ev); } event_count++; @@ -2768,6 +2782,14 @@ Vector2 Viewport::get_camera_rect_size() const { } void Viewport::set_disable_input(bool p_disable) { + if (p_disable == disable_input) { + return; + } + if (p_disable) { + _drop_mouse_focus(); + _drop_mouse_over(); + _gui_cancel_tooltip(); + } disable_input = p_disable; } @@ -3040,14 +3062,10 @@ Viewport *Viewport::get_parent_viewport() const { return get_parent()->get_viewport(); } -void Viewport::set_embed_subwindows_hint(bool p_embed) { +void Viewport::set_embedding_subwindows(bool p_embed) { gui.embed_subwindows_hint = p_embed; } -bool Viewport::get_embed_subwindows_hint() const { - return gui.embed_subwindows_hint; -} - bool Viewport::is_embedding_subwindows() const { return gui.embed_subwindows_hint; } @@ -3638,8 +3656,7 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_filter", "mode"), &Viewport::set_default_canvas_item_texture_filter); ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_filter"), &Viewport::get_default_canvas_item_texture_filter); - ClassDB::bind_method(D_METHOD("set_embed_subwindows_hint", "enable"), &Viewport::set_embed_subwindows_hint); - ClassDB::bind_method(D_METHOD("get_embed_subwindows_hint"), &Viewport::get_embed_subwindows_hint); + ClassDB::bind_method(D_METHOD("set_embedding_subwindows", "enable"), &Viewport::set_embedding_subwindows); ClassDB::bind_method(D_METHOD("is_embedding_subwindows"), &Viewport::is_embedding_subwindows); ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat); @@ -3721,7 +3738,7 @@ void Viewport::_bind_methods() { ADD_GROUP("GUI", "gui_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embed_subwindows_hint", "get_embed_subwindows_hint"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embedding_subwindows", "is_embedding_subwindows"); ADD_GROUP("SDF", "sdf_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize"); ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale"); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 93e42f1838..e4912f31c5 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -388,6 +388,7 @@ private: Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform); void _gui_input_event(Ref<InputEvent> p_event); + void _gui_cleanup_internal_state(Ref<InputEvent> p_event); _FORCE_INLINE_ Transform2D _get_input_pre_xform() const; @@ -600,8 +601,7 @@ public: virtual DisplayServer::WindowID get_window_id() const = 0; - void set_embed_subwindows_hint(bool p_embed); - bool get_embed_subwindows_hint() const; + void set_embedding_subwindows(bool p_embed); bool is_embedding_subwindows() const; Viewport *get_parent_viewport() const; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 61114333fb..da37228ed9 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -103,7 +103,7 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi return style; } -void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) { +void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) { scale = p_scale; // Font colors @@ -924,9 +924,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te theme->set_stylebox("normal", "RichTextLabel", make_empty_stylebox(0, 0, 0, 0)); theme->set_font("normal_font", "RichTextLabel", Ref<Font>()); - theme->set_font("bold_font", "RichTextLabel", Ref<Font>()); - theme->set_font("italics_font", "RichTextLabel", Ref<Font>()); - theme->set_font("bold_italics_font", "RichTextLabel", Ref<Font>()); + theme->set_font("bold_font", "RichTextLabel", bold_font); + theme->set_font("italics_font", "RichTextLabel", italics_font); + theme->set_font("bold_italics_font", "RichTextLabel", bold_italics_font); theme->set_font("mono_font", "RichTextLabel", Ref<Font>()); theme->set_font_size("normal_font_size", "RichTextLabel", -1); @@ -1025,6 +1025,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos Ref<StyleBox> default_style; Ref<Texture2D> default_icon; Ref<Font> default_font; + Ref<Font> bold_font; + Ref<Font> bold_italics_font; + Ref<Font> italics_font; float default_scale = CLAMP(p_scale, 0.5, 8.0); if (p_font.is_valid()) { @@ -1048,7 +1051,31 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos default_font = dynamic_font; } - fill_default_theme(t, default_font, default_icon, default_style, default_scale); + if (default_font.is_valid()) { + bold_font.instantiate(); + for (int i = 0; i < default_font->get_data_count(); i++) { + Ref<FontData> data = default_font->get_data(i)->duplicate(); + data->set_embolden(1.2); + bold_font->add_data(data); + } + + bold_italics_font.instantiate(); + for (int i = 0; i < default_font->get_data_count(); i++) { + Ref<FontData> data = default_font->get_data(i)->duplicate(); + data->set_embolden(1.2); + data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0)); + bold_italics_font->add_data(data); + } + + italics_font.instantiate(); + for (int i = 0; i < default_font->get_data_count(); i++) { + Ref<FontData> data = default_font->get_data(i)->duplicate(); + data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0)); + italics_font->add_data(data); + } + } + + fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale); Theme::set_default(t); Theme::set_fallback_base_scale(default_scale); diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index 28afd5f5e1..a9e21dda3f 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -35,7 +35,7 @@ const int default_font_size = 16; -void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); +void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa); void clear_default_theme(); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 5b57e93950..ce2a675854 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -61,6 +61,8 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const { TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter); TS->font_set_hinting(cache[p_cache_index], hinting); TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning); + TS->font_set_embolden(cache[p_cache_index], embolden); + TS->font_set_transform(cache[p_cache_index], transform); TS->font_set_oversampling(cache[p_cache_index], oversampling); } } @@ -105,6 +107,12 @@ void FontData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning); ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning); + ClassDB::bind_method(D_METHOD("set_embolden", "strength"), &FontData::set_embolden); + ClassDB::bind_method(D_METHOD("get_embolden"), &FontData::get_embolden); + + ClassDB::bind_method(D_METHOD("set_transform", "transform"), &FontData::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"), &FontData::get_transform); + ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling); ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling); @@ -209,6 +217,8 @@ void FontData::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01", PROPERTY_USAGE_STORAGE), "set_embolden", "get_embolden"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field"); ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range"); ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size"); @@ -439,6 +449,8 @@ void FontData::reset_state() { msdf_pixel_range = 14; msdf_size = 128; fixed_size = 0; + embolden = 0.f; + transform = Transform2D(); oversampling = 0.f; } @@ -1385,6 +1397,36 @@ TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const { return subpixel_positioning; } +void FontData::set_embolden(float p_strength) { + if (embolden != p_strength) { + embolden = p_strength; + for (int i = 0; i < cache.size(); i++) { + _ensure_rid(i); + TS->font_set_embolden(cache[i], embolden); + } + emit_changed(); + } +} + +float FontData::get_embolden() const { + return embolden; +} + +void FontData::set_transform(Transform2D p_transform) { + if (transform != p_transform) { + transform = p_transform; + for (int i = 0; i < cache.size(); i++) { + _ensure_rid(i); + TS->font_set_transform(cache[i], transform); + } + emit_changed(); + } +} + +Transform2D FontData::get_transform() const { + return transform; +} + void FontData::set_oversampling(real_t p_oversampling) { if (oversampling != p_oversampling) { oversampling = p_oversampling; diff --git a/scene/resources/font.h b/scene/resources/font.h index aaf0a7fe7b..0185b019f1 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -57,6 +57,8 @@ class FontData : public Resource { TextServer::Hinting hinting = TextServer::HINTING_LIGHT; TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; real_t oversampling = 0.f; + real_t embolden = 0.f; + Transform2D transform; // Cache. mutable Vector<RID> cache; @@ -122,6 +124,12 @@ public: virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel); virtual TextServer::SubpixelPositioning get_subpixel_positioning() const; + virtual void set_embolden(float p_strength); + virtual float get_embolden() const; + + virtual void set_transform(Transform2D p_transform); + virtual Transform2D get_transform() const; + virtual void set_oversampling(real_t p_oversampling); virtual real_t get_oversampling() const; diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index d9ac967699..fd6f018651 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -908,10 +908,9 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p return ERR_CANT_CREATE; } - DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); da->remove(p_path); da->rename(p_path + ".depren", p_path); - memdelete(da); return OK; } diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index 8e633a4075..54543782f6 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -71,6 +71,25 @@ float ProceduralSkyMaterial::get_sky_energy() const { return sky_energy; } +void ProceduralSkyMaterial::set_sky_cover(const Ref<Texture2D> &p_sky_cover) { + sky_cover = p_sky_cover; + RID tex_rid = p_sky_cover.is_valid() ? p_sky_cover->get_rid() : RID(); + RS::get_singleton()->material_set_param(_get_material(), "sky_cover", tex_rid); +} + +Ref<Texture2D> ProceduralSkyMaterial::get_sky_cover() const { + return sky_cover; +} + +void ProceduralSkyMaterial::set_sky_cover_modulate(const Color &p_sky_cover_modulate) { + sky_cover_modulate = p_sky_cover_modulate; + RS::get_singleton()->material_set_param(_get_material(), "sky_cover_modulate", sky_cover_modulate); +} + +Color ProceduralSkyMaterial::get_sky_cover_modulate() const { + return sky_cover_modulate; +} + void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) { ground_bottom_color = p_ground_bottom; RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color); @@ -156,6 +175,12 @@ void ProceduralSkyMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy); ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy); + ClassDB::bind_method(D_METHOD("set_sky_cover", "sky_cover"), &ProceduralSkyMaterial::set_sky_cover); + ClassDB::bind_method(D_METHOD("get_sky_cover"), &ProceduralSkyMaterial::get_sky_cover); + + ClassDB::bind_method(D_METHOD("set_sky_cover_modulate", "color"), &ProceduralSkyMaterial::set_sky_cover_modulate); + ClassDB::bind_method(D_METHOD("get_sky_cover_modulate"), &ProceduralSkyMaterial::get_sky_cover_modulate); + ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSkyMaterial::set_ground_bottom_color); ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSkyMaterial::get_ground_bottom_color); @@ -179,6 +204,8 @@ void ProceduralSkyMaterial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_horizon_color", "get_sky_horizon_color"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_cover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_sky_cover", "get_sky_cover"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_cover_modulate"), "set_sky_cover_modulate", "get_sky_cover_modulate"); ADD_GROUP("Ground", "ground_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_bottom_color", "get_ground_bottom_color"); @@ -212,6 +239,8 @@ uniform vec4 sky_top_color : hint_color = vec4(0.385, 0.454, 0.55, 1.0); uniform vec4 sky_horizon_color : hint_color = vec4(0.646, 0.656, 0.67, 1.0); uniform float sky_curve : hint_range(0, 1) = 0.15; uniform float sky_energy = 1.0; +uniform sampler2D sky_cover : hint_black_albedo; +uniform vec4 sky_cover_modulate : hint_color = vec4(1.0, 1.0, 1.0, 1.0); uniform vec4 ground_bottom_color : hint_color = vec4(0.2, 0.169, 0.133, 1.0); uniform vec4 ground_horizon_color : hint_color = vec4(0.646, 0.656, 0.67, 1.0); uniform float ground_curve : hint_range(0, 1) = 0.02; @@ -265,6 +294,9 @@ void sky() { } } + vec4 sky_cover_texture = texture(sky_cover, SKY_COORDS); + sky += (sky_cover_texture.rgb * sky_cover_modulate.rgb) * sky_cover_texture.a * sky_cover_modulate.a * sky_energy; + c = (v_angle - (PI * 0.5)) / (PI * 0.5); vec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0)); ground *= ground_energy; @@ -281,6 +313,7 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() { set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708)); set_sky_curve(0.15); set_sky_energy(1.0); + set_sky_cover_modulate(Color(1, 1, 1)); set_ground_bottom_color(Color(0.2, 0.169, 0.133)); set_ground_horizon_color(Color(0.6463, 0.6558, 0.6708)); diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h index 7f421beb8d..5c791a185a 100644 --- a/scene/resources/sky_material.h +++ b/scene/resources/sky_material.h @@ -42,6 +42,8 @@ private: Color sky_horizon_color; float sky_curve; float sky_energy; + Ref<Texture2D> sky_cover; + Color sky_cover_modulate; Color ground_bottom_color; Color ground_horizon_color; @@ -72,6 +74,12 @@ public: void set_sky_energy(float p_energy); float get_sky_energy() const; + void set_sky_cover(const Ref<Texture2D> &p_sky_cover); + Ref<Texture2D> get_sky_cover() const; + + void set_sky_cover_modulate(const Color &p_sky_cover_modulate); + Color get_sky_cover_modulate() const; + void set_ground_bottom_color(const Color &p_ground_bottom); Color get_ground_bottom_color() const; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index d541284381..3113987fbc 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -212,7 +212,7 @@ void ImageTexture::update(const Ref<Image> &p_image) { ERR_FAIL_COND_MSG(mipmaps != p_image->has_mipmaps(), "The new image mipmaps configuration must match the texture's image mipmaps configuration"); - RenderingServer::get_singleton()->texture_2d_update(texture, p_image); + RS::get_singleton()->texture_2d_update(texture, p_image); notify_property_list_changed(); emit_changed(); @@ -482,24 +482,24 @@ void CompressedTexture2D::set_path(const String &p_path, bool p_take_over) { } void CompressedTexture2D::_requested_3d(void *p_ud) { - CompressedTexture2D *st = (CompressedTexture2D *)p_ud; - Ref<CompressedTexture2D> stex(st); + CompressedTexture2D *ct = (CompressedTexture2D *)p_ud; + Ref<CompressedTexture2D> ctex(ct); ERR_FAIL_COND(!request_3d_callback); - request_3d_callback(stex); + request_3d_callback(ctex); } void CompressedTexture2D::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) { - CompressedTexture2D *st = (CompressedTexture2D *)p_ud; - Ref<CompressedTexture2D> stex(st); + CompressedTexture2D *ct = (CompressedTexture2D *)p_ud; + Ref<CompressedTexture2D> ctex(ct); ERR_FAIL_COND(!request_roughness_callback); - request_roughness_callback(stex, p_normal_path, p_roughness_channel); + request_roughness_callback(ctex, p_normal_path, p_roughness_channel); } void CompressedTexture2D::_requested_normal(void *p_ud) { - CompressedTexture2D *st = (CompressedTexture2D *)p_ud; - Ref<CompressedTexture2D> stex(st); + CompressedTexture2D *ct = (CompressedTexture2D *)p_ud; + Ref<CompressedTexture2D> ctex(ct); ERR_FAIL_COND(!request_normal_callback); - request_normal_callback(stex); + request_normal_callback(ctex); } CompressedTexture2D::TextureFormatRequestCallback CompressedTexture2D::request_3d_callback = nullptr; @@ -522,14 +522,14 @@ Error CompressedTexture2D::_load_data(const String &p_path, int &r_width, int &r f->get_buffer(header, 4); if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != '2') { memdelete(f); - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is corrupt (Bad header)."); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is corrupt (Bad header)."); } uint32_t version = f->get_32(); if (version > FORMAT_VERSION) { memdelete(f); - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new."); } r_width = f->get_32(); r_height = f->get_32(); @@ -973,11 +973,11 @@ Error CompressedTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> & f->get_buffer(header, 4); ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L', ERR_FILE_UNRECOGNIZED); - //stored as stream textures (used for lossless and lossy compression) + //stored as compressed textures (used for lossless and lossy compression) uint32_t version = f->get_32(); if (version > FORMAT_VERSION) { - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new."); } r_depth = f->get_32(); //depth @@ -1129,7 +1129,7 @@ RES ResourceFormatLoaderCompressedTexture3D::load(const String &p_path, const St } void ResourceFormatLoaderCompressedTexture3D::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("stex3d"); + p_extensions->push_back("ctex3d"); } bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type) const { @@ -1137,7 +1137,7 @@ bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type) } String ResourceFormatLoaderCompressedTexture3D::get_resource_type(const String &p_path) const { - if (p_path.get_extension().to_lower() == "stex3d") { + if (p_path.get_extension().to_lower() == "ctex3d") { return "CompressedTexture3D"; } return ""; @@ -2792,13 +2792,13 @@ Error CompressedTextureLayered::_load_data(const String &p_path, Vector<Ref<Imag uint8_t header[4]; f->get_buffer(header, 4); if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L') { - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture layered file is corrupt (Bad header)."); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture layered file is corrupt (Bad header)."); } uint32_t version = f->get_32(); if (version > FORMAT_VERSION) { - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new."); } uint32_t layer_count = f->get_32(); //layer count @@ -2939,26 +2939,26 @@ CompressedTextureLayered::~CompressedTextureLayered() { ///////////////////////////////////////////////// RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref<CompressedTextureLayered> st; - if (p_path.get_extension().to_lower() == "stexarray") { - Ref<CompressedTexture2DArray> s; - s.instantiate(); - st = s; - } else if (p_path.get_extension().to_lower() == "scube") { - Ref<CompressedCubemap> s; - s.instantiate(); - st = s; - } else if (p_path.get_extension().to_lower() == "scubearray") { - Ref<CompressedCubemapArray> s; - s.instantiate(); - st = s; + Ref<CompressedTextureLayered> ct; + if (p_path.get_extension().to_lower() == "ctexarray") { + Ref<CompressedTexture2DArray> c; + c.instantiate(); + ct = c; + } else if (p_path.get_extension().to_lower() == "ccube") { + Ref<CompressedCubemap> c; + c.instantiate(); + ct = c; + } else if (p_path.get_extension().to_lower() == "ccubearray") { + Ref<CompressedCubemapArray> c; + c.instantiate(); + ct = c; } else { if (r_error) { *r_error = ERR_FILE_UNRECOGNIZED; } return RES(); } - Error err = st->load(p_path); + Error err = ct->load(p_path); if (r_error) { *r_error = err; } @@ -2966,13 +2966,13 @@ RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, con return RES(); } - return st; + return ct; } void ResourceFormatLoaderCompressedTextureLayered::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("stexarray"); - p_extensions->push_back("scube"); - p_extensions->push_back("scubearray"); + p_extensions->push_back("ctexarray"); + p_extensions->push_back("ccube"); + p_extensions->push_back("ccubearray"); } bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_type) const { @@ -2980,13 +2980,13 @@ bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_ } String ResourceFormatLoaderCompressedTextureLayered::get_resource_type(const String &p_path) const { - if (p_path.get_extension().to_lower() == "stexarray") { + if (p_path.get_extension().to_lower() == "ctexarray") { return "CompressedTexture2DArray"; } - if (p_path.get_extension().to_lower() == "scube") { + if (p_path.get_extension().to_lower() == "ccube") { return "CompressedCubemap"; } - if (p_path.get_extension().to_lower() == "scubearray") { + if (p_path.get_extension().to_lower() == "ccubearray") { return "CompressedCubemapArray"; } return ""; diff --git a/servers/SCsub b/servers/SCsub index 2cd4741d56..66a1b9b26f 100644 --- a/servers/SCsub +++ b/servers/SCsub @@ -13,6 +13,7 @@ SConscript("rendering/SCsub") SConscript("audio/SCsub") SConscript("text/SCsub") SConscript("debugger/SCsub") +SConscript("extensions/SCsub") lib = env.add_library("servers", env.servers_sources) diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index f74a8fad23..3853ff4fdc 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -33,7 +33,7 @@ #include "servers/display_server.h" -#include "servers/rendering/rasterizer_dummy.h" +#include "servers/rendering/dummy/rasterizer_dummy.h" class DisplayServerHeadless : public DisplayServer { private: diff --git a/servers/extensions/SCsub b/servers/extensions/SCsub new file mode 100644 index 0000000000..eac66ea283 --- /dev/null +++ b/servers/extensions/SCsub @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +Import("env") + +import make_wrappers +from platform_methods import run_in_subprocess + +env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", run_in_subprocess(make_wrappers.run)) + +env_object = env.Clone() + +env_object.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/extensions/make_wrappers.py b/servers/extensions/make_wrappers.py new file mode 100644 index 0000000000..862d313fba --- /dev/null +++ b/servers/extensions/make_wrappers.py @@ -0,0 +1,93 @@ +proto = """ +#define EXBIND$VER($RETTYPE m_name$ARG) \\ +GDVIRTUAL$VER($RETTYPE_##m_name$ARG)\\ +virtual $RETVAL m_name($FUNCARGS) $CONST override { \\ + $RETPRE\\ + GDVIRTUAL_REQUIRED_CALL(_##m_name$CALLARGS$RETREF);\\ + $RETPOST\\ +} +""" + + +def generate_version(argcount, const=False, returns=False): + s = proto + sproto = str(argcount) + method_info = "" + if returns: + sproto += "R" + s = s.replace("$RETTYPE", "m_ret, ") + s = s.replace("$RETVAL", "m_ret") + s = s.replace("$RETPRE", "m_ret ret; ZeroInitializer<m_ret>::initialize(ret);\\\n") + s = s.replace("$RETPOST", "return ret;\\\n") + + else: + s = s.replace("$RETTYPE", "") + s = s.replace("$RETVAL", "void") + s = s.replace("$RETPRE", "") + s = s.replace("$RETPOST", "return;") + + if const: + sproto += "C" + s = s.replace("$CONST", "const") + else: + s = s.replace("$CONST", "") + + s = s.replace("$VER", sproto) + argtext = "" + funcargs = "" + callargs = "" + + for i in range(argcount): + if i > 0: + funcargs += ", " + + argtext += ", m_type" + str(i + 1) + funcargs += "m_type" + str(i + 1) + " arg" + str(i + 1) + callargs += ", arg" + str(i + 1) + + if argcount: + s = s.replace("$ARG", argtext) + s = s.replace("$FUNCARGS", funcargs) + s = s.replace("$CALLARGS", callargs) + else: + s = s.replace("$ARG", "") + s = s.replace("$FUNCARGS", funcargs) + s = s.replace("$CALLARGS", callargs) + + if returns: + s = s.replace("$RETREF", ", ret") + else: + s = s.replace("$RETREF", "") + + return s + + +def run(target, source, env): + + max_versions = 12 + + txt = """ +#ifndef GDEXTENSION_WRAPPERS_GEN_H +#define GDEXTENSION_WRAPPERS_GEN_H + + +""" + + for i in range(max_versions + 1): + + txt += "/* " + str(i) + " Arguments */\n\n" + txt += generate_version(i, False, False) + txt += generate_version(i, False, True) + txt += generate_version(i, True, False) + txt += generate_version(i, True, True) + + txt += "#endif" + + with open(target[0], "w") as f: + f.write(txt) + + +if __name__ == "__main__": + from platform_methods import subprocess_main + + subprocess_main(globals()) diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp new file mode 100644 index 0000000000..b2a9273538 --- /dev/null +++ b/servers/extensions/physics_server_3d_extension.cpp @@ -0,0 +1,322 @@ +/*************************************************************************/ +/* physics_server_3d_extension.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_server_3d_extension.h" + +bool PhysicsDirectSpaceState3DExtension::is_body_excluded_from_query(const RID &p_body) const { + return exclude && exclude->has(p_body); +} + +thread_local const Set<RID> *PhysicsDirectSpaceState3DExtension::exclude = nullptr; + +void PhysicsDirectSpaceState3DExtension::_bind_methods() { + GDVIRTUAL_BIND(_intersect_ray, "from", "to", "collision_mask", "collide_with_bodies", "collide_with_areas", "hit_from_inside", "hit_back_faces", "result"); + GDVIRTUAL_BIND(_intersect_point, "position", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results"); + GDVIRTUAL_BIND(_intersect_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "result_count", "max_results"); + GDVIRTUAL_BIND(_cast_motion, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "closest_safe", "closest_unsafe", "info"); + GDVIRTUAL_BIND(_collide_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results", "result_count"); + GDVIRTUAL_BIND(_rest_info, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "rest_info"); + GDVIRTUAL_BIND(_get_closest_point_to_object_volume, "object", "point"); +} + +PhysicsDirectSpaceState3DExtension::PhysicsDirectSpaceState3DExtension() { +} + +void PhysicsDirectBodyState3DExtension::_bind_methods() { + GDVIRTUAL_BIND(_get_total_gravity); + GDVIRTUAL_BIND(_get_total_linear_damp); + GDVIRTUAL_BIND(_get_total_angular_damp); + + GDVIRTUAL_BIND(_get_center_of_mass); + GDVIRTUAL_BIND(_get_center_of_mass_local); + GDVIRTUAL_BIND(_get_principal_inertia_axes); + + GDVIRTUAL_BIND(_get_inverse_mass); + GDVIRTUAL_BIND(_get_inverse_inertia); + + GDVIRTUAL_BIND(_set_linear_velocity, "velocity"); + GDVIRTUAL_BIND(_get_linear_velocity); + + GDVIRTUAL_BIND(_set_angular_velocity, "velocity"); + GDVIRTUAL_BIND(_get_angular_velocity); + + GDVIRTUAL_BIND(_set_transform, "transform"); + GDVIRTUAL_BIND(_get_transform); + + GDVIRTUAL_BIND(_get_velocity_at_local_position, "local_position"); + + GDVIRTUAL_BIND(_apply_central_impulse, "impulse"); + GDVIRTUAL_BIND(_apply_impulse, "impulse", "position"); + GDVIRTUAL_BIND(_apply_torque_impulse, "impulse"); + + GDVIRTUAL_BIND(_apply_central_force, "force"); + GDVIRTUAL_BIND(_apply_force, "force", "position"); + GDVIRTUAL_BIND(_apply_torque, "torque"); + + GDVIRTUAL_BIND(_add_constant_central_force, "force"); + GDVIRTUAL_BIND(_add_constant_force, "force", "position"); + GDVIRTUAL_BIND(_add_constant_torque, "torque"); + + GDVIRTUAL_BIND(_set_constant_force, "force"); + GDVIRTUAL_BIND(_get_constant_force); + + GDVIRTUAL_BIND(_set_constant_torque, "torque"); + GDVIRTUAL_BIND(_get_constant_torque); + + GDVIRTUAL_BIND(_set_sleep_state, "enabled"); + GDVIRTUAL_BIND(_is_sleeping); + + GDVIRTUAL_BIND(_get_contact_count); + + GDVIRTUAL_BIND(_get_contact_local_position, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_local_normal, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_impulse, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_local_shape, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_position, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_id, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_object, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_shape, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_velocity_at_position, "contact_idx"); + GDVIRTUAL_BIND(_get_step); + GDVIRTUAL_BIND(_integrate_forces); + GDVIRTUAL_BIND(_get_space_state); +} + +PhysicsDirectBodyState3DExtension::PhysicsDirectBodyState3DExtension() { +} + +thread_local const Set<RID> *PhysicsServer3DExtension::exclude_bodies = nullptr; +thread_local const Set<ObjectID> *PhysicsServer3DExtension::exclude_objects = nullptr; + +bool PhysicsServer3DExtension::body_test_motion_is_excluding_body(RID p_body) const { + return exclude_bodies && exclude_bodies->has(p_body); +} + +bool PhysicsServer3DExtension::body_test_motion_is_excluding_object(ObjectID p_object) const { + return exclude_objects && exclude_objects->has(p_object); +} + +void PhysicsServer3DExtension::_bind_methods() { + GDVIRTUAL_BIND(_world_boundary_shape_create); + GDVIRTUAL_BIND(_separation_ray_shape_create); + GDVIRTUAL_BIND(_sphere_shape_create); + GDVIRTUAL_BIND(_box_shape_create); + GDVIRTUAL_BIND(_capsule_shape_create); + GDVIRTUAL_BIND(_cylinder_shape_create); + GDVIRTUAL_BIND(_convex_polygon_shape_create); + GDVIRTUAL_BIND(_concave_polygon_shape_create); + GDVIRTUAL_BIND(_heightmap_shape_create); + GDVIRTUAL_BIND(_custom_shape_create); + + GDVIRTUAL_BIND(_shape_set_data, "shape", "data"); + + GDVIRTUAL_BIND(_shape_get_type, "shape"); + GDVIRTUAL_BIND(_shape_get_data, "shape"); + + GDVIRTUAL_BIND(_space_create); + GDVIRTUAL_BIND(_space_set_active, "space", "active"); + GDVIRTUAL_BIND(_space_is_active, "space"); + GDVIRTUAL_BIND(_space_set_param, "space", "param", "value"); + GDVIRTUAL_BIND(_space_get_param, "space", "param"); + GDVIRTUAL_BIND(_space_get_direct_state, "space"); + + GDVIRTUAL_BIND(_area_create); + GDVIRTUAL_BIND(_area_set_space, "area", "space"); + GDVIRTUAL_BIND(_area_get_space, "area"); + + GDVIRTUAL_BIND(_area_add_shape, "area", "shape", "transform", "disabled"); + GDVIRTUAL_BIND(_area_set_shape, "area", "shape_idx", "shape"); + GDVIRTUAL_BIND(_area_set_shape_transform, "area", "shape_idx", "transform"); + GDVIRTUAL_BIND(_area_set_shape_disabled, "area", "shape_idx", "disabled"); + + GDVIRTUAL_BIND(_area_get_shape_count, "area"); + GDVIRTUAL_BIND(_area_get_shape, "area", "shape_idx"); + GDVIRTUAL_BIND(_area_get_shape_transform, "area", "shape_idx"); + + GDVIRTUAL_BIND(_area_remove_shape, "area", "shape_idx"); + GDVIRTUAL_BIND(_area_clear_shapes, "area"); + + GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer"); + GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask"); + + GDVIRTUAL_BIND(_area_set_param, "area", "param", "value"); + GDVIRTUAL_BIND(_area_set_transform, "area", "transform"); + + GDVIRTUAL_BIND(_area_get_param, "area", "param"); + GDVIRTUAL_BIND(_area_get_transform, "area"); + + GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id"); + GDVIRTUAL_BIND(_area_get_object_instance_id, "area"); + + GDVIRTUAL_BIND(_area_set_monitor_callback, "area", "callback"); + GDVIRTUAL_BIND(_area_set_area_monitor_callback, "area", "callback"); + GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable"); + + GDVIRTUAL_BIND(_area_set_ray_pickable, "area", "enable"); + + GDVIRTUAL_BIND(_body_create); + + GDVIRTUAL_BIND(_body_set_space, "body", "space"); + GDVIRTUAL_BIND(_body_get_space, "body"); + + GDVIRTUAL_BIND(_body_set_mode, "body", "mode"); + GDVIRTUAL_BIND(_body_get_mode, "body"); + + GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer"); + GDVIRTUAL_BIND(_body_get_collision_layer, "body"); + + GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask"); + GDVIRTUAL_BIND(_body_get_collision_mask, "body"); + + GDVIRTUAL_BIND(_body_add_shape, "body", "shape", "transform", "disabled"); + GDVIRTUAL_BIND(_body_set_shape, "body", "shape_idx", "shape"); + GDVIRTUAL_BIND(_body_set_shape_transform, "body", "shape_idx", "transform"); + GDVIRTUAL_BIND(_body_set_shape_disabled, "body", "shape_idx", "disabled"); + + GDVIRTUAL_BIND(_body_get_shape_count, "body"); + GDVIRTUAL_BIND(_body_get_shape, "body", "shape_idx"); + GDVIRTUAL_BIND(_body_get_shape_transform, "body", "shape_idx"); + + GDVIRTUAL_BIND(_body_remove_shape, "body", "shape_idx"); + GDVIRTUAL_BIND(_body_clear_shapes, "body"); + + GDVIRTUAL_BIND(_body_attach_object_instance_id, "body", "id"); + GDVIRTUAL_BIND(_body_get_object_instance_id, "body"); + + GDVIRTUAL_BIND(_body_set_enable_continuous_collision_detection, "body", "enable"); + GDVIRTUAL_BIND(_body_is_continuous_collision_detection_enabled, "body"); + + GDVIRTUAL_BIND(_body_set_param, "body", "param", "value"); + GDVIRTUAL_BIND(_body_get_param, "body", "param"); + + GDVIRTUAL_BIND(_body_reset_mass_properties, "body"); + + GDVIRTUAL_BIND(_body_set_state, "body", "state", "value"); + GDVIRTUAL_BIND(_body_get_state, "body", "state"); + + GDVIRTUAL_BIND(_body_apply_central_impulse, "body", "impulse"); + GDVIRTUAL_BIND(_body_apply_impulse, "body", "impulse", "position"); + GDVIRTUAL_BIND(_body_apply_torque_impulse, "body", "impulse"); + + GDVIRTUAL_BIND(_body_apply_central_force, "body", "force"); + GDVIRTUAL_BIND(_body_apply_force, "body", "force", "position"); + GDVIRTUAL_BIND(_body_apply_torque, "body", "torque"); + + GDVIRTUAL_BIND(_body_add_constant_central_force, "body", "force"); + GDVIRTUAL_BIND(_body_add_constant_force, "body", "force", "position"); + GDVIRTUAL_BIND(_body_add_constant_torque, "body", "torque"); + + GDVIRTUAL_BIND(_body_set_constant_force, "body", "force"); + GDVIRTUAL_BIND(_body_get_constant_force, "body"); + + GDVIRTUAL_BIND(_body_set_constant_torque, "body", "torque"); + GDVIRTUAL_BIND(_body_get_constant_torque, "body"); + + GDVIRTUAL_BIND(_body_set_axis_velocity, "body", "axis_velocity"); + + GDVIRTUAL_BIND(_body_set_axis_lock, "body", "axis", "lock"); + GDVIRTUAL_BIND(_body_is_axis_locked, "body", "axis"); + + GDVIRTUAL_BIND(_body_add_collision_exception, "body", "excepted_body"); + GDVIRTUAL_BIND(_body_remove_collision_exception, "body", "excepted_body"); + + GDVIRTUAL_BIND(_body_set_max_contacts_reported, "body", "amount"); + GDVIRTUAL_BIND(_body_get_max_contacts_reported, "body"); + + GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable"); + GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body"); + + GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata"); + + GDVIRTUAL_BIND(_body_set_ray_pickable, "body", "enable"); + + GDVIRTUAL_BIND(_body_test_motion, "body", "from", "motion", "margin", "max_collisions", "collide_separation_ray", "result"); + + GDVIRTUAL_BIND(_body_get_direct_state, "body"); + + GDVIRTUAL_BIND(_soft_body_get_bounds, "body"); + + GDVIRTUAL_BIND(_joint_create); + GDVIRTUAL_BIND(_joint_clear, "joint"); + + GDVIRTUAL_BIND(_joint_make_pin, "joint", "body_A", "local_A", "body_B", "local_B"); + GDVIRTUAL_BIND(_pin_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_pin_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_pin_joint_set_local_a, "joint", "local_A"); + GDVIRTUAL_BIND(_pin_joint_get_local_a, "joint"); + + GDVIRTUAL_BIND(_pin_joint_set_local_b, "joint", "local_B"); + GDVIRTUAL_BIND(_pin_joint_get_local_b, "joint"); + + GDVIRTUAL_BIND(_joint_make_hinge, "joint", "body_A", "hinge_A", "body_B", "hinge_B"); + + GDVIRTUAL_BIND(_hinge_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_hinge_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_hinge_joint_set_flag, "joint", "flag", "enabled"); + GDVIRTUAL_BIND(_hinge_joint_get_flag, "joint", "flag"); + + GDVIRTUAL_BIND(_joint_make_slider, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"); + + GDVIRTUAL_BIND(_slider_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_slider_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_joint_make_cone_twist, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"); + + GDVIRTUAL_BIND(_cone_twist_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_cone_twist_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_joint_get_type, "joint"); + + GDVIRTUAL_BIND(_joint_set_solver_priority, "joint", "priority"); + GDVIRTUAL_BIND(_joint_get_solver_priority, "joint"); + + GDVIRTUAL_BIND(_joint_make_generic_6dof, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"); + + GDVIRTUAL_BIND(_generic_6dof_joint_set_param, "joint", "axis", "param", "value"); + GDVIRTUAL_BIND(_generic_6dof_joint_get_param, "joint", "axis", "param"); + + GDVIRTUAL_BIND(_generic_6dof_joint_set_flag, "joint", "axis", "flag", "enable"); + GDVIRTUAL_BIND(_generic_6dof_joint_get_flag, "joint", "axis", "flag"); + + GDVIRTUAL_BIND(_free_rid, "rid"); + + GDVIRTUAL_BIND(_set_active, "active"); + + GDVIRTUAL_BIND(_get_process_info, "process_info"); +} + +PhysicsServer3DExtension::PhysicsServer3DExtension() { +} + +PhysicsServer3DExtension::~PhysicsServer3DExtension() { +} diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h new file mode 100644 index 0000000000..b40ab8a295 --- /dev/null +++ b/servers/extensions/physics_server_3d_extension.h @@ -0,0 +1,548 @@ +/*************************************************************************/ +/* physics_server_3d_extension.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_SERVER_3D_EXTENSION_H +#define PHYSICS_SERVER_3D_EXTENSION_H + +#include "core/object/script_language.h" +#include "core/variant/native_ptr.h" +#include "core/variant/type_info.h" +#include "core/variant/typed_array.h" +#include "servers/extensions/ext_wrappers.gen.inc" +#include "servers/physics_server_3d.h" + +class PhysicsDirectBodyState3DExtension : public PhysicsDirectBodyState3D { + GDCLASS(PhysicsDirectBodyState3DExtension, PhysicsDirectBodyState3D); + +protected: + static void _bind_methods(); + +public: + // The warning is valid, but unavoidable. If the function is not overriden it will error anyway. + + EXBIND0RC(Vector3, get_total_gravity) + EXBIND0RC(real_t, get_total_angular_damp) + EXBIND0RC(real_t, get_total_linear_damp) + + EXBIND0RC(Vector3, get_center_of_mass) + EXBIND0RC(Vector3, get_center_of_mass_local) + EXBIND0RC(Basis, get_principal_inertia_axes) + EXBIND0RC(real_t, get_inverse_mass) + EXBIND0RC(Vector3, get_inverse_inertia) + EXBIND0RC(Basis, get_inverse_inertia_tensor) + + EXBIND1(set_linear_velocity, const Vector3 &) + EXBIND0RC(Vector3, get_linear_velocity) + + EXBIND1(set_angular_velocity, const Vector3 &) + EXBIND0RC(Vector3, get_angular_velocity) + + EXBIND1(set_transform, const Transform3D &) + EXBIND0RC(Transform3D, get_transform) + + EXBIND1RC(Vector3, get_velocity_at_local_position, const Vector3 &) + + EXBIND1(apply_central_impulse, const Vector3 &) + EXBIND2(apply_impulse, const Vector3 &, const Vector3 &) + EXBIND1(apply_torque_impulse, const Vector3 &) + + EXBIND1(apply_central_force, const Vector3 &) + EXBIND2(apply_force, const Vector3 &, const Vector3 &) + EXBIND1(apply_torque, const Vector3 &) + + EXBIND1(add_constant_central_force, const Vector3 &) + EXBIND2(add_constant_force, const Vector3 &, const Vector3 &) + EXBIND1(add_constant_torque, const Vector3 &) + + EXBIND1(set_constant_force, const Vector3 &) + EXBIND0RC(Vector3, get_constant_force) + + EXBIND1(set_constant_torque, const Vector3 &) + EXBIND0RC(Vector3, get_constant_torque) + + EXBIND1(set_sleep_state, bool) + EXBIND0RC(bool, is_sleeping) + + EXBIND0RC(int, get_contact_count) + + EXBIND1RC(Vector3, get_contact_local_position, int) + EXBIND1RC(Vector3, get_contact_local_normal, int) + EXBIND1RC(real_t, get_contact_impulse, int) + EXBIND1RC(int, get_contact_local_shape, int) + EXBIND1RC(RID, get_contact_collider, int) + EXBIND1RC(Vector3, get_contact_collider_position, int) + EXBIND1RC(ObjectID, get_contact_collider_id, int) + EXBIND1RC(Object *, get_contact_collider_object, int) + EXBIND1RC(int, get_contact_collider_shape, int) + EXBIND1RC(Vector3, get_contact_collider_velocity_at_position, int) + + EXBIND0RC(real_t, get_step) + + EXBIND0(integrate_forces) + EXBIND0R(PhysicsDirectSpaceState3D *, get_space_state) + + PhysicsDirectBodyState3DExtension(); +}; + +typedef PhysicsDirectSpaceState3D::RayResult PhysicsServer3DExtensionRayResult; +typedef PhysicsDirectSpaceState3D::ShapeResult PhysicsServer3DExtensionShapeResult; +typedef PhysicsDirectSpaceState3D::ShapeRestInfo PhysicsServer3DExtensionShapeRestInfo; + +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionRayResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionShapeResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionShapeRestInfo) + +class PhysicsDirectSpaceState3DExtension : public PhysicsDirectSpaceState3D { + GDCLASS(PhysicsDirectSpaceState3DExtension, PhysicsDirectSpaceState3D); + + thread_local static const Set<RID> *exclude; + +protected: + static void _bind_methods(); + bool is_body_excluded_from_query(const RID &p_body) const; + + GDVIRTUAL8R(bool, _intersect_ray, const Vector3 &, const Vector3 &, uint32_t, bool, bool, bool, bool, GDNativePtr<PhysicsServer3DExtensionRayResult>) + GDVIRTUAL6R(int, _intersect_point, const Vector3 &, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeResult>, int) + GDVIRTUAL9R(int, _intersect_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeResult>, int) + GDVIRTUAL10R(bool, _cast_motion, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<real_t>, GDNativePtr<real_t>, GDNativePtr<PhysicsServer3DExtensionShapeRestInfo>) + GDVIRTUAL10R(bool, _collide_shape, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<Vector3>, int, GDNativePtr<int>) + GDVIRTUAL8R(bool, _rest_info, RID, const Transform3D &, const Vector3 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer3DExtensionShapeRestInfo>) + GDVIRTUAL2RC(Vector3, _get_closest_point_to_object_volume, RID, const Vector3 &) + +public: + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_intersect_ray, p_parameters.from, p_parameters.to, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, p_parameters.hit_from_inside, p_parameters.hit_back_faces, &r_result, ret); + exclude = nullptr; + return ret; + } + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override { + exclude = &p_parameters.exclude; + int ret = false; + GDVIRTUAL_REQUIRED_CALL(_intersect_point, p_parameters.position, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret); + exclude = nullptr; + return ret; + } + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override { + exclude = &p_parameters.exclude; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_intersect_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret); + exclude = nullptr; + return ret; + } + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_cast_motion, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, &p_closest_safe, &p_closest_unsafe, r_info, ret); + exclude = nullptr; + return ret; + } + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_collide_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, &r_result_count, ret); + exclude = nullptr; + return ret; + } + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_rest_info, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_info, ret); + exclude = nullptr; + return ret; + } + + virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override { + Vector3 ret; + GDVIRTUAL_REQUIRED_CALL(_get_closest_point_to_object_volume, p_object, p_point, ret); + return ret; + } + + PhysicsDirectSpaceState3DExtension(); +}; + +typedef PhysicsServer3D::MotionCollision PhysicsServer3DExtensionMotionCollision; +typedef PhysicsServer3D::MotionResult PhysicsServer3DExtensionMotionResult; + +struct PhysicsServer3DExtensionStateCallback { + void *instance; + void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state); +}; + +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionCollision) +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionStateCallback) + +class PhysicsServer3DExtension : public PhysicsServer3D { + GDCLASS(PhysicsServer3DExtension, PhysicsServer3D); + +protected: + static void _bind_methods(); + +public: + // The warning is valid, but unavoidable. If the function is not overriden it will error anyway. + + EXBIND0R(RID, world_boundary_shape_create) + EXBIND0R(RID, separation_ray_shape_create) + EXBIND0R(RID, sphere_shape_create) + EXBIND0R(RID, box_shape_create) + EXBIND0R(RID, capsule_shape_create) + EXBIND0R(RID, cylinder_shape_create) + EXBIND0R(RID, convex_polygon_shape_create) + EXBIND0R(RID, concave_polygon_shape_create) + EXBIND0R(RID, heightmap_shape_create) + EXBIND0R(RID, custom_shape_create) + + EXBIND2(shape_set_data, RID, const Variant &) + EXBIND2(shape_set_custom_solver_bias, RID, real_t) + + EXBIND2(shape_set_margin, RID, real_t) + EXBIND1RC(real_t, shape_get_margin, RID) + + EXBIND1RC(ShapeType, shape_get_type, RID) + EXBIND1RC(Variant, shape_get_data, RID) + EXBIND1RC(real_t, shape_get_custom_solver_bias, RID) + + /* SPACE API */ + + EXBIND0R(RID, space_create) + EXBIND2(space_set_active, RID, bool) + EXBIND1RC(bool, space_is_active, RID) + + EXBIND3(space_set_param, RID, SpaceParameter, real_t) + EXBIND2RC(real_t, space_get_param, RID, SpaceParameter) + + EXBIND1R(PhysicsDirectSpaceState3D *, space_get_direct_state, RID) + + EXBIND2(space_set_debug_contacts, RID, int) + EXBIND1RC(Vector<Vector3>, space_get_contacts, RID) + EXBIND1RC(int, space_get_contact_count, RID) + + /* AREA API */ + + //EXBIND0RID(area); + EXBIND0R(RID, area_create) + + EXBIND2(area_set_space, RID, RID) + EXBIND1RC(RID, area_get_space, RID) + + EXBIND4(area_add_shape, RID, RID, const Transform3D &, bool) + EXBIND3(area_set_shape, RID, int, RID) + EXBIND3(area_set_shape_transform, RID, int, const Transform3D &) + EXBIND3(area_set_shape_disabled, RID, int, bool) + + EXBIND1RC(int, area_get_shape_count, RID) + EXBIND2RC(RID, area_get_shape, RID, int) + EXBIND2RC(Transform3D, area_get_shape_transform, RID, int) + EXBIND2(area_remove_shape, RID, int) + EXBIND1(area_clear_shapes, RID) + + EXBIND2(area_attach_object_instance_id, RID, ObjectID) + EXBIND1RC(ObjectID, area_get_object_instance_id, RID) + + EXBIND3(area_set_param, RID, AreaParameter, const Variant &) + EXBIND2(area_set_transform, RID, const Transform3D &) + + EXBIND2RC(Variant, area_get_param, RID, AreaParameter) + EXBIND1RC(Transform3D, area_get_transform, RID) + + EXBIND2(area_set_collision_mask, RID, uint32_t) + EXBIND2(area_set_collision_layer, RID, uint32_t) + + EXBIND2(area_set_monitorable, RID, bool) + EXBIND2(area_set_ray_pickable, RID, bool) + + EXBIND2(area_set_monitor_callback, RID, const Callable &) + EXBIND2(area_set_area_monitor_callback, RID, const Callable &) + + /* BODY API */ + + //EXBIND2RID(body,BodyMode,bool); + EXBIND0R(RID, body_create) + + EXBIND2(body_set_space, RID, RID) + EXBIND1RC(RID, body_get_space, RID) + + EXBIND2(body_set_mode, RID, BodyMode) + EXBIND1RC(BodyMode, body_get_mode, RID) + + EXBIND4(body_add_shape, RID, RID, const Transform3D &, bool) + EXBIND3(body_set_shape, RID, int, RID) + EXBIND3(body_set_shape_transform, RID, int, const Transform3D &) + + EXBIND1RC(int, body_get_shape_count, RID) + EXBIND2RC(Transform3D, body_get_shape_transform, RID, int) + EXBIND2RC(RID, body_get_shape, RID, int) + + EXBIND3(body_set_shape_disabled, RID, int, bool) + + EXBIND2(body_remove_shape, RID, int) + EXBIND1(body_clear_shapes, RID) + + EXBIND2(body_attach_object_instance_id, RID, ObjectID) + EXBIND1RC(ObjectID, body_get_object_instance_id, RID) + + EXBIND2(body_set_enable_continuous_collision_detection, RID, bool) + EXBIND1RC(bool, body_is_continuous_collision_detection_enabled, RID) + + EXBIND2(body_set_collision_layer, RID, uint32_t) + EXBIND1RC(uint32_t, body_get_collision_layer, RID) + + EXBIND2(body_set_collision_mask, RID, uint32_t) + EXBIND1RC(uint32_t, body_get_collision_mask, RID) + + EXBIND2(body_set_user_flags, RID, uint32_t) + EXBIND1RC(uint32_t, body_get_user_flags, RID) + + EXBIND3(body_set_param, RID, BodyParameter, const Variant &) + EXBIND2RC(Variant, body_get_param, RID, BodyParameter) + + EXBIND1(body_reset_mass_properties, RID) + + EXBIND3(body_set_state, RID, BodyState, const Variant &) + EXBIND2RC(Variant, body_get_state, RID, BodyState) + + EXBIND2(body_apply_torque_impulse, RID, const Vector3 &) + EXBIND2(body_apply_central_impulse, RID, const Vector3 &) + EXBIND3(body_apply_impulse, RID, const Vector3 &, const Vector3 &) + + EXBIND2(body_apply_central_force, RID, const Vector3 &) + EXBIND3(body_apply_force, RID, const Vector3 &, const Vector3 &) + EXBIND2(body_apply_torque, RID, const Vector3 &) + + EXBIND2(body_add_constant_central_force, RID, const Vector3 &) + EXBIND3(body_add_constant_force, RID, const Vector3 &, const Vector3 &) + EXBIND2(body_add_constant_torque, RID, const Vector3 &) + + EXBIND2(body_set_constant_force, RID, const Vector3 &) + EXBIND1RC(Vector3, body_get_constant_force, RID) + + EXBIND2(body_set_constant_torque, RID, const Vector3 &) + EXBIND1RC(Vector3, body_get_constant_torque, RID) + + EXBIND2(body_set_axis_velocity, RID, const Vector3 &) + + EXBIND3(body_set_axis_lock, RID, BodyAxis, bool) + EXBIND2RC(bool, body_is_axis_locked, RID, BodyAxis) + + EXBIND2(body_add_collision_exception, RID, RID) + EXBIND2(body_remove_collision_exception, RID, RID) + + GDVIRTUAL1RC(TypedArray<RID>, _body_get_collision_exceptions, RID) + + void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override { + TypedArray<RID> ret; + GDVIRTUAL_REQUIRED_CALL(_body_get_collision_exceptions, p_body, ret); + for (int i = 0; i < ret.size(); i++) { + p_exceptions->push_back(ret[i]); + } + } + + EXBIND2(body_set_max_contacts_reported, RID, int) + EXBIND1RC(int, body_get_max_contacts_reported, RID) + + EXBIND2(body_set_contacts_reported_depth_threshold, RID, real_t) + EXBIND1RC(real_t, body_get_contacts_reported_depth_threshold, RID) + + EXBIND2(body_set_omit_force_integration, RID, bool) + EXBIND1RC(bool, body_is_omitting_force_integration, RID) + + GDVIRTUAL2(_body_set_state_sync_callback, RID, GDNativePtr<PhysicsServer3DExtensionStateCallback>) + void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override { + PhysicsServer3DExtensionStateCallback callback; + callback.callback = p_callback; + callback.instance = p_instance; + GDVIRTUAL_REQUIRED_CALL(_body_set_state_sync_callback, p_body, &callback); + } + EXBIND3(body_set_force_integration_callback, RID, const Callable &, const Variant &) + + EXBIND2(body_set_ray_pickable, RID, bool) + + GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform3D &, const Vector3 &, real_t, int, bool, GDNativePtr<PhysicsServer3DExtensionMotionResult>) + + thread_local static const Set<RID> *exclude_bodies; + thread_local static const Set<ObjectID> *exclude_objects; + + bool body_test_motion_is_excluding_body(RID p_body) const; + bool body_test_motion_is_excluding_object(ObjectID p_object) const; + + bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { + bool ret = false; + exclude_bodies = &p_parameters.exclude_bodies; + exclude_objects = &p_parameters.exclude_objects; + GDVIRTUAL_REQUIRED_CALL(_body_test_motion, p_body, p_parameters.from, p_parameters.motion, p_parameters.margin, p_parameters.max_collisions, p_parameters.collide_separation_ray, r_result, ret); + exclude_bodies = nullptr; + exclude_objects = nullptr; + return ret; + } + + EXBIND1R(PhysicsDirectBodyState3D *, body_get_direct_state, RID) + + /* SOFT BODY API */ + + EXBIND0R(RID, soft_body_create) + + EXBIND2(soft_body_update_rendering_server, RID, PhysicsServer3DRenderingServerHandler *) + + EXBIND2(soft_body_set_space, RID, RID) + EXBIND1RC(RID, soft_body_get_space, RID) + + EXBIND2(soft_body_set_ray_pickable, RID, bool) + + EXBIND2(soft_body_set_collision_layer, RID, uint32_t) + EXBIND1RC(uint32_t, soft_body_get_collision_layer, RID) + + EXBIND2(soft_body_set_collision_mask, RID, uint32_t) + EXBIND1RC(uint32_t, soft_body_get_collision_mask, RID) + + EXBIND2(soft_body_add_collision_exception, RID, RID) + EXBIND2(soft_body_remove_collision_exception, RID, RID) + + GDVIRTUAL1RC(TypedArray<RID>, _soft_body_get_collision_exceptions, RID) + + void soft_body_get_collision_exceptions(RID p_soft_body, List<RID> *p_exceptions) override { + TypedArray<RID> ret; + GDVIRTUAL_REQUIRED_CALL(_soft_body_get_collision_exceptions, p_soft_body, ret); + for (int i = 0; i < ret.size(); i++) { + p_exceptions->push_back(ret[i]); + } + } + + EXBIND3(soft_body_set_state, RID, BodyState, const Variant &) + EXBIND2RC(Variant, soft_body_get_state, RID, BodyState) + + EXBIND2(soft_body_set_transform, RID, const Transform3D &) + + EXBIND2(soft_body_set_simulation_precision, RID, int) + EXBIND1RC(int, soft_body_get_simulation_precision, RID) + + EXBIND2(soft_body_set_total_mass, RID, real_t) + EXBIND1RC(real_t, soft_body_get_total_mass, RID) + + EXBIND2(soft_body_set_linear_stiffness, RID, real_t) + EXBIND1RC(real_t, soft_body_get_linear_stiffness, RID) + + EXBIND2(soft_body_set_pressure_coefficient, RID, real_t) + EXBIND1RC(real_t, soft_body_get_pressure_coefficient, RID) + + EXBIND2(soft_body_set_damping_coefficient, RID, real_t) + EXBIND1RC(real_t, soft_body_get_damping_coefficient, RID) + + EXBIND2(soft_body_set_drag_coefficient, RID, real_t) + EXBIND1RC(real_t, soft_body_get_drag_coefficient, RID) + + EXBIND2(soft_body_set_mesh, RID, RID) + + EXBIND1RC(AABB, soft_body_get_bounds, RID) + + EXBIND3(soft_body_move_point, RID, int, const Vector3 &) + EXBIND2RC(Vector3, soft_body_get_point_global_position, RID, int) + + EXBIND1(soft_body_remove_all_pinned_points, RID) + EXBIND3(soft_body_pin_point, RID, int, bool) + EXBIND2RC(bool, soft_body_is_point_pinned, RID, int) + + /* JOINT API */ + + EXBIND0R(RID, joint_create) + + EXBIND1(joint_clear, RID) + + EXBIND5(joint_make_pin, RID, RID, const Vector3 &, RID, const Vector3 &) + + EXBIND3(pin_joint_set_param, RID, PinJointParam, real_t) + EXBIND2RC(real_t, pin_joint_get_param, RID, PinJointParam) + + EXBIND2(pin_joint_set_local_a, RID, const Vector3 &) + EXBIND1RC(Vector3, pin_joint_get_local_a, RID) + + EXBIND2(pin_joint_set_local_b, RID, const Vector3 &) + EXBIND1RC(Vector3, pin_joint_get_local_b, RID) + + EXBIND5(joint_make_hinge, RID, RID, const Transform3D &, RID, const Transform3D &) + EXBIND7(joint_make_hinge_simple, RID, RID, const Vector3 &, const Vector3 &, RID, const Vector3 &, const Vector3 &) + + EXBIND3(hinge_joint_set_param, RID, HingeJointParam, real_t) + EXBIND2RC(real_t, hinge_joint_get_param, RID, HingeJointParam) + + EXBIND3(hinge_joint_set_flag, RID, HingeJointFlag, bool) + EXBIND2RC(bool, hinge_joint_get_flag, RID, HingeJointFlag) + + EXBIND5(joint_make_slider, RID, RID, const Transform3D &, RID, const Transform3D &) + + EXBIND3(slider_joint_set_param, RID, SliderJointParam, real_t) + EXBIND2RC(real_t, slider_joint_get_param, RID, SliderJointParam) + + EXBIND5(joint_make_cone_twist, RID, RID, const Transform3D &, RID, const Transform3D &) + + EXBIND3(cone_twist_joint_set_param, RID, ConeTwistJointParam, real_t) + EXBIND2RC(real_t, cone_twist_joint_get_param, RID, ConeTwistJointParam) + + EXBIND5(joint_make_generic_6dof, RID, RID, const Transform3D &, RID, const Transform3D &) + + EXBIND4(generic_6dof_joint_set_param, RID, Vector3::Axis, G6DOFJointAxisParam, real_t) + EXBIND3RC(real_t, generic_6dof_joint_get_param, RID, Vector3::Axis, G6DOFJointAxisParam) + + EXBIND4(generic_6dof_joint_set_flag, RID, Vector3::Axis, G6DOFJointAxisFlag, bool) + EXBIND3RC(bool, generic_6dof_joint_get_flag, RID, Vector3::Axis, G6DOFJointAxisFlag) + + EXBIND1RC(JointType, joint_get_type, RID) + + EXBIND2(joint_set_solver_priority, RID, int) + EXBIND1RC(int, joint_get_solver_priority, RID) + + EXBIND2(joint_disable_collisions_between_bodies, RID, bool) + EXBIND1RC(bool, joint_is_disabled_collisions_between_bodies, RID) + + /* MISC */ + + GDVIRTUAL1(_free_rid, RID) + virtual void free(RID p_rid) override { + GDVIRTUAL_REQUIRED_CALL(_free_rid, p_rid); + } + + EXBIND1(set_active, bool) + + EXBIND0(init) + EXBIND1(step, real_t) + EXBIND0(sync) + EXBIND0(end_sync) + EXBIND0(flush_queries) + EXBIND0(finish) + + EXBIND0RC(bool, is_flushing_queries) + EXBIND1R(int, get_process_info, ProcessInfo) + + PhysicsServer3DExtension(); + ~PhysicsServer3DExtension(); +}; + +#endif // PHYSICSSERVER3DEXTENSION_H diff --git a/servers/physics_2d/godot_joints_2d.cpp b/servers/physics_2d/godot_joints_2d.cpp index 0876184d8c..0c21b08ea9 100644 --- a/servers/physics_2d/godot_joints_2d.cpp +++ b/servers/physics_2d/godot_joints_2d.cpp @@ -118,22 +118,26 @@ bool GodotPinJoint2D::setup(real_t p_step) { K1[0].y = 0.0f; K1[1].y = A->get_inv_mass() + B_inv_mass; + Vector2 r1 = rA - A->get_center_of_mass(); + Transform2D K2; - K2[0].x = A->get_inv_inertia() * rA.y * rA.y; - K2[1].x = -A->get_inv_inertia() * rA.x * rA.y; - K2[0].y = -A->get_inv_inertia() * rA.x * rA.y; - K2[1].y = A->get_inv_inertia() * rA.x * rA.x; + K2[0].x = A->get_inv_inertia() * r1.y * r1.y; + K2[1].x = -A->get_inv_inertia() * r1.x * r1.y; + K2[0].y = -A->get_inv_inertia() * r1.x * r1.y; + K2[1].y = A->get_inv_inertia() * r1.x * r1.x; Transform2D K; K[0] = K1[0] + K2[0]; K[1] = K1[1] + K2[1]; if (B) { + Vector2 r2 = rB - B->get_center_of_mass(); + Transform2D K3; - K3[0].x = B->get_inv_inertia() * rB.y * rB.y; - K3[1].x = -B->get_inv_inertia() * rB.x * rB.y; - K3[0].y = -B->get_inv_inertia() * rB.x * rB.y; - K3[1].y = B->get_inv_inertia() * rB.x * rB.x; + K3[0].x = B->get_inv_inertia() * r2.y * r2.y; + K3[1].x = -B->get_inv_inertia() * r2.x * r2.y; + K3[0].y = -B->get_inv_inertia() * r2.x * r2.y; + K3[1].y = B->get_inv_inertia() * r2.x * r2.x; K[0] += K3[0]; K[1] += K3[1]; diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index a1912dc660..f7270713e0 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -920,7 +920,7 @@ RID GodotPhysicsServer3D::soft_body_create() { return rid; } -void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) { +void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) { GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); ERR_FAIL_COND(!soft_body); @@ -1355,7 +1355,7 @@ int GodotPhysicsServer3D::joint_get_solver_priority(RID p_joint) const { return joint->get_priority(); } -void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { +void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) { GodotJoint3D *joint = joint_owner.get_or_null(p_joint); ERR_FAIL_COND(!joint); diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h index b903f4808c..00ed763e01 100644 --- a/servers/physics_3d/godot_physics_server_3d.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -253,7 +253,7 @@ public: virtual RID soft_body_create() override; - virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) override; + virtual void soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) override; virtual void soft_body_set_space(RID p_body, RID p_space) override; virtual RID soft_body_get_space(RID p_body) const override; @@ -353,7 +353,7 @@ public: virtual void joint_set_solver_priority(RID p_joint, int p_priority) override; virtual int joint_get_solver_priority(RID p_joint) const override; - virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) override; + virtual void joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) override; virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const override; /* MISC */ diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index 095050b7f3..f09da92cae 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -147,7 +147,7 @@ void GodotSoftBody3D::set_mesh(RID p_mesh) { } } -void GodotSoftBody3D::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) { +void GodotSoftBody3D::update_rendering_server(PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) { if (soft_mesh.is_null()) { return; } diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h index 5028e81dd8..d9f5078313 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -157,7 +157,7 @@ public: void set_mesh(RID p_mesh); - void update_rendering_server(RenderingServerHandler *p_rendering_server_handler); + void update_rendering_server(PhysicsServer3DRenderingServerHandler *p_rendering_server_handler); Vector3 get_vertex_position(int p_index) const; void set_vertex_position(int p_index, const Vector3 &p_position); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index fc119e49e9..17c94978d1 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -33,6 +33,22 @@ #include "core/config/project_settings.h" #include "core/string/print_string.h" +void PhysicsServer3DRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { + GDVIRTUAL_REQUIRED_CALL(_set_vertex, p_vertex_id, p_vector3); +} +void PhysicsServer3DRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { + GDVIRTUAL_REQUIRED_CALL(_set_normal, p_vertex_id, p_vector3); +} +void PhysicsServer3DRenderingServerHandler::set_aabb(const AABB &p_aabb) { + GDVIRTUAL_REQUIRED_CALL(_set_aabb, p_aabb); +} + +void PhysicsServer3DRenderingServerHandler::_bind_methods() { + GDVIRTUAL_BIND(_set_vertex, "vertex_id", "vertices"); + GDVIRTUAL_BIND(_set_normal, "vertex_id", "normals"); + GDVIRTUAL_BIND(_set_aabb, "aabb"); +} + PhysicsServer3D *PhysicsServer3D::singleton = nullptr; void PhysicsDirectBodyState3D::integrate_forces() { diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index f830c95b58..4811f7a039 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -33,6 +33,9 @@ #include "core/io/resource.h" #include "core/object/class_db.h" +#include "core/object/gdvirtual.gen.inc" +#include "core/object/script_language.h" +#include "core/variant/native_ptr.h" class PhysicsDirectSpaceState3D; @@ -202,13 +205,21 @@ public: PhysicsDirectSpaceState3D(); }; -class RenderingServerHandler { +class PhysicsServer3DRenderingServerHandler : public Object { + GDCLASS(PhysicsServer3DRenderingServerHandler, Object) +protected: + GDVIRTUAL2(_set_vertex, int, GDNativeConstPtr<void>) + GDVIRTUAL2(_set_normal, int, GDNativeConstPtr<void>) + GDVIRTUAL1(_set_aabb, const AABB &) + + static void _bind_methods(); + public: - virtual void set_vertex(int p_vertex_id, const void *p_vector3) = 0; - virtual void set_normal(int p_vertex_id, const void *p_vector3) = 0; - virtual void set_aabb(const AABB &p_aabb) = 0; + virtual void set_vertex(int p_vertex_id, const void *p_vector3); + virtual void set_normal(int p_vertex_id, const void *p_vector3); + virtual void set_aabb(const AABB &p_aabb); - virtual ~RenderingServerHandler() {} + virtual ~PhysicsServer3DRenderingServerHandler() {} }; class PhysicsTestMotionParameters3D; @@ -552,7 +563,7 @@ public: virtual RID soft_body_create() = 0; - virtual void soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) = 0; + virtual void soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) = 0; virtual void soft_body_set_space(RID p_body, RID p_space) = 0; virtual RID soft_body_get_space(RID p_body) const = 0; @@ -624,7 +635,7 @@ public: virtual void joint_set_solver_priority(RID p_joint, int p_priority) = 0; virtual int joint_get_solver_priority(RID p_joint) const = 0; - virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0; + virtual void joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) = 0; virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0; virtual void joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0; diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index ecaef886e1..e44f82672d 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -269,7 +269,7 @@ public: FUNCRID(soft_body) - FUNC2(soft_body_update_rendering_server, RID, class RenderingServerHandler *) + FUNC2(soft_body_update_rendering_server, RID, PhysicsServer3DRenderingServerHandler *) FUNC2(soft_body_set_space, RID, RID) FUNC1RC(RID, soft_body_get_space, RID) @@ -369,7 +369,7 @@ public: FUNC2(joint_set_solver_priority, RID, int); FUNC1RC(int, joint_get_solver_priority, RID); - FUNC2(joint_disable_collisions_between_bodies, RID, const bool); + FUNC2(joint_disable_collisions_between_bodies, RID, bool); FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID); /* MISC */ diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 6848620b48..f73407ad34 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -70,6 +70,7 @@ #include "rendering/rendering_device.h" #include "rendering/rendering_device_binds.h" #include "rendering_server.h" +#include "servers/extensions/physics_server_3d_extension.h" #include "servers/rendering/shader_types.h" #include "text/text_server_extension.h" #include "text_server.h" @@ -113,6 +114,9 @@ void preregister_server_types() { GDREGISTER_ABSTRACT_CLASS(TextServer); GDREGISTER_CLASS(TextServerExtension); + GDREGISTER_NATIVE_STRUCT(Glyph, "int start = -1;int end = -1;uint8_t count = 0;uint8_t repeat = 1;uint16_t flags = 0;float x_off = 0.f;float y_off = 0.f;float advance = 0.f;RID font_rid;int font_size = 0;int32_t index = 0"); + GDREGISTER_NATIVE_STRUCT(CaretInfo, "Rect2 leading_caret;Rect2 trailing_caret;TextServer::Direction leading_direction;TextServer::Direction trailing_direction"); + Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager")); } @@ -125,6 +129,18 @@ void register_server_types() { GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D); GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D); + GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DExtension); + GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3DExtension); + GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3DExtension) + GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DRenderingServerHandler) + + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionRayResult, "Vector3 position;Vector3 normal;RID rid;ObjectID collider_id;Object *collider;int shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeRestInfo, "Vector3 point;Vector3 normal;RID rid;ObjectID collider_id;int shape;Vector3 linear_velocity"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionCollision, "Vector3 position;Vector3 normal;Vector3 collider_velocity;real_t depth;int local_shape;ObjectID collider_id;RID collider;int collider_shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionResult, "Vector3 travel;Vector3 remainder;real_t collision_safe_fraction;real_t collision_unsafe_fraction;PhysicsServer3DExtensionMotionCollision collisions[32];int collision_count"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionStateCallback, "void *instance;void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state)"); + GDREGISTER_ABSTRACT_CLASS(NavigationServer2D); GDREGISTER_ABSTRACT_CLASS(NavigationServer3D); GDREGISTER_CLASS(XRServer); diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub index 0939b68482..06d1d28b08 100644 --- a/servers/rendering/SCsub +++ b/servers/rendering/SCsub @@ -5,3 +5,4 @@ Import("env") env.add_source_files(env.servers_sources, "*.cpp") SConscript("renderer_rd/SCsub") +SConscript("storage/SCsub") diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h new file mode 100644 index 0000000000..194b5b5cfe --- /dev/null +++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h @@ -0,0 +1,63 @@ +/*************************************************************************/ +/* rasterizer_canvas_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_CANVAS_DUMMY_H +#define RASTERIZER_CANVAS_DUMMY_H + +#include "servers/rendering/renderer_canvas_render.h" + +class RasterizerCanvasDummy : public RendererCanvasRender { +public: + PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; } + void free_polygon(PolygonID p_polygon) override {} + + void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {} + void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {} + + RID light_create() override { return RID(); } + void light_set_texture(RID p_rid, RID p_texture) override {} + void light_set_use_shadow(RID p_rid, bool p_enable) override {} + void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {} + void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {} + + void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {} + RID occluder_polygon_create() override { return RID(); } + void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {} + void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {} + void set_shadow_texture_size(int p_size) override {} + + bool free(RID p_rid) override { return true; } + void update() override {} + + RasterizerCanvasDummy() {} + ~RasterizerCanvasDummy() {} +}; + +#endif // !RASTERIZER_CANVAS_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h new file mode 100644 index 0000000000..b3fbc18c46 --- /dev/null +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -0,0 +1,99 @@ +/*************************************************************************/ +/* rasterizer_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_DUMMY_H +#define RASTERIZER_DUMMY_H + +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "scene/resources/mesh.h" +#include "servers/rendering/dummy/rasterizer_canvas_dummy.h" +#include "servers/rendering/dummy/rasterizer_scene_dummy.h" +#include "servers/rendering/dummy/rasterizer_storage_dummy.h" +#include "servers/rendering/dummy/storage/canvas_texture_storage.h" +#include "servers/rendering/dummy/storage/texture_storage.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering_server.h" + +class RasterizerDummy : public RendererCompositor { +private: + uint64_t frame = 1; + double delta = 0; + +protected: + RasterizerCanvasDummy canvas; + RendererDummy::CanvasTextureStorage canvas_texture_storage; + RendererDummy::TextureStorage texture_storage; + RasterizerStorageDummy storage; + RasterizerSceneDummy scene; + +public: + RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; }; + RendererTextureStorage *get_texture_storage() override { return &texture_storage; }; + RendererStorage *get_storage() override { return &storage; } + RendererCanvasRender *get_canvas() override { return &canvas; } + RendererSceneRender *get_scene() override { return &scene; } + + void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {} + + void initialize() override {} + void begin_frame(double frame_step) override { + frame++; + delta = frame_step; + } + + void prepare_for_blitting_render_targets() override {} + void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {} + + void end_frame(bool p_swap_buffers) override { + if (p_swap_buffers) { + DisplayServer::get_singleton()->swap_buffers(); + } + } + + void finalize() override {} + + static RendererCompositor *_create_current() { + return memnew(RasterizerDummy); + } + + static void make_current() { + _create_func = _create_current; + } + + bool is_low_end() const override { return true; } + uint64_t get_frame_number() const override { return frame; } + double get_frame_delta_time() const override { return delta; } + + RasterizerDummy() {} + ~RasterizerDummy() {} +}; + +#endif // RASTERIZER_DUMMY_H diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h new file mode 100644 index 0000000000..3855222554 --- /dev/null +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -0,0 +1,217 @@ +/*************************************************************************/ +/* rasterizer_scene_dummy.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_SCENE_DUMMY_H +#define RASTERIZER_SCENE_DUMMY_H + +#include "servers/rendering/renderer_scene_render.h" + +class RasterizerSceneDummy : public RendererSceneRender { +public: + GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } + void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {} + void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {} + void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {} + void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {} + void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {} + void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {} + void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {} + void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {} + void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {} + void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {} + void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {} + void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {} + void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} + void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {} + void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {} + + uint32_t geometry_instance_get_pair_mask() override { return 0; } + void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {} + void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} + void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} + void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} + void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {} + + void geometry_instance_free(GeometryInstance *p_geometry_instance) override {} + + /* SHADOW ATLAS API */ + + RID shadow_atlas_create() override { return RID(); } + void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {} + void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {} + bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; } + + void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {} + int get_directional_light_shadow_size(RID p_light_intance) override { return 0; } + void set_directional_shadow_count(int p_count) override {} + + /* SDFGI UPDATE */ + + void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} + int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } + AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } + uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } + + /* SKY API */ + + RID sky_allocate() override { return RID(); } + void sky_initialize(RID p_rid) override {} + void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {} + void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {} + void sky_set_material(RID p_sky, RID p_material) override {} + Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } + + /* ENVIRONMENT API */ + + RID environment_allocate() override { return RID(); } + void environment_initialize(RID p_rid) override {} + void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {} + void environment_set_sky(RID p_env, RID p_sky) override {} + void environment_set_sky_custom_fov(RID p_env, float p_scale) override {} + void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {} + void environment_set_bg_color(RID p_env, const Color &p_color) override {} + void environment_set_bg_energy(RID p_env, float p_energy) override {} + void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {} + void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {} + + void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {} + void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} + void environment_glow_set_use_high_quality(bool p_enable) override {} + + void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {} + void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {} + void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {} + void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} + void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {} + void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} + + void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} + + void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {} + void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {} + void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {} + + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {} + + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {} + + void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {} + void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {} + void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {} + void environment_set_volumetric_fog_filter_active(bool p_enable) override {} + + Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } + + bool is_environment(RID p_env) const override { return false; } + RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; } + int environment_get_canvas_max_layer(RID p_env) const override { return 0; } + + RID camera_effects_allocate() override { return RID(); } + void camera_effects_initialize(RID p_rid) override {} + void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {} + void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {} + + void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {} + void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {} + + void shadows_quality_set(RS::ShadowQuality p_quality) override {} + void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {} + + RID light_instance_create(RID p_light) override { return RID(); } + void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} + void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} + void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {} + void light_instance_mark_visible(RID p_light_instance) override {} + + RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); } + void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {} + void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {} + RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); } + Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); } + + RID reflection_atlas_create() override { return RID(); } + int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; } + void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {} + + RID reflection_probe_instance_create(RID p_probe) override { return RID(); } + void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {} + void reflection_probe_release_atlas_index(RID p_instance) override {} + bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } + bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } + bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } + bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } + + RID decal_instance_create(RID p_decal) override { return RID(); } + void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} + + RID lightmap_instance_create(RID p_lightmap) override { return RID(); } + void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} + + RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } + void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} + bool voxel_gi_needs_update(RID p_probe) const override { return false; } + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {} + + void voxel_gi_set_quality(RS::VoxelGIQuality) override {} + + void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} + void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} + void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} + + void set_scene_pass(uint64_t p_pass) override {} + void set_time(double p_time, double p_step) override {} + void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} + + RID render_buffers_create() override { return RID(); } + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {} + void gi_set_use_half_resolution(bool p_enable) override {} + + void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} + bool screen_space_roughness_limiter_is_active() const override { return false; } + + void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {} + void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {} + + TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } + + bool free(RID p_rid) override { return false; } + void update() override {} + void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {} + + virtual void decals_set_filter(RS::DecalFilter p_filter) override {} + virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {} + + RasterizerSceneDummy() {} + ~RasterizerSceneDummy() {} +}; + +#endif // !RASTERIZER_SCENE_DUMMY_H diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h index 8f82356d11..1c8258da32 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_storage_dummy.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* rasterizer_dummy.h */ +/* rasterizer_storage_dummy.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,265 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_DUMMY_H -#define RASTERIZER_DUMMY_H +#ifndef RASTERIZER_STORAGE_DUMMY_H +#define RASTERIZER_STORAGE_DUMMY_H -#include "core/templates/rid_owner.h" -#include "core/templates/self_list.h" -#include "scene/resources/mesh.h" -#include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/renderer_scene_render.h" -#include "servers/rendering_server.h" - -class RasterizerSceneDummy : public RendererSceneRender { -public: - GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } - void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {} - void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {} - void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {} - void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {} - void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {} - void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {} - void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {} - void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {} - void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {} - void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {} - void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {} - void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {} - void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} - void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {} - void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {} - - uint32_t geometry_instance_get_pair_mask() override { return 0; } - void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {} - void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} - void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} - void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} - void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {} - - void geometry_instance_free(GeometryInstance *p_geometry_instance) override {} - - /* SHADOW ATLAS API */ - - RID shadow_atlas_create() override { return RID(); } - void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {} - void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {} - bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; } - - void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {} - int get_directional_light_shadow_size(RID p_light_intance) override { return 0; } - void set_directional_shadow_count(int p_count) override {} - - /* SDFGI UPDATE */ - - void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} - int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } - AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } - uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } - - /* SKY API */ - - RID sky_allocate() override { return RID(); } - void sky_initialize(RID p_rid) override {} - void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {} - void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {} - void sky_set_material(RID p_sky, RID p_material) override {} - Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } - - /* ENVIRONMENT API */ - - RID environment_allocate() override { return RID(); } - void environment_initialize(RID p_rid) override {} - void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {} - void environment_set_sky(RID p_env, RID p_sky) override {} - void environment_set_sky_custom_fov(RID p_env, float p_scale) override {} - void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {} - void environment_set_bg_color(RID p_env, const Color &p_color) override {} - void environment_set_bg_energy(RID p_env, float p_energy) override {} - void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {} - void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {} - - void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {} - void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} - void environment_glow_set_use_high_quality(bool p_enable) override {} - - void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {} - void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {} - void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {} - void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {} - void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {} - - void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {} - - void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {} - void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {} - void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {} - - void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {} - - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {} - - void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {} - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {} - void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {} - void environment_set_volumetric_fog_filter_active(bool p_enable) override {} - - Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); } - - bool is_environment(RID p_env) const override { return false; } - RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; } - int environment_get_canvas_max_layer(RID p_env) const override { return 0; } - - RID camera_effects_allocate() override { return RID(); } - void camera_effects_initialize(RID p_rid) override {} - void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {} - void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {} - - void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {} - void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {} - - void shadows_quality_set(RS::ShadowQuality p_quality) override {} - void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {} - - RID light_instance_create(RID p_light) override { return RID(); } - void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} - void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} - void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {} - void light_instance_mark_visible(RID p_light_instance) override {} - - RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); } - void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {} - void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {} - RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); } - Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); } - - RID reflection_atlas_create() override { return RID(); } - int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; } - void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {} - - RID reflection_probe_instance_create(RID p_probe) override { return RID(); } - void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {} - void reflection_probe_release_atlas_index(RID p_instance) override {} - bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } - bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } - bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } - bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } - - RID decal_instance_create(RID p_decal) override { return RID(); } - void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} - - RID lightmap_instance_create(RID p_lightmap) override { return RID(); } - void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} - - RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } - void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} - bool voxel_gi_needs_update(RID p_probe) const override { return false; } - void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {} - - void voxel_gi_set_quality(RS::VoxelGIQuality) override {} - - void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} - void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {} - - void set_scene_pass(uint64_t p_pass) override {} - void set_time(double p_time, double p_step) override {} - void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} - - RID render_buffers_create() override { return RID(); } - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {} - void gi_set_use_half_resolution(bool p_enable) override {} - - void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} - bool screen_space_roughness_limiter_is_active() const override { return false; } - - void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {} - void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {} - - TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } - - bool free(RID p_rid) override { return false; } - void update() override {} - void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {} - - virtual void decals_set_filter(RS::DecalFilter p_filter) override {} - virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {} - - RasterizerSceneDummy() {} - ~RasterizerSceneDummy() {} -}; +#include "servers/rendering/renderer_storage.h" +#include "storage/texture_storage.h" class RasterizerStorageDummy : public RendererStorage { public: - bool can_create_resources_async() const override { return false; } - - /* TEXTURE API */ - struct DummyTexture { - Ref<Image> image; - }; - mutable RID_PtrOwner<DummyTexture> texture_owner; - - RID texture_allocate() override { - DummyTexture *texture = memnew(DummyTexture); - ERR_FAIL_COND_V(!texture, RID()); - return texture_owner.make_rid(texture); - } - void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override { - DummyTexture *t = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!t); - t->image = p_image->duplicate(); - } - - void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {} - void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {} - void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {} - void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {} - void texture_proxy_initialize(RID p_texture, RID p_base) override {} - void texture_proxy_update(RID p_proxy, RID p_base) override {} - - void texture_2d_placeholder_initialize(RID p_texture) override {} - void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {} - void texture_3d_placeholder_initialize(RID p_texture) override {} - - Ref<Image> texture_2d_get(RID p_texture) const override { - DummyTexture *t = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!t, Ref<Image>()); - return t->image; - } - - Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); } - Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); } - - void texture_replace(RID p_texture, RID p_by_texture) override { free(p_by_texture); } - void texture_set_size_override(RID p_texture, int p_width, int p_height) override {} - - void texture_set_path(RID p_texture, const String &p_path) override {} - String texture_get_path(RID p_texture) const override { return String(); } - - void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {} - void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {} - void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {} - - void texture_debug_usage(List<RS::TextureInfo> *r_info) override {} - void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {} - Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); } - - void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} - - /* CANVAS TEXTURE API */ - - RID canvas_texture_allocate() override { return RID(); } - void canvas_texture_initialize(RID p_rid) override {} - void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {} - void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {} - - void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {} - void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {} - /* SHADER API */ RID shader_allocate() override { return RID(); } @@ -481,6 +230,9 @@ public: AABB decal_get_aabb(RID p_decal) const override { return AABB(); } + void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + /* VOXEL GI API */ RID voxel_gi_allocate() override { return RID(); } @@ -682,11 +434,8 @@ public: RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; } bool free(RID p_rid) override { - if (texture_owner.owns(p_rid)) { - // delete the texture - DummyTexture *texture = texture_owner.get_or_null(p_rid); - texture_owner.free(p_rid); - memdelete(texture); + if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) { + RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid); return true; } return false; @@ -721,81 +470,4 @@ public: ~RasterizerStorageDummy() {} }; -class RasterizerCanvasDummy : public RendererCanvasRender { -public: - PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; } - void free_polygon(PolygonID p_polygon) override {} - - void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {} - void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {} - - RID light_create() override { return RID(); } - void light_set_texture(RID p_rid, RID p_texture) override {} - void light_set_use_shadow(RID p_rid, bool p_enable) override {} - void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {} - void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {} - - void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {} - RID occluder_polygon_create() override { return RID(); } - void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {} - void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {} - void set_shadow_texture_size(int p_size) override {} - - bool free(RID p_rid) override { return true; } - void update() override {} - - RasterizerCanvasDummy() {} - ~RasterizerCanvasDummy() {} -}; - -class RasterizerDummy : public RendererCompositor { -private: - uint64_t frame = 1; - double delta = 0; - -protected: - RasterizerCanvasDummy canvas; - RasterizerStorageDummy storage; - RasterizerSceneDummy scene; - -public: - RendererStorage *get_storage() override { return &storage; } - RendererCanvasRender *get_canvas() override { return &canvas; } - RendererSceneRender *get_scene() override { return &scene; } - - void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {} - - void initialize() override {} - void begin_frame(double frame_step) override { - frame++; - delta = frame_step; - } - - void prepare_for_blitting_render_targets() override {} - void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {} - - void end_frame(bool p_swap_buffers) override { - if (p_swap_buffers) { - DisplayServer::get_singleton()->swap_buffers(); - } - } - - void finalize() override {} - - static RendererCompositor *_create_current() { - return memnew(RasterizerDummy); - } - - static void make_current() { - _create_func = _create_current; - } - - bool is_low_end() const override { return true; } - uint64_t get_frame_number() const override { return frame; } - double get_frame_delta_time() const override { return delta; } - - RasterizerDummy() {} - ~RasterizerDummy() {} -}; - -#endif // RASTERIZER_DUMMY_H +#endif // !RASTERIZER_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/canvas_texture_storage.h b/servers/rendering/dummy/storage/canvas_texture_storage.h new file mode 100644 index 0000000000..daa3ac5e42 --- /dev/null +++ b/servers/rendering/dummy/storage/canvas_texture_storage.h @@ -0,0 +1,53 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_DUMMY_H +#define CANVAS_TEXTURE_STORAGE_DUMMY_H + +#include "servers/rendering/storage/canvas_texture_storage.h" + +namespace RendererDummy { + +class CanvasTextureStorage : public RendererCanvasTextureStorage { +public: + virtual RID canvas_texture_allocate() override { return RID(); }; + virtual void canvas_texture_initialize(RID p_rid) override{}; + virtual void canvas_texture_free(RID p_rid) override{}; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override{}; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override{}; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override{}; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override{}; +}; + +} // namespace RendererDummy + +#endif // !CANVAS_TEXTURE_STORAGE_DUMMY_H diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h new file mode 100644 index 0000000000..d40a1842a4 --- /dev/null +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -0,0 +1,116 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_DUMMY_H +#define TEXTURE_STORAGE_DUMMY_H + +#include "servers/rendering/rendering_server_globals.h" +#include "servers/rendering/storage/texture_storage.h" + +namespace RendererDummy { + +class TextureStorage : public RendererTextureStorage { +private: + struct DummyTexture { + Ref<Image> image; + }; + mutable RID_PtrOwner<DummyTexture> texture_owner; + +public: + static TextureStorage *get_singleton() { + // Here we cheat until we can retire RasterizerStorageDummy::free() + + return (TextureStorage *)RSG::texture_storage; + }; + + virtual bool can_create_resources_async() const override { return false; } + + DummyTexture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + + virtual RID texture_allocate() override { + DummyTexture *texture = memnew(DummyTexture); + ERR_FAIL_COND_V(!texture, RID()); + return texture_owner.make_rid(texture); + }; + + virtual void texture_free(RID p_rid) override { + // delete the texture + DummyTexture *texture = texture_owner.get_or_null(p_rid); + texture_owner.free(p_rid); + memdelete(texture); + }; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override { + DummyTexture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!t); + t->image = p_image->duplicate(); + }; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override{}; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override{}; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) override{}; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override{}; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{}; + virtual void texture_proxy_update(RID p_proxy, RID p_base) override{}; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) override{}; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override{}; + virtual void texture_3d_placeholder_initialize(RID p_texture) override{}; + + virtual Ref<Image> texture_2d_get(RID p_texture) const override { + DummyTexture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!t, Ref<Image>()); + return t->image; + }; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }; + + virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); }; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override{}; + + virtual void texture_set_path(RID p_texture, const String &p_path) override{}; + virtual String texture_get_path(RID p_texture) const override { return String(); }; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{}; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{}; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{}; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override{}; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override{}; + + virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }; +}; + +} // namespace RendererDummy + +#endif // !TEXTURE_STORAGE_DUMMY_H diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index a96f873088..56eaa396c8 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -34,6 +34,7 @@ #include "renderer_viewport.h" #include "rendering_server_default.h" #include "rendering_server_globals.h" +#include "servers/rendering/storage/canvas_texture_storage.h" static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; @@ -1530,26 +1531,26 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) { } RID RendererCanvasCull::canvas_texture_allocate() { - return RSG::storage->canvas_texture_allocate(); + return RSG::canvas_texture_storage->canvas_texture_allocate(); } void RendererCanvasCull::canvas_texture_initialize(RID p_rid) { - RSG::storage->canvas_texture_initialize(p_rid); + RSG::canvas_texture_storage->canvas_texture_initialize(p_rid); } void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { - RSG::storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture); + RSG::canvas_texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture); } void RendererCanvasCull::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) { - RSG::storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess); + RSG::canvas_texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess); } void RendererCanvasCull::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { - RSG::storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter); + RSG::canvas_texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter); } void RendererCanvasCull::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { - RSG::storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat); + RSG::canvas_texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat); } void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) { diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index e58fd7bebc..c2bc2c03d0 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -34,6 +34,8 @@ #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_storage.h" +#include "servers/rendering/storage/canvas_texture_storage.h" +#include "servers/rendering/storage/texture_storage.h" #include "servers/rendering_server.h" class RendererSceneRender; @@ -70,6 +72,8 @@ protected: public: static RendererCompositor *create(); + virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0; + virtual RendererTextureStorage *get_texture_storage() = 0; virtual RendererStorage *get_storage() = 0; virtual RendererCanvasRender *get_canvas() = 0; virtual RendererSceneRender *get_scene() = 0; diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub index 64e613ab91..d3ad381965 100644 --- a/servers/rendering/renderer_rd/SCsub +++ b/servers/rendering/renderer_rd/SCsub @@ -7,3 +7,4 @@ env.add_source_files(env.servers_sources, "*.cpp") SConscript("forward_clustered/SCsub") SConscript("forward_mobile/SCsub") SConscript("shaders/SCsub") +SConscript("storage_rd/SCsub") diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 6b500260ef..3aabc5058e 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -187,12 +187,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) { clear(); - ERR_FAIL_COND_MSG(p_view_count != 1, "Multiple views is currently not supported in this renderer, please use the mobile renderer for VR support"); - msaa = p_msaa; width = p_width; height = p_height; + view_count = p_view_count; color = p_color_buffer; depth = p_depth_buffer; @@ -203,20 +202,25 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c fb.push_back(p_color_buffer); fb.push_back(depth); - color_fb = RD::get_singleton()->framebuffer_create(fb); + color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } { Vector<RID> fb; fb.push_back(depth); - depth_fb = RD::get_singleton()->framebuffer_create(fb); + depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } } else { RD::TextureFormat tf; + if (view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + } tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = p_width; tf.height = p_height; - tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = view_count; // create a layer for every view tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { @@ -241,13 +245,13 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c fb.push_back(color_msaa); fb.push_back(depth_msaa); - color_fb = RD::get_singleton()->framebuffer_create(fb); + color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } { Vector<RID> fb; fb.push_back(depth_msaa); - depth_fb = RD::get_singleton()->framebuffer_create(fb); + depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } } } @@ -417,22 +421,23 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p switch (p_pass_mode) { case PASS_MODE_COLOR: { if (element_info.uses_lightmap) { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS; + pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS; } else { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS; + pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS; } } break; case PASS_MODE_COLOR_TRANSPARENT: { if (element_info.uses_lightmap) { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS; + pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS; } else { if (element_info.uses_forward_gi) { pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI; } - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS; + pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS; } } break; case PASS_MODE_COLOR_SPECULAR: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for specular pass"); if (element_info.uses_lightmap) { pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR; } else { @@ -441,21 +446,26 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p } break; case PASS_MODE_SHADOW: case PASS_MODE_DEPTH: { - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS; + pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS; } break; case PASS_MODE_SHADOW_DP: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_DP; } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for depth/roughness pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for voxel GI pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI; } break; case PASS_MODE_DEPTH_MATERIAL: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL; } break; case PASS_MODE_SDF: { + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for SDF pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF; } break; } @@ -605,6 +615,12 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix); RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); + for (uint32_t v = 0; v < p_render_data->view_count; v++) { + projection = correction * p_render_data->view_projection[v]; + RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]); + RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]); + } + scene_state.ubo.z_far = p_render_data->z_far; scene_state.ubo.z_near = p_render_data->z_near; @@ -1200,8 +1216,6 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps } void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { - ERR_FAIL_COND_MSG(p_render_data->view_count != 1, "Multiview is currently not supported in the clustered renderer. Please use the mobile renderer for VR."); - RenderBufferDataForwardClustered *render_buffer = nullptr; if (p_render_data->render_buffers.is_valid()) { render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); @@ -1434,7 +1448,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID()); bool finish_depth = using_ssao || using_sdfgi || using_voxelgi; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); _render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear); RD::get_singleton()->draw_command_end_label(); @@ -1492,7 +1506,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); if (will_continue_color && using_separate_specular) { // close the specular framebuffer, as it's no longer used @@ -1538,14 +1552,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (draw_sky || draw_sky_fog_only) { RENDER_TIMESTAMP("Render Sky"); - CameraMatrix projection = p_render_data->cam_projection; + RD::get_singleton()->draw_command_begin_label("Draw Sky"); + if (p_render_data->reflection_probe.is_valid()) { CameraMatrix correction; correction.set_depth_correction(true); - projection = correction * p_render_data->cam_projection; + CameraMatrix projection = correction * p_render_data->cam_projection; + sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time); + } else { + sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); } - RD::get_singleton()->draw_command_begin_label("Draw Sky"); - sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time); RD::get_singleton()->draw_command_end_label(); } @@ -1599,7 +1615,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); { - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold); + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); } @@ -1649,6 +1665,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page RenderDataRD render_data; render_data.cam_projection = p_projection; render_data.cam_transform = p_transform; + render_data.view_projection[0] = p_projection; render_data.z_far = p_zfar; render_data.z_near = 0.0; render_data.cluster_size = 1; @@ -1720,7 +1737,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; - RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); + RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect); } @@ -1738,6 +1755,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con RenderDataRD render_data; render_data.cam_projection = p_cam_projection; render_data.cam_transform = p_cam_transform; + render_data.view_projection[0] = p_cam_projection; render_data.z_near = 0.0; render_data.z_far = p_cam_projection.get_z_far(); render_data.cluster_size = 1; @@ -1776,6 +1794,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform RenderDataRD render_data; render_data.cam_projection = p_cam_projection; render_data.cam_transform = p_cam_transform; + render_data.view_projection[0] = p_cam_projection; render_data.cluster_size = 1; render_data.cluster_max_elements = 32; render_data.instances = &p_instances; @@ -2194,7 +2213,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -2211,7 +2230,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -2225,7 +2244,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } u.append_id(texture); uniforms.push_back(u); @@ -2237,7 +2256,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } @@ -2246,12 +2265,12 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = storage->lightmap_get_texture(base); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); } else { u.append_id(default_tex); @@ -2264,7 +2283,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) { RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]); @@ -2294,7 +2313,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2303,7 +2322,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2313,7 +2332,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); u.append_id(texture); uniforms.push_back(u); } @@ -2323,7 +2342,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID(); - RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2333,7 +2352,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID(); - RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2343,7 +2362,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 14; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID(); - RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2355,7 +2374,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers); } else { - t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } u.append_id(t); uniforms.push_back(u); @@ -2367,7 +2386,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -2386,10 +2405,10 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) { vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers); if (vfog.is_null()) { - vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } } else { - vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(vfog); uniforms.push_back(u); @@ -2399,7 +2418,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 19; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID(); - RID texture = ssil.is_valid() ? ssil : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2427,7 +2446,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te } { // No radiance texture. - RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2437,7 +2456,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No reflection atlas. - RID ref_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2450,7 +2469,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2460,7 +2479,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -2471,7 +2490,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { u.append_id(default_tex); } @@ -2485,7 +2504,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { u.append_id(default_tex); } diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index dd5c719352..a219b98204 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -107,6 +107,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID color_specular_fb; RID specular_only_fb; int width, height; + uint32_t view_count; RID render_sdfgi_uniform_set; void ensure_specular(); @@ -155,6 +156,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { bool reverse_cull = false; PassMode pass_mode = PASS_MODE_COLOR; bool no_gi = false; + uint32_t view_count = 1; RID render_pass_uniform_set; bool force_wireframe = false; Vector2 uv_offset; @@ -166,13 +168,14 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t barrier = RD::BARRIER_MASK_ALL; bool use_directional_soft_shadow = false; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; reverse_cull = p_reverse_cull; pass_mode = p_pass_mode; no_gi = p_no_gi; + view_count = p_view_count; render_pass_uniform_set = p_render_pass_uniform_set; force_wireframe = p_force_wireframe; uv_offset = p_uv_offset; @@ -219,6 +222,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { float camera_matrix[16]; float inv_camera_matrix[16]; + float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; + float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; + float viewport_size[2]; float screen_pixel_size[2]; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index b4def4e11c..217427d515 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/math/math_defs.h" #include "render_forward_clustered.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" using namespace RendererSceneRenderImplementation; @@ -149,7 +150,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - Map<String, String>::Element * el = gen_code.code.front(); + Map<String, String>::Element *el = gen_code.code.front(); while (el) { print_line("\n**code " + el->key() + ":\n" + el->value()); @@ -282,6 +283,12 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { SHADER_VERSION_LIGHTMAP_COLOR_PASS, SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, SHADER_VERSION_LIGHTMAP_COLOR_PASS, + + SHADER_VERSION_DEPTH_PASS_MULTIVIEW, + SHADER_VERSION_COLOR_PASS_MULTIVIEW, + SHADER_VERSION_COLOR_PASS_MULTIVIEW, + SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, + SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, }; shader_version = shader_version_table[k]; @@ -297,7 +304,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; RD::PipelineMultisampleState multisample_state; - if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS) { + if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS || k == PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW) { if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { multisample_state.enable_alpha_to_coverage = true; } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { @@ -310,9 +317,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { if (depth_draw == DEPTH_DRAW_OPAQUE) { depth_stencil.enable_depth_write = false; //alpha does not draw depth } - } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS) { + } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS || k == PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW) { blend_state = blend_state_opaque; - } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP) { + } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW || k == PIPELINE_VERSION_DEPTH_PASS_DP) { //none, leave empty } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { blend_state = blend_state_depth_normal_roughness; @@ -501,7 +508,18 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR + // multiview versions of our shaders + shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW + shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW + shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW + shader.initialize(shader_versions, p_defines); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false); + shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false); + shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false); + } } storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); @@ -516,7 +534,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix"; actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix"; actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix"; + actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; actions.renames["MODELVIEW_MATRIX"] = "modelview"; actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; @@ -587,8 +605,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.renames["CUSTOM3"] = "custom3_attrib"; actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - // not implemented but need these just in case code is in the shaders - actions.renames["VIEW_INDEX"] = "0"; + actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 33049fad9c..4398517259 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -55,6 +55,11 @@ public: SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, SHADER_VERSION_LIGHTMAP_COLOR_PASS, SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, + + SHADER_VERSION_DEPTH_PASS_MULTIVIEW, + SHADER_VERSION_COLOR_PASS_MULTIVIEW, + SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, + SHADER_VERSION_MAX }; @@ -71,6 +76,13 @@ public: PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS, PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR, PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS, + + PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW, + PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW, + PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW, + PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW, + PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW, + PIPELINE_VERSION_MAX }; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 957b490664..99584ad757 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -315,7 +315,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -332,7 +332,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -346,7 +346,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } u.append_id(texture); uniforms.push_back(u); @@ -358,7 +358,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } @@ -369,12 +369,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = storage->lightmap_get_texture(base); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); } else { u.append_id(default_tex); @@ -390,7 +390,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.resize(MAX_VOXEL_GI_INSTANCESS); - RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (i < (int)p_voxel_gi_instances.size()) { RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]); @@ -421,7 +421,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); u.append_id(texture); uniforms.push_back(u); } @@ -430,7 +430,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 38234cf0e7..9a1c4505fa 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -358,7 +358,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI bool use_normal; bool use_specular; - bool success = storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); + bool success = canvas_texture_storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); //something odd happened if (!success) { _bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size); @@ -694,9 +694,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend _bind_canvas_texture(p_draw_list, RID(), current_filter, current_repeat, last_texture, push_constant, texpixel_size); - RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3, primitive->point_count) - 1]); + RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]); - for (uint32_t j = 0; j < MIN(3, primitive->point_count); j++) { + for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) { push_constant.points[j * 2 + 0] = primitive->points[j].x; push_constant.points[j * 2 + 1] = primitive->points[j].y; push_constant.uvs[j * 2 + 0] = primitive->uvs[j].x; @@ -977,7 +977,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo } else { screen = storage->render_target_get_rd_backbuffer(p_to_render_target); if (screen.is_null()) { //unallocated backbuffer - screen = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + screen = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } } u.append_id(screen); @@ -2245,6 +2245,8 @@ void RendererCanvasRenderRD::update() { } RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { + canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton(); + texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_storage; { //create default samplers @@ -2575,8 +2577,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); } - default_canvas_texture = storage->canvas_texture_allocate(); - storage->canvas_texture_initialize(default_canvas_texture); + default_canvas_texture = canvas_texture_storage->canvas_texture_allocate(); + canvas_texture_storage->canvas_texture_initialize(default_canvas_texture); state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size"); @@ -2696,6 +2698,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() { } RD::get_singleton()->free(state.shadow_texture); - storage->free(default_canvas_texture); + canvas_texture_storage->canvas_texture_free(default_canvas_texture); //pipelines don't need freeing, they are all gone after shaders are gone } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 84f64b6fda..c0138c4fe0 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -37,10 +37,14 @@ #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" class RendererCanvasRenderRD : public RendererCanvasRender { + RendererRD::CanvasTextureStorage *canvas_texture_storage; + RendererRD::TextureStorage *texture_storage; RendererStorageRD *storage; enum { diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index e8978e7dca..bbd1498417 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -46,7 +46,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID for (int i = 0; i < p_amount; i++) { RID texture = storage->render_target_get_texture(p_render_targets[i].render_target); ERR_CONTINUE(texture.is_null()); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); ERR_CONTINUE(rd_texture.is_null()); // TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in. @@ -155,6 +155,8 @@ void RendererCompositorRD::finalize() { memdelete(scene); memdelete(canvas); memdelete(storage); + memdelete(texture_storage); + memdelete(canvas_texture_storage); //only need to erase these, the rest are erased by cascade blit.shader.version_free(blit.shader_version); @@ -165,9 +167,9 @@ void RendererCompositorRD::finalize() { void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { RD::get_singleton()->prepare_screen_for_drawing(); - RID texture = storage->texture_allocate(); - storage->texture_2d_initialize(texture, p_image); - RID rd_texture = storage->texture_get_rd_texture(texture); + RID texture = texture_storage->texture_allocate(); + texture_storage->texture_2d_initialize(texture, p_image); + RID rd_texture = texture_storage->texture_get_rd_texture(texture); RID uset; { @@ -235,7 +237,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->swap_buffers(); - storage->free(texture); + texture_storage->texture_free(texture); } RendererCompositorRD *RendererCompositorRD::singleton = nullptr; @@ -283,6 +285,8 @@ RendererCompositorRD::RendererCompositorRD() { singleton = this; time = 0; + canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage); + texture_storage = memnew(RendererRD::TextureStorage); storage = memnew(RendererStorageRD); canvas = memnew(RendererCanvasRenderRD(storage)); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index e526b95677..07df38b2b2 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -39,12 +39,16 @@ #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" class RendererCompositorRD : public RendererCompositor { protected: UniformSetCacheRD *uniform_set_cache; RendererCanvasRenderRD *canvas; + RendererRD::CanvasTextureStorage *canvas_texture_storage; + RendererRD::TextureStorage *texture_storage; RendererStorageRD *storage; RendererSceneRenderRD *scene; @@ -88,6 +92,8 @@ protected: static uint64_t frame; public: + RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; }; + RendererTextureStorage *get_texture_storage() { return texture_storage; }; RendererStorage *get_storage() { return storage; } RendererCanvasRender *get_canvas() { return canvas; } RendererSceneRender *get_scene() { return scene; } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 8f0e1d36db..7d79bf7707 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -40,6 +40,7 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF // SDFGI void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_gi->storage; gi = p_gi; num_cascades = p_env->sdfgi_cascades; @@ -377,7 +378,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -620,7 +621,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -633,7 +634,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -646,7 +647,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -659,7 +660,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1108,6 +1109,8 @@ void RendererSceneGIRD::SDFGI::update_cascades() { } void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) { Vector<RD::Uniform> uniforms; { @@ -1118,7 +1121,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1131,7 +1134,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1144,7 +1147,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1157,7 +1160,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -2807,6 +2810,8 @@ RendererSceneGIRD::~RendererSceneGIRD() { } void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + storage = p_storage; /* GI */ @@ -2924,7 +2929,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); uniforms.push_back(u); } { @@ -3023,6 +3028,8 @@ RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironme } void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + r_voxel_gi_instances_used = 0; // feels a little dirty to use our container this way but.... @@ -3085,7 +3092,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra } if (texture == RID()) { - texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } if (texture != rb->gi.voxel_gi_textures[i]) { @@ -3121,6 +3128,8 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra } void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RD::get_singleton()->draw_command_begin_label("GI Render"); RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); @@ -3186,7 +3195,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].sdf_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3199,7 +3208,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3212,7 +3221,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3225,7 +3234,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3237,7 +3246,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi) { u.append_id(rb->sdfgi->occlusion_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -3279,7 +3288,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ if (rb->sdfgi) { u.append_id(rb->sdfgi->lightprobe_texture); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } uniforms.push_back(u); } @@ -3301,7 +3310,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 14; - RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); u.append_id(buffer); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index f2d1a17099..d51b1bf691 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -45,6 +45,7 @@ #include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 6296e10962..ad9b2e62fa 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1666,8 +1666,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { if (i == 1) { // next 2 are half size - tf.width = MAX(1, tf.width >> 1); - tf.height = MAX(1, tf.height >> 1); + tf.width = MAX(1u, tf.width >> 1); + tf.height = MAX(1u, tf.height >> 1); } } @@ -2490,7 +2490,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.exposure_texture = rb->luminance.current; tonemap.auto_exposure_grey = env->auto_exp_scale; } else { - tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } if (can_use_effects && env && env->glow_enabled) { @@ -2506,15 +2506,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.glow_texture = rb->blur[1].texture; if (env->glow_map.is_valid()) { tonemap.glow_map_strength = env->glow_map_strength; - tonemap.glow_map = storage->texture_get_rd_texture(env->glow_map); + tonemap.glow_map = texture_storage->texture_get_rd_texture(env->glow_map); } else { tonemap.glow_map_strength = 0.0f; - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } } else { - tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { @@ -2536,7 +2536,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); if (can_use_effects && env) { tonemap.use_bcs = env->adjustments_enabled; @@ -2546,7 +2546,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (env->adjustments_enabled && env->color_correction.is_valid()) { tonemap.use_color_correction = true; tonemap.use_1d_color_correction = env->use_1d_color_correction; - tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction); } } @@ -2606,14 +2606,14 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr } tonemap.use_glow = false; - tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_auto_exposure = false; - tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); if (can_use_effects && env) { tonemap.use_bcs = env->adjustments_enabled; @@ -2623,7 +2623,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr if (env->adjustments_enabled && env->color_correction.is_valid()) { tonemap.use_color_correction = true; tonemap.use_1d_color_correction = env->use_1d_color_correction; - tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction); } } @@ -2656,7 +2656,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); if (shadow_atlas_texture.is_null()) { - shadow_atlas_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); } Size2 rtsize = storage->render_target_get_size(rb->render_target); @@ -2716,7 +2716,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { if (p_occlusion_buffer.is_valid()) { Size2 rtsize = storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); + effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); } } } @@ -4364,7 +4364,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e u.binding = 1; ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } else { u.append_id(shadow_atlas->depth); } @@ -4380,7 +4380,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e if (directional_shadow.depth.is_valid()) { u.append_id(directional_shadow.depth); } else { - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); copy_uniforms.push_back(u); @@ -4545,7 +4545,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 19; - RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID(); u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); uniforms.push_back(u); @@ -5600,6 +5600,7 @@ uint32_t RendererSceneRenderRD::get_max_elements() const { } RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { + texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_storage; singleton = this; } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 4a86ced322..e302db2631 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -41,6 +41,7 @@ #include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -92,6 +93,7 @@ class RendererSceneRenderRD : public RendererSceneRender { friend RendererSceneGIRD; protected: + RendererRD::TextureStorage *texture_storage; RendererStorageRD *storage; double time; double time_step = 0; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index d39fe306f4..1785a6b180 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -33,6 +33,7 @@ #include "core/math/math_defs.h" #include "renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" //////////////////////////////////////////////////////////////////////////////// @@ -362,8 +363,8 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6, j, 1, RD::TEXTURE_SLICE_CUBEMAP); - mmw = MAX(1, mmw >> 1); - mmh = MAX(1, mmh >> 1); + mmw = MAX(1u, mmw >> 1); + mmh = MAX(1u, mmh >> 1); } layers.push_back(layer); @@ -390,8 +391,8 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, j, 1, RD::TEXTURE_SLICE_CUBEMAP); - mmw = MAX(1, mmw >> 1); - mmh = MAX(1, mmh >> 1); + mmw = MAX(1u, mmw >> 1); + mmh = MAX(1u, mmh >> 1); } layers.push_back(layer); @@ -432,8 +433,8 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR } } - mmw = MAX(1, mmw >> 1); - mmh = MAX(1, mmh >> 1); + mmw = MAX(1u, mmw >> 1); + mmh = MAX(1u, mmh >> 1); } } } @@ -621,6 +622,8 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) { } RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) { return texture_uniform_sets[p_version]; } @@ -632,7 +635,7 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { u.append_id(radiance); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } uniforms.push_back(u); } @@ -648,9 +651,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -667,9 +670,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -793,6 +796,7 @@ RendererSceneSkyRD::RendererSceneSkyRD() { } void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); storage = p_storage; { @@ -972,7 +976,7 @@ void sky() { RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); u.append_id(vfog); uniforms.push_back(u); } @@ -1006,21 +1010,21 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } @@ -1170,7 +1174,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b sky_light_data.direction[0] = world_direction.x; sky_light_data.direction[1] = world_direction.y; - sky_light_data.direction[2] = -world_direction.z; + sky_light_data.direction[2] = world_direction.z; float sign = storage->light_is_negative(base) ? -1 : 1; sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index e4ddc1b41f..2a17a86e42 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -35,1114 +35,13 @@ #include "core/io/resource_loader.h" #include "core/math/math_defs.h" #include "renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_globals.h" #include "servers/rendering/shader_language.h" -bool RendererStorageRD::can_create_resources_async() const { - return true; -} - -Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { - Ref<Image> image = p_image->duplicate(); - - switch (p_image->get_format()) { - case Image::FORMAT_L8: { - r_format.format = RD::DATA_FORMAT_R8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //luminance - case Image::FORMAT_LA8: { - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; - } break; //luminance-alpha - case Image::FORMAT_R8: { - r_format.format = RD::DATA_FORMAT_R8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RG8: { - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGB8: { - //this format is not mandatory for specification, check if supported first - if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGBA8: { - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RGBA4444: { - r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RGB565: { - r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RF: { - r_format.format = RD::DATA_FORMAT_R32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //float - case Image::FORMAT_RGF: { - r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBF: { - //this format is not mandatory for specification, check if supported first - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - image->convert(Image::FORMAT_RGBAF); - } - - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBAF: { - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; - case Image::FORMAT_RH: { - r_format.format = RD::DATA_FORMAT_R16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //half float - case Image::FORMAT_RGH: { - r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGBH: { - //this format is not mandatory for specification, check if supported first - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->convert(Image::FORMAT_RGBAH); - } - - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBAH: { - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; - case Image::FORMAT_RGBE9995: { - r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; -#ifndef _MSC_VER -#warning TODO need to make a function in Image to swap bits for this -#endif - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; - } break; - case Image::FORMAT_DXT1: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //s3tc bc1 - case Image::FORMAT_DXT3: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; //bc2 - case Image::FORMAT_DXT5: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; //bc3 - case Image::FORMAT_RGTC_R: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGTC_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_BPTC_RGBA: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; //btpc bc7 - case Image::FORMAT_BPTC_RGBF: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->decompress(); - image->convert(Image::FORMAT_RGBAH); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //float bc6h - case Image::FORMAT_BPTC_RGBFU: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->decompress(); - image->convert(Image::FORMAT_RGBAH); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //unsigned float bc6hu - case Image::FORMAT_ETC2_R11: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //etc2 - case Image::FORMAT_ETC2_R11S: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_SNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //signed: {} break; NOT srgb. - case Image::FORMAT_ETC2_RG11: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_ETC2_RG11S: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_SNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_ETC: - case Image::FORMAT_ETC2_RGB8: { - //ETC2 is backwards compatible with ETC1, and all modern platforms support it - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_ETC2_RGBA8: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_RGB8A1: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_RA_AS_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_DXT5_RA_AS_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - - default: { - } - } - - return image; -} - -RID RendererStorageRD::texture_allocate() { - return texture_owner.allocate_rid(); -} - -void RendererStorageRD::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(p_image->is_empty()); - - TextureToRDFormat ret_format; - Ref<Image> image = _validate_texture_format(p_image, ret_format); - - Texture texture; - - texture.type = Texture::TYPE_2D; - - texture.width = p_image->get_width(); - texture.height = p_image->get_height(); - texture.layers = 1; - texture.mipmaps = p_image->get_mipmap_count() + 1; - texture.depth = 1; - texture.format = p_image->get_format(); - texture.validated_format = image->get_format(); - - texture.rd_type = RD::TEXTURE_TYPE_2D; - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = 1; - rd_format.array_layers = 1; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<uint8_t> data = image->get_data(); //use image data - Vector<Vector<uint8_t>> data_slices; - data_slices.push_back(data); - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { - ERR_FAIL_COND(p_layers.size() == 0); - - ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6); - ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0)); - - TextureToRDFormat ret_format; - Vector<Ref<Image>> images; - { - int valid_width = 0; - int valid_height = 0; - bool valid_mipmaps = false; - Image::Format valid_format = Image::FORMAT_MAX; - - for (int i = 0; i < p_layers.size(); i++) { - ERR_FAIL_COND(p_layers[i]->is_empty()); - - if (i == 0) { - valid_width = p_layers[i]->get_width(); - valid_height = p_layers[i]->get_height(); - valid_format = p_layers[i]->get_format(); - valid_mipmaps = p_layers[i]->has_mipmaps(); - } else { - ERR_FAIL_COND(p_layers[i]->get_width() != valid_width); - ERR_FAIL_COND(p_layers[i]->get_height() != valid_height); - ERR_FAIL_COND(p_layers[i]->get_format() != valid_format); - ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps); - } - - images.push_back(_validate_texture_format(p_layers[i], ret_format)); - } - } - - Texture texture; - - texture.type = Texture::TYPE_LAYERED; - texture.layered_type = p_layered_type; - - texture.width = p_layers[0]->get_width(); - texture.height = p_layers[0]->get_height(); - texture.layers = p_layers.size(); - texture.mipmaps = p_layers[0]->get_mipmap_count() + 1; - texture.depth = 1; - texture.format = p_layers[0]->get_format(); - texture.validated_format = images[0]->get_format(); - - switch (p_layered_type) { - case RS::TEXTURE_LAYERED_2D_ARRAY: { - texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY; - } break; - case RS::TEXTURE_LAYERED_CUBEMAP: { - texture.rd_type = RD::TEXTURE_TYPE_CUBE; - } break; - case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: { - texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY; - } break; - } - - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = 1; - rd_format.array_layers = texture.layers; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<Vector<uint8_t>> data_slices; - for (int i = 0; i < images.size(); i++) { - Vector<uint8_t> data = images[i]->get_data(); //use image data - data_slices.push_back(data); - } - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { - ERR_FAIL_COND(p_data.size() == 0); - Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); - if (verr != Image::VALIDATE_3D_OK) { - ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); - } - - TextureToRDFormat ret_format; - Image::Format validated_format = Image::FORMAT_MAX; - Vector<uint8_t> all_data; - uint32_t mipmap_count = 0; - Vector<Texture::BufferSlice3D> slices; - { - Vector<Ref<Image>> images; - uint32_t all_data_size = 0; - images.resize(p_data.size()); - for (int i = 0; i < p_data.size(); i++) { - TextureToRDFormat f; - images.write[i] = _validate_texture_format(p_data[i], f); - if (i == 0) { - ret_format = f; - validated_format = images[0]->get_format(); - } - - all_data_size += images[i]->get_data().size(); - } - - all_data.resize(all_data_size); //consolidate all data here - uint32_t offset = 0; - Size2i prev_size; - for (int i = 0; i < p_data.size(); i++) { - uint32_t s = images[i]->get_data().size(); - - memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); - { - Texture::BufferSlice3D slice; - slice.size.width = images[i]->get_width(); - slice.size.height = images[i]->get_height(); - slice.offset = offset; - slice.buffer_size = s; - slices.push_back(slice); - } - offset += s; - - Size2i img_size(images[i]->get_width(), images[i]->get_height()); - if (img_size != prev_size) { - mipmap_count++; - } - prev_size = img_size; - } - } - - Texture texture; - - texture.type = Texture::TYPE_3D; - texture.width = p_width; - texture.height = p_height; - texture.depth = p_depth; - texture.mipmaps = mipmap_count; - texture.format = p_data[0]->get_format(); - texture.validated_format = validated_format; - - texture.buffer_size_3d = all_data.size(); - texture.buffer_slices_3d = slices; - - texture.rd_type = RD::TEXTURE_TYPE_3D; - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = texture.depth; - rd_format.array_layers = 1; - rd_format.mipmaps = texture.mipmaps; - rd_format.texture_type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector<Vector<uint8_t>> data_slices; - data_slices.push_back(all_data); //one slice - - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND(texture.rd_texture.is_null()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - texture_owner.initialize_rid(p_texture, texture); -} - -void RendererStorageRD::texture_proxy_initialize(RID p_texture, RID p_base) { - Texture *tex = texture_owner.get_or_null(p_base); - ERR_FAIL_COND(!tex); - Texture proxy_tex = *tex; - - proxy_tex.rd_view.format_override = tex->rd_format; - proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); - if (proxy_tex.rd_texture_srgb.is_valid()) { - proxy_tex.rd_view.format_override = tex->rd_format_srgb; - proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); - } - proxy_tex.proxy_to = p_base; - proxy_tex.is_render_target = false; - proxy_tex.is_proxy = true; - proxy_tex.proxies.clear(); - - texture_owner.initialize_rid(p_texture, proxy_tex); - - tex->proxies.push_back(p_texture); -} - -void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) { - ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); - - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->is_render_target); - ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); - ERR_FAIL_COND(p_image->get_format() != tex->format); - - if (tex->type == Texture::TYPE_LAYERED) { - ERR_FAIL_INDEX(p_layer, tex->layers); - } - -#ifdef TOOLS_ENABLED - tex->image_cache_2d.unref(); -#endif - TextureToRDFormat f; - Ref<Image> validated = _validate_texture_format(p_image, f); - - RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data()); -} - -void RendererStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { - _texture_2d_update(p_texture, p_image, p_layer, false); -} - -void RendererStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_3D); - Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); - if (verr != Image::VALIDATE_3D_OK) { - ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); - } - - Vector<uint8_t> all_data; - { - Vector<Ref<Image>> images; - uint32_t all_data_size = 0; - images.resize(p_data.size()); - for (int i = 0; i < p_data.size(); i++) { - Ref<Image> image = p_data[i]; - if (image->get_format() != tex->validated_format) { - image = image->duplicate(); - image->convert(tex->validated_format); - } - all_data_size += images[i]->get_data().size(); - images.push_back(image); - } - - all_data.resize(all_data_size); //consolidate all data here - uint32_t offset = 0; - - for (int i = 0; i < p_data.size(); i++) { - uint32_t s = images[i]->get_data().size(); - memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); - offset += s; - } - } - - RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data); -} - -void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(!tex->is_proxy); - Texture *proxy_to = texture_owner.get_or_null(p_proxy_to); - ERR_FAIL_COND(!proxy_to); - ERR_FAIL_COND(proxy_to->is_proxy); - - if (tex->proxy_to.is_valid()) { - //unlink proxy - if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { - RD::get_singleton()->free(tex->rd_texture); - tex->rd_texture = RID(); - } - if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { - RD::get_singleton()->free(tex->rd_texture_srgb); - tex->rd_texture_srgb = RID(); - } - Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to); - ERR_FAIL_COND(!prev_tex); - prev_tex->proxies.erase(p_texture); - } - - *tex = *proxy_to; - - tex->proxy_to = p_proxy_to; - tex->is_render_target = false; - tex->is_proxy = true; - tex->proxies.clear(); - proxy_to->proxies.push_back(p_texture); - - tex->rd_view.format_override = tex->rd_format; - tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); - if (tex->rd_texture_srgb.is_valid()) { - tex->rd_view.format_override = tex->rd_format_srgb; - tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); - } -} - -//these two APIs can be used together or in combination with the others. -void RendererStorageRD::texture_2d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - texture_2d_initialize(p_texture, image); -} - -void RendererStorageRD::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; - if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { - images.push_back(image); - } else { - //cube - for (int i = 0; i < 6; i++) { - images.push_back(image); - } - } - - texture_2d_layered_initialize(p_texture, images, p_layered_type); -} - -void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) { - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - image->fill(Color(1, 0, 1, 1)); - - Vector<Ref<Image>> images; - //cube - for (int i = 0; i < 4; i++) { - images.push_back(image); - } - - texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images); -} - -Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - -#ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid() && !tex->is_render_target) { - return tex->image_cache_2d; - } -#endif - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) { - tex->image_cache_2d = image; - } -#endif - - return image; -} - -Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); - - Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); - ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - - return image; -} - -Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); - ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); - - Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - - ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>()); - - Vector<Ref<Image>> ret; - - for (int i = 0; i < tex->buffer_slices_3d.size(); i++) { - const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i]; - ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>()); - ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>()); - Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size); - - Ref<Image> img; - img.instantiate(); - img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); - ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>()); - if (tex->format != tex->validated_format) { - img->convert(tex->format); - } - - ret.push_back(img); - } - - return ret; -} - -void RendererStorageRD::texture_replace(RID p_texture, RID p_by_texture) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy - Texture *by_tex = texture_owner.get_or_null(p_by_texture); - ERR_FAIL_COND(!by_tex); - ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy - - if (tex == by_tex) { - return; - } - - if (tex->rd_texture_srgb.is_valid()) { - RD::get_singleton()->free(tex->rd_texture_srgb); - } - RD::get_singleton()->free(tex->rd_texture); - - if (tex->canvas_texture) { - memdelete(tex->canvas_texture); - tex->canvas_texture = nullptr; - } - - Vector<RID> proxies_to_update = tex->proxies; - Vector<RID> proxies_to_redirect = by_tex->proxies; - - *tex = *by_tex; - - tex->proxies = proxies_to_update; //restore proxies, so they can be updated - - if (tex->canvas_texture) { - tex->canvas_texture->diffuse = p_texture; //update - } - - for (int i = 0; i < proxies_to_update.size(); i++) { - texture_proxy_update(proxies_to_update[i], p_texture); - } - for (int i = 0; i < proxies_to_redirect.size(); i++) { - texture_proxy_update(proxies_to_redirect[i], p_texture); - } - //delete last, so proxies can be updated - texture_owner.free(p_by_texture); - - if (decal_atlas.textures.has(p_texture)) { - //belongs to decal atlas.. - - decal_atlas.dirty = true; //mark it dirty since it was most likely modified - } -} - -void RendererStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_2D); - tex->width_2d = p_width; - tex->height_2d = p_height; -} - -void RendererStorageRD::texture_set_path(RID p_texture, const String &p_path) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->path = p_path; -} - -String RendererStorageRD::texture_get_path(RID p_texture) const { - return String(); -} - -void RendererStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_3d_callback_ud = p_userdata; - tex->detect_3d_callback = p_callback; -} - -void RendererStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_normal_callback_ud = p_userdata; - tex->detect_normal_callback = p_callback; -} - -void RendererStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_roughness_callback_ud = p_userdata; - tex->detect_roughness_callback = p_callback; -} - -void RendererStorageRD::texture_debug_usage(List<RS::TextureInfo> *r_info) { -} - -void RendererStorageRD::texture_set_proxy(RID p_proxy, RID p_base) { -} - -void RendererStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { -} - -Size2 RendererStorageRD::texture_size_with_proxy(RID p_proxy) { - return texture_2d_get_size(p_proxy); -} - /* CANVAS TEXTURE */ -void RendererStorageRD::CanvasTexture::clear_sets() { - if (cleared_cache) { - return; - } - for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) { - RD::get_singleton()->free(uniform_sets[i][j]); - uniform_sets[i][j] = RID(); - } - } - } - cleared_cache = true; -} - -RendererStorageRD::CanvasTexture::~CanvasTexture() { - clear_sets(); -} - void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { @@ -1237,149 +136,6 @@ void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { } } -RID RendererStorageRD::canvas_texture_allocate() { - return canvas_texture_owner.allocate_rid(); -} -void RendererStorageRD::canvas_texture_initialize(RID p_rid) { - canvas_texture_owner.initialize_rid(p_rid); -} - -void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - switch (p_channel) { - case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { - ct->diffuse = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { - ct->normal_map = p_texture; - } break; - case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { - ct->specular = p_texture; - } break; - } - - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->specular_color.r = p_specular_color.r; - ct->specular_color.g = p_specular_color.g; - ct->specular_color.b = p_specular_color.b; - ct->specular_color.a = p_shininess; - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_filter = p_filter; - ct->clear_sets(); -} - -void RendererStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { - CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); - ct->texture_repeat = p_repeat; - ct->clear_sets(); -} - -bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { - CanvasTexture *ct = nullptr; - - Texture *t = texture_owner.get_or_null(p_texture); - - if (t) { - //regular texture - if (!t->canvas_texture) { - t->canvas_texture = memnew(CanvasTexture); - t->canvas_texture->diffuse = p_texture; - } - - ct = t->canvas_texture; - } else { - ct = canvas_texture_owner.get_or_null(p_texture); - } - - if (!ct) { - return false; //invalid texture RID - } - - RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter; - ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false); - - RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; - ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false); - - RID uniform_set = ct->uniform_sets[filter][repeat]; - if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //create and update - Vector<RD::Uniform> uniforms; - { //diffuse - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - - t = texture_owner.get_or_null(ct->diffuse); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); - ct->size_cache = Size2i(1, 1); - } else { - u.append_id(t->rd_texture); - ct->size_cache = Size2i(t->width_2d, t->height_2d); - } - uniforms.push_back(u); - } - { //normal - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - - t = texture_owner.get_or_null(ct->normal_map); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); - ct->use_normal_cache = false; - } else { - u.append_id(t->rd_texture); - ct->use_normal_cache = true; - } - uniforms.push_back(u); - } - { //specular - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - - t = texture_owner.get_or_null(ct->specular); - if (!t) { - u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); - ct->use_specular_cache = false; - } else { - u.append_id(t->rd_texture); - ct->use_specular_cache = true; - } - uniforms.push_back(u); - } - { //sampler - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 3; - u.append_id(sampler_rd_get_default(filter, repeat)); - uniforms.push_back(u); - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set); - ct->uniform_sets[filter][repeat] = uniform_set; - ct->cleared_cache = false; - } - - r_uniform_set = uniform_set; - r_size = ct->size_cache; - r_specular_shininess = ct->specular_color; - r_use_normal = ct->use_normal_cache; - r_use_specular = ct->use_specular_cache; - - return true; -} - /* SHADER API */ RID RendererStorageRD::shader_allocate() { @@ -1487,7 +243,7 @@ void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const Str Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); - if (p_texture.is_valid() && texture_owner.owns(p_texture)) { + if (p_texture.is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(p_texture)) { if (!shader->default_texture_parameter.has(p_name)) { shader->default_texture_parameter[p_name] = Map<int, RID>(); } @@ -2642,11 +1398,12 @@ RendererStorageRD::MaterialData::~MaterialData() { } void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { - RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton; + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + #ifdef TOOLS_ENABLED - Texture *roughness_detect_texture = nullptr; + RendererRD::Texture *roughness_detect_texture = nullptr; RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; - Texture *normal_detect_texture = nullptr; + RendererRD::Texture *normal_detect_texture = nullptr; #endif bool uses_global_textures = false; @@ -2732,19 +1489,19 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari switch (p_texture_uniforms[i].hint) { case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_ANISO); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); } break; default: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } break; } } break; @@ -2753,27 +1510,27 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari switch (p_texture_uniforms[i].hint) { case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } break; default: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); } break; } } break; case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); } break; case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: case ShaderLanguage::TYPE_SAMPLER3D: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } break; case ShaderLanguage::TYPE_ISAMPLER2DARRAY: case ShaderLanguage::TYPE_USAMPLER2DARRAY: case ShaderLanguage::TYPE_SAMPLER2DARRAY: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } break; default: { @@ -2795,7 +1552,7 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); for (int j = 0; j < textures.size(); j++) { - Texture *tex = singleton->texture_owner.get_or_null(textures[j]); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(textures[j]); if (tex) { rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; @@ -2817,7 +1574,7 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari #endif } if (rd_texture.is_null()) { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); } #ifdef TOOLS_ENABLED if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { @@ -4946,6 +3703,8 @@ void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool } void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) { Vector<RD::Uniform> uniforms; @@ -5248,14 +4007,14 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { RID rd_tex; if (i < collision_3d_textures_used) { - Texture *t = texture_owner.get_or_null(collision_3d_textures[i]); - if (t && t->type == Texture::TYPE_3D) { + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]); + if (t && t->type == RendererRD::Texture::TYPE_3D) { rd_tex = t->rd_texture; } } if (rd_tex == RID()) { - rd_tex = default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE]; + rd_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(rd_tex); } @@ -5268,7 +4027,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt if (collision_heightmap_texture.is_valid()) { u.append_id(collision_heightmap_texture); } else { - u.append_id(default_rd_textures[DEFAULT_RD_TEXTURE_BLACK]); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); } @@ -6991,9 +5750,9 @@ void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, return; } - ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); + ERR_FAIL_COND(p_texture.is_valid() && !RendererRD::TextureStorage::get_singleton()->owns_texture(p_texture)); - if (decal->textures[p_type].is_valid() && texture_owner.owns(decal->textures[p_type])) { + if (decal->textures[p_type].is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(decal->textures[p_type])) { texture_remove_from_decal_atlas(decal->textures[p_type]); } @@ -7398,6 +6157,8 @@ void RendererStorageRD::lightmap_initialize(RID p_lightmap) { } void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); ERR_FAIL_COND(!lm); @@ -7405,17 +6166,17 @@ void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool //erase lightmap users if (lm->light_texture.is_valid()) { - Texture *t = texture_owner.get_or_null(lm->light_texture); + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture); if (t) { t->lightmap_users.erase(p_lightmap); } } - Texture *t = texture_owner.get_or_null(p_light); + RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light); lm->light_texture = p_light; lm->uses_spherical_harmonics = p_uses_spherical_haromics; - RID default_2d_array = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE]; + RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); if (!t) { if (using_lightmap_array) { if (lm->array_index >= 0) { @@ -7593,9 +6354,9 @@ void RendererStorageRD::_clear_render_target(RenderTarget *rt) { void RendererStorageRD::_update_render_target(RenderTarget *rt) { if (rt->texture.is_null()) { //create a placeholder until updated - rt->texture = texture_allocate(); - texture_2d_placeholder_initialize(rt->texture); - Texture *tex = texture_owner.get_or_null(rt->texture); + rt->texture = RendererRD::TextureStorage::get_singleton()->texture_allocate(); + RendererRD::TextureStorage::get_singleton()->texture_2d_placeholder_initialize(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); tex->is_render_target = true; } @@ -7642,7 +6403,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) { { //update texture - Texture *tex = texture_owner.get_or_null(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); //free existing textures if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { @@ -7678,7 +6439,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) { Vector<RID> proxies = tex->proxies; //make a copy, since update may change it for (int i = 0; i < proxies.size(); i++) { - texture_proxy_update(proxies[i], rt->texture); + RendererRD::TextureStorage::get_singleton()->texture_proxy_update(proxies[i], rt->texture); } } } @@ -8341,6 +7102,21 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { return RS::INSTANCE_NONE; } +void RendererStorageRD::decal_atlas_remove_texture(RID p_texture) { + if (decal_atlas.textures.has(p_texture)) { + decal_atlas.textures.erase(p_texture); + //there is not much a point of making it dirty, just let it be. + } +} + +void RendererStorageRD::decal_atlas_mark_dirty_on_texture(RID p_texture) { + if (decal_atlas.textures.has(p_texture)) { + //belongs to decal atlas.. + + decal_atlas.dirty = true; //mark it dirty since it was most likely modified + } +} + void RendererStorageRD::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) { if (!decal_atlas.textures.has(p_texture)) { DecalAtlas::Texture t; @@ -8406,7 +7182,7 @@ void RendererStorageRD::_update_decal_atlas() { while ((K = decal_atlas.textures.next(K))) { DecalAtlas::SortItem &si = itemsv.write[idx]; - Texture *src_tex = texture_owner.get_or_null(*K); + RendererRD::Texture *src_tex = RendererRD::TextureStorage::get_singleton()->get_texture(*K); si.size.width = (src_tex->width / border) + 1; si.size.height = (src_tex->height / border) + 1; @@ -8555,7 +7331,7 @@ void RendererStorageRD::_update_decal_atlas() { const RID *K = nullptr; while ((K = decal_atlas.textures.next(K))) { DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K); - Texture *src_tex = texture_owner.get_or_null(*K); + RendererRD::Texture *src_tex = RendererRD::TextureStorage::get_singleton()->get_texture(*K); effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0); } @@ -9265,47 +8041,10 @@ bool RendererStorageRD::has_os_feature(const String &p_feature) const { } bool RendererStorageRD::free(RID p_rid) { - if (texture_owner.owns(p_rid)) { - Texture *t = texture_owner.get_or_null(p_rid); - - ERR_FAIL_COND_V(!t, false); - ERR_FAIL_COND_V(t->is_render_target, false); - - if (RD::get_singleton()->texture_is_valid(t->rd_texture_srgb)) { - //erase this first, as it's a dependency of the one below - RD::get_singleton()->free(t->rd_texture_srgb); - } - if (RD::get_singleton()->texture_is_valid(t->rd_texture)) { - RD::get_singleton()->free(t->rd_texture); - } - - if (t->is_proxy && t->proxy_to.is_valid()) { - Texture *proxy_to = texture_owner.get_or_null(t->proxy_to); - if (proxy_to) { - proxy_to->proxies.erase(p_rid); - } - } - - if (decal_atlas.textures.has(p_rid)) { - decal_atlas.textures.erase(p_rid); - //there is not much a point of making it dirty, just let it be. - } - - for (int i = 0; i < t->proxies.size(); i++) { - Texture *p = texture_owner.get_or_null(t->proxies[i]); - ERR_CONTINUE(!p); - p->proxy_to = RID(); - p->rd_texture = RID(); - p->rd_texture_srgb = RID(); - } - - if (t->canvas_texture) { - memdelete(t->canvas_texture); - } - texture_owner.free(p_rid); - - } else if (canvas_texture_owner.owns(p_rid)) { - canvas_texture_owner.free(p_rid); + if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) { + RendererRD::TextureStorage::get_singleton()->texture_free(p_rid); + } else if (RendererRD::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { + RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid); } else if (shader_owner.owns(p_rid)) { Shader *shader = shader_owner.get_or_null(p_rid); //make material unreference this @@ -9367,7 +8106,7 @@ bool RendererStorageRD::free(RID p_rid) { } else if (decal_owner.owns(p_rid)) { Decal *decal = decal_owner.get_or_null(p_rid); for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) { - if (decal->textures[i].is_valid() && texture_owner.owns(decal->textures[i])) { + if (decal->textures[i].is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(decal->textures[i])) { texture_remove_from_decal_atlas(decal->textures[i]); } } @@ -9421,7 +8160,7 @@ bool RendererStorageRD::free(RID p_rid) { _clear_render_target(rt); if (rt->texture.is_valid()) { - Texture *tex = texture_owner.get_or_null(rt->texture); + RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture); tex->is_render_target = false; free(rt->texture); } @@ -9504,14 +8243,15 @@ RendererStorageRD *RendererStorageRD::base_singleton = nullptr; RendererStorageRD::RendererStorageRD() { base_singleton = this; + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + for (int i = 0; i < SHADER_TYPE_MAX; i++) { shader_data_request_func[i] = nullptr; } static_assert(sizeof(GlobalVariables::Value) == 16); - global_variables.buffer_size = GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"); - global_variables.buffer_size = MAX(4096, global_variables.buffer_size); + global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size); memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size); global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size); @@ -9519,8 +8259,7 @@ RendererStorageRD::RendererStorageRD() { memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size); - { //create default textures - + { // default atlas texture RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; tformat.width = 4; @@ -9530,18 +8269,6 @@ RendererStorageRD::RendererStorageRD() { Vector<uint8_t> pv; pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } for (int i = 0; i < 16; i++) { pv.set(i * 4 + 0, 0); @@ -9551,211 +8278,12 @@ RendererStorageRD::RendererStorageRD() { } { + //take the chance and initialize decal atlas to something Vector<Vector<uint8_t>> vpv; vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - - //take the chance and initialize decal atlas to something decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); decal_atlas.texture_srgb = decal_atlas.texture; } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 128); - pv.set(i * 4 + 1, 128); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 128); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT; - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap white array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_CUBE; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default 3D - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.depth = 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_3D; - - Vector<uint8_t> pv; - pv.resize(64 * 4); - for (int i = 0; i < 64; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - for (int i = 0; i < 64; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 1; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - - Vector<uint8_t> pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector<Vector<uint8_t>> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } } //default samplers @@ -9971,7 +8499,7 @@ RendererStorageRD::RendererStorageRD() { } for (int i = 0; i < lightmap_textures.size(); i++) { - lightmap_textures.write[i] = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE]; + lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } } @@ -10178,11 +8706,6 @@ RendererStorageRD::~RendererStorageRD() { memdelete_arr(global_variables.buffer_dirty_regions); RD::get_singleton()->free(global_variables.buffer); - //def textures - for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) { - RD::get_singleton()->free(default_rd_textures[i]); - } - //def samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 9416d04cdd..16f1b265a3 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -41,9 +41,12 @@ #include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" + class RendererStorageRD : public RendererStorage { public: static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { @@ -179,22 +182,6 @@ public: typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); static void _material_uniform_set_erased(void *p_material); - enum DefaultRDTexture { - DEFAULT_RD_TEXTURE_WHITE, - DEFAULT_RD_TEXTURE_BLACK, - DEFAULT_RD_TEXTURE_NORMAL, - DEFAULT_RD_TEXTURE_ANISO, - DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, - DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, - DEFAULT_RD_TEXTURE_3D_WHITE, - DEFAULT_RD_TEXTURE_3D_BLACK, - DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, - DEFAULT_RD_TEXTURE_2D_UINT, - DEFAULT_RD_TEXTURE_MAX - }; - enum DefaultRDBuffer { DEFAULT_RD_BUFFER_VERTEX, DEFAULT_RD_BUFFER_NORMAL, @@ -212,113 +199,8 @@ public: }; private: - /* CANVAS TEXTURE API (2D) */ - - struct CanvasTexture { - RID diffuse; - RID normal_map; - RID specular; - Color specular_color = Color(1, 1, 1, 1); - float shininess = 1.0; - - RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - - Size2i size_cache = Size2i(1, 1); - bool use_normal_cache = false; - bool use_specular_cache = false; - bool cleared_cache = true; - void clear_sets(); - ~CanvasTexture(); - }; - - RID_Owner<CanvasTexture, true> canvas_texture_owner; - /* TEXTURE API */ - struct Texture { - enum Type { - TYPE_2D, - TYPE_LAYERED, - TYPE_3D - }; - - Type type; - RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; - - RenderingDevice::TextureType rd_type; - RID rd_texture; - RID rd_texture_srgb; - RenderingDevice::DataFormat rd_format; - RenderingDevice::DataFormat rd_format_srgb; - RD::TextureView rd_view; - - Image::Format format; - Image::Format validated_format; - - int width; - int height; - int depth; - int layers; - int mipmaps; - - int height_2d; - int width_2d; - - struct BufferSlice3D { - Size2i size; - uint32_t offset = 0; - uint32_t buffer_size = 0; - }; - Vector<BufferSlice3D> buffer_slices_3d; - uint32_t buffer_size_3d = 0; - - bool is_render_target; - bool is_proxy; - - Ref<Image> image_cache_2d; - String path; - - RID proxy_to; - Vector<RID> proxies; - Set<RID> lightmap_users; - - RS::TextureDetectCallback detect_3d_callback = nullptr; - void *detect_3d_callback_ud = nullptr; - - RS::TextureDetectCallback detect_normal_callback = nullptr; - void *detect_normal_callback_ud = nullptr; - - RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; - void *detect_roughness_callback_ud = nullptr; - - CanvasTexture *canvas_texture = nullptr; - }; - - struct TextureToRDFormat { - RD::DataFormat format; - RD::DataFormat format_srgb; - RD::TextureSwizzle swizzle_r; - RD::TextureSwizzle swizzle_g; - RD::TextureSwizzle swizzle_b; - RD::TextureSwizzle swizzle_a; - TextureToRDFormat() { - format = RD::DATA_FORMAT_MAX; - format_srgb = RD::DATA_FORMAT_MAX; - swizzle_r = RD::TEXTURE_SWIZZLE_R; - swizzle_g = RD::TEXTURE_SWIZZLE_G; - swizzle_b = RD::TEXTURE_SWIZZLE_B; - swizzle_a = RD::TEXTURE_SWIZZLE_A; - } - }; - - //textures can be created from threads, so this RID_Owner is thread safe - mutable RID_Owner<Texture, true> texture_owner; - - Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format); - - RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; RID default_rd_storage_buffer; @@ -1308,52 +1190,6 @@ private: EffectsRD *effects = nullptr; public: - virtual bool can_create_resources_async() const; - - /* TEXTURE API */ - - virtual RID texture_allocate(); - - virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image); - virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type); - virtual void texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent - virtual void texture_proxy_initialize(RID p_texture, RID p_base); - - virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate); - - virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); - virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data); - virtual void texture_proxy_update(RID p_texture, RID p_proxy_to); - - //these two APIs can be used together or in combination with the others. - virtual void texture_2d_placeholder_initialize(RID p_texture); - virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type); - virtual void texture_3d_placeholder_initialize(RID p_texture); - - virtual Ref<Image> texture_2d_get(RID p_texture) const; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const; - - virtual void texture_replace(RID p_texture, RID p_by_texture); - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); - - virtual void texture_set_path(RID p_texture, const String &p_path); - virtual String texture_get_path(RID p_texture) const; - - virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata); - - virtual void texture_debug_usage(List<RS::TextureInfo> *r_info); - - virtual void texture_set_proxy(RID p_proxy, RID p_base); - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); - - virtual Size2 texture_size_with_proxy(RID p_proxy); - - virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); - virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); - RID decal_atlas_get_texture() const; RID decal_atlas_get_texture_srgb() const; _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) { @@ -1367,33 +1203,6 @@ public: //internal usage - _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { - if (p_texture.is_null()) { - return RID(); - } - Texture *tex = texture_owner.get_or_null(p_texture); - - if (!tex) { - return RID(); - } - return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; - } - - _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) { - if (p_texture.is_null()) { - return Size2i(); - } - Texture *tex = texture_owner.get_or_null(p_texture); - - if (!tex) { - return Size2i(); - } - return Size2i(tex->width_2d, tex->height_2d); - } - - _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { - return default_rd_textures[p_texture]; - } _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { return default_rd_samplers[p_filter][p_repeat]; } @@ -1405,19 +1214,6 @@ public: void sampler_rd_set_default(float p_mipmap_bias); - /* CANVAS TEXTURE API */ - - RID canvas_texture_allocate(); - void canvas_texture_initialize(RID p_canvas_texture); - - virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture); - virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess); - - virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter); - virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat); - - bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular); - /* SHADER API */ RID shader_allocate(); @@ -1926,7 +1722,7 @@ public: const Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); - return texture_owner.owns(light->projector); + return light_owner.owns(light->projector); } _FORCE_INLINE_ bool light_is_negative(RID p_light) const { @@ -2010,6 +1806,12 @@ public: virtual void decal_set_fade(RID p_decal, float p_above, float p_below); virtual void decal_set_normal_fade(RID p_decal, float p_fade); + void decal_atlas_mark_dirty_on_texture(RID p_texture); + void decal_atlas_remove_texture(RID p_texture); + + virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); + virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false); + _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) { const Decal *decal = decal_owner.get_or_null(p_decal); return decal->extents; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index a8648fc96a..f9cee011d2 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -99,6 +99,18 @@ layout(location = 8) out float dp_clip; layout(location = 9) out flat uint instance_index_interp; +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + invariant gl_Position; #GLOBALS @@ -244,7 +256,13 @@ void main() { vec4 position; #endif +#ifdef USE_MULTIVIEW + mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; + mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; +#else mat4 projection_matrix = scene_data.projection_matrix; + mat4 inv_projection_matrix = scene_data.inv_projection_matrix; +#endif //USE_MULTIVIEW //using world coordinates #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) @@ -421,10 +439,26 @@ layout(location = 8) in float dp_clip; layout(location = 9) in flat uint instance_index_interp; +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + //defines to keep compatibility with vertex #define world_matrix instances.data[instance_index].transform +#ifdef USE_MULTIVIEW +#define projection_matrix scene_data.projection_matrix_view[ViewIndex] +#else #define projection_matrix scene_data.projection_matrix +#endif #if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE) //both required for transmittance to be enabled diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index 3b110aded2..2e31503669 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -2,6 +2,7 @@ #define ROUGHNESS_MAX_LOD 5 #define MAX_VOXEL_GI_INSTANCES 8 +#define MAX_VIEWS 2 #if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) @@ -12,6 +13,10 @@ #endif +#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview) +#extension GL_EXT_multiview : enable +#endif + #include "cluster_data_inc.glsl" #include "decal_data_inc.glsl" @@ -169,10 +174,13 @@ sdfgi; layout(set = 1, binding = 0, std140) uniform SceneData { mat4 projection_matrix; mat4 inv_projection_matrix; - mat4 camera_matrix; mat4 inv_camera_matrix; + // only used for multiview + mat4 projection_matrix_view[MAX_VIEWS]; + mat4 inv_projection_matrix_view[MAX_VIEWS]; + vec2 viewport_size; vec2 screen_pixel_size; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index 1c9b08b6d3..bd1c2b5758 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -1,9 +1,9 @@ // Functions related to lighting float D_GGX(float cos_theta_m, float alpha) { - float alpha2 = alpha * alpha; - float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m; - return alpha2 / (M_PI * d * d); + float a = cos_theta_m * alpha; + float k = alpha / (1.0 - cos_theta_m * cos_theta_m + a * a); + return k * k * (1.0 / M_PI); } // From Earl Hammon, Jr. "PBR Diffuse Lighting for GGX+Smith Microsurfaces" https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl index b258e89c66..5b4594da99 100644 --- a/servers/rendering/renderer_rd/shaders/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/sky.glsl @@ -180,12 +180,11 @@ void main() { cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projections[ViewIndex].x)) / params.projections[ViewIndex].y; cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projections[ViewIndex].z)) / params.projections[ViewIndex].w; cube_normal = mat3(params.orientation) * cube_normal; - cube_normal.z = -cube_normal.z; cube_normal = normalize(cube_normal); vec2 uv = uv_interp * 0.5 + 0.5; - vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y)); + vec2 panorama_coords = vec2(atan(cube_normal.x, -cube_normal.z), acos(cube_normal.y)); if (panorama_coords.x < 0.0) { panorama_coords.x += M_PI * 2.0; @@ -200,13 +199,11 @@ void main() { vec4 custom_fog = vec4(0.0); #ifdef USE_CUBEMAP_PASS - vec3 inverted_cube_normal = cube_normal; - inverted_cube_normal.z *= -1.0; #ifdef USES_HALF_RES_COLOR - half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier; + half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier; #endif #ifdef USES_QUARTER_RES_COLOR - quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier; + quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier; #endif #else #ifdef USES_HALF_RES_COLOR diff --git a/servers/rendering/renderer_rd/storage_rd/SCsub b/servers/rendering/renderer_rd/storage_rd/SCsub new file mode 100644 index 0000000000..86681f9c74 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp new file mode 100644 index 0000000000..3299b93ee2 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp @@ -0,0 +1,235 @@ +/*************************************************************************/ +/* canvas_texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "canvas_texture_storage.h" +#include "texture_storage.h" + +// Until we move things into their own storage classes, also include our old class +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" + +using namespace RendererRD; + +/////////////////////////////////////////////////////////////////////////// +// CanvasTexture + +void CanvasTexture::clear_sets() { + if (cleared_cache) { + return; + } + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) { + RD::get_singleton()->free(uniform_sets[i][j]); + uniform_sets[i][j] = RID(); + } + } + } + cleared_cache = true; +} + +CanvasTexture::~CanvasTexture() { + clear_sets(); +} + +/////////////////////////////////////////////////////////////////////////// +// CanvasTextureStorage + +CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr; + +CanvasTextureStorage *CanvasTextureStorage::get_singleton() { + return singleton; +} + +CanvasTextureStorage::CanvasTextureStorage() { + singleton = this; +} + +CanvasTextureStorage::~CanvasTextureStorage() { + singleton = nullptr; +} + +RID CanvasTextureStorage::canvas_texture_allocate() { + return canvas_texture_owner.allocate_rid(); +} + +void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) { + canvas_texture_owner.initialize_rid(p_rid); +} + +void CanvasTextureStorage::canvas_texture_free(RID p_rid) { + canvas_texture_owner.free(p_rid); +} + +void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + switch (p_channel) { + case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { + ct->diffuse = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { + ct->normal_map = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { + ct->specular = p_texture; + } break; + } + + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + ct->specular_color.r = p_specular_color.r; + ct->specular_color.g = p_specular_color.g; + ct->specular_color.b = p_specular_color.b; + ct->specular_color.a = p_shininess; + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + + ct->texture_filter = p_filter; + ct->clear_sets(); +} + +void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { + CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); + ERR_FAIL_NULL(ct); + ct->texture_repeat = p_repeat; + ct->clear_sets(); +} + +bool CanvasTextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { + RendererStorageRD *storage = RendererStorageRD::base_singleton; + + CanvasTexture *ct = nullptr; + TextureStorage *texture_storage = TextureStorage::get_singleton(); + Texture *t = texture_storage->get_texture(p_texture); + + // TODO once we have our texture storage split off we'll look into moving this code into canvas_texture + + if (t) { + //regular texture + if (!t->canvas_texture) { + t->canvas_texture = memnew(CanvasTexture); + t->canvas_texture->diffuse = p_texture; + } + + ct = t->canvas_texture; + } else { + ct = get_canvas_texture(p_texture); + } + + if (!ct) { + return false; //invalid texture RID + } + + RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter; + ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false); + + RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; + ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false); + + RID uniform_set = ct->uniform_sets[filter][repeat]; + if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //create and update + Vector<RD::Uniform> uniforms; + { //diffuse + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + + t = texture_storage->get_texture(ct->diffuse); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ct->size_cache = Size2i(1, 1); + } else { + u.append_id(t->rd_texture); + ct->size_cache = Size2i(t->width_2d, t->height_2d); + } + uniforms.push_back(u); + } + { //normal + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + + t = texture_storage->get_texture(ct->normal_map); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); + ct->use_normal_cache = false; + } else { + u.append_id(t->rd_texture); + ct->use_normal_cache = true; + } + uniforms.push_back(u); + } + { //specular + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + + t = texture_storage->get_texture(ct->specular); + if (!t) { + u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ct->use_specular_cache = false; + } else { + u.append_id(t->rd_texture); + ct->use_specular_cache = true; + } + uniforms.push_back(u); + } + { //sampler + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 3; + u.append_id(storage->sampler_rd_get_default(filter, repeat)); + uniforms.push_back(u); + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set); + ct->uniform_sets[filter][repeat] = uniform_set; + ct->cleared_cache = false; + } + + r_uniform_set = uniform_set; + r_size = ct->size_cache; + r_specular_shininess = ct->specular_color; + r_use_normal = ct->use_normal_cache; + r_use_specular = ct->use_specular_cache; + + return true; +} diff --git a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h new file mode 100644 index 0000000000..6d3868edd5 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_RD_H +#define CANVAS_TEXTURE_STORAGE_RD_H + +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/canvas_texture_storage.h" + +namespace RendererRD { + +class CanvasTexture { +public: + RID diffuse; + RID normal_map; + RID specular; + Color specular_color = Color(1, 1, 1, 1); + float shininess = 1.0; + + RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + + Size2i size_cache = Size2i(1, 1); + bool use_normal_cache = false; + bool use_specular_cache = false; + bool cleared_cache = true; + + void clear_sets(); + ~CanvasTexture(); +}; + +class CanvasTextureStorage : public RendererCanvasTextureStorage { +private: + static CanvasTextureStorage *singleton; + + RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner; + +public: + static CanvasTextureStorage *get_singleton(); + + CanvasTextureStorage(); + virtual ~CanvasTextureStorage(); + + CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }; + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + + virtual RID canvas_texture_allocate() override; + virtual void canvas_texture_initialize(RID p_rid) override; + virtual void canvas_texture_free(RID p_rid) override; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override; + + bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular); +}; + +} // namespace RendererRD + +#endif // !CANVAS_TEXTURE_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp new file mode 100644 index 0000000000..acdaaae7a4 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -0,0 +1,1420 @@ +/*************************************************************************/ +/* texture_storage.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "texture_storage.h" + +// only include until we have DecalStorage sorted +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" + +using namespace RendererRD; + +/////////////////////////////////////////////////////////////////////////// +// Texture + +void Texture::cleanup() { + if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) { + //erase this first, as it's a dependency of the one below + RD::get_singleton()->free(rd_texture_srgb); + } + if (RD::get_singleton()->texture_is_valid(rd_texture)) { + RD::get_singleton()->free(rd_texture); + } + if (canvas_texture) { + memdelete(canvas_texture); + } +} + +/////////////////////////////////////////////////////////////////////////// +// TextureStorage + +TextureStorage *TextureStorage::singleton = nullptr; + +TextureStorage *TextureStorage::get_singleton() { + return singleton; +} + +TextureStorage::TextureStorage() { + singleton = this; + + { //create default textures + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 128); + pv.set(i * 4 + 1, 128); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 128); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT; + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap white array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default 3D + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.depth = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_3D; + + Vector<uint8_t> pv; + pv.resize(64 * 4); + for (int i = 0; i < 64; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + for (int i = 0; i < 64; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 1; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } +} + +TextureStorage::~TextureStorage() { + singleton = nullptr; + + //def textures + for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) { + texture_free(default_rd_textures[i]); + } +} + +bool TextureStorage::can_create_resources_async() const { + return true; +} + +RID TextureStorage::texture_allocate() { + return texture_owner.allocate_rid(); +} + +void TextureStorage::texture_free(RID p_texture) { + Texture *t = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!t); + ERR_FAIL_COND(t->is_render_target); + + t->cleanup(); + + if (t->is_proxy && t->proxy_to.is_valid()) { + Texture *proxy_to = texture_owner.get_or_null(t->proxy_to); + if (proxy_to) { + proxy_to->proxies.erase(p_texture); + } + } + + RendererStorageRD::base_singleton->decal_atlas_remove_texture(p_texture); + + for (int i = 0; i < t->proxies.size(); i++) { + Texture *p = texture_owner.get_or_null(t->proxies[i]); + ERR_CONTINUE(!p); + p->proxy_to = RID(); + p->rd_texture = RID(); + p->rd_texture_srgb = RID(); + } + + texture_owner.free(p_texture); +} + +void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { + TextureToRDFormat ret_format; + Ref<Image> image = _validate_texture_format(p_image, ret_format); + + Texture texture; + + texture.type = Texture::TYPE_2D; + + texture.width = p_image->get_width(); + texture.height = p_image->get_height(); + texture.layers = 1; + texture.mipmaps = p_image->get_mipmap_count() + 1; + texture.depth = 1; + texture.format = p_image->get_format(); + texture.validated_format = image->get_format(); + + texture.rd_type = RD::TEXTURE_TYPE_2D; + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = 1; + rd_format.array_layers = 1; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<uint8_t> data = image->get_data(); //use image data + Vector<Vector<uint8_t>> data_slices; + data_slices.push_back(data); + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { + ERR_FAIL_COND(p_layers.size() == 0); + + ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6); + ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0)); + + TextureToRDFormat ret_format; + Vector<Ref<Image>> images; + { + int valid_width = 0; + int valid_height = 0; + bool valid_mipmaps = false; + Image::Format valid_format = Image::FORMAT_MAX; + + for (int i = 0; i < p_layers.size(); i++) { + ERR_FAIL_COND(p_layers[i]->is_empty()); + + if (i == 0) { + valid_width = p_layers[i]->get_width(); + valid_height = p_layers[i]->get_height(); + valid_format = p_layers[i]->get_format(); + valid_mipmaps = p_layers[i]->has_mipmaps(); + } else { + ERR_FAIL_COND(p_layers[i]->get_width() != valid_width); + ERR_FAIL_COND(p_layers[i]->get_height() != valid_height); + ERR_FAIL_COND(p_layers[i]->get_format() != valid_format); + ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps); + } + + images.push_back(_validate_texture_format(p_layers[i], ret_format)); + } + } + + Texture texture; + + texture.type = Texture::TYPE_LAYERED; + texture.layered_type = p_layered_type; + + texture.width = p_layers[0]->get_width(); + texture.height = p_layers[0]->get_height(); + texture.layers = p_layers.size(); + texture.mipmaps = p_layers[0]->get_mipmap_count() + 1; + texture.depth = 1; + texture.format = p_layers[0]->get_format(); + texture.validated_format = images[0]->get_format(); + + switch (p_layered_type) { + case RS::TEXTURE_LAYERED_2D_ARRAY: { + texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY; + } break; + case RS::TEXTURE_LAYERED_CUBEMAP: { + texture.rd_type = RD::TEXTURE_TYPE_CUBE; + } break; + case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: { + texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + } break; + } + + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = 1; + rd_format.array_layers = texture.layers; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<Vector<uint8_t>> data_slices; + for (int i = 0; i < images.size(); i++) { + Vector<uint8_t> data = images[i]->get_data(); //use image data + data_slices.push_back(data); + } + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { + ERR_FAIL_COND(p_data.size() == 0); + + Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); + if (verr != Image::VALIDATE_3D_OK) { + ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); + } + + TextureToRDFormat ret_format; + Image::Format validated_format = Image::FORMAT_MAX; + Vector<uint8_t> all_data; + uint32_t mipmap_count = 0; + Vector<Texture::BufferSlice3D> slices; + { + Vector<Ref<Image>> images; + uint32_t all_data_size = 0; + images.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + TextureToRDFormat f; + images.write[i] = _validate_texture_format(p_data[i], f); + if (i == 0) { + ret_format = f; + validated_format = images[0]->get_format(); + } + + all_data_size += images[i]->get_data().size(); + } + + all_data.resize(all_data_size); //consolidate all data here + uint32_t offset = 0; + Size2i prev_size; + for (int i = 0; i < p_data.size(); i++) { + uint32_t s = images[i]->get_data().size(); + + memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); + { + Texture::BufferSlice3D slice; + slice.size.width = images[i]->get_width(); + slice.size.height = images[i]->get_height(); + slice.offset = offset; + slice.buffer_size = s; + slices.push_back(slice); + } + offset += s; + + Size2i img_size(images[i]->get_width(), images[i]->get_height()); + if (img_size != prev_size) { + mipmap_count++; + } + prev_size = img_size; + } + } + + Texture texture; + + texture.type = Texture::TYPE_3D; + texture.width = p_width; + texture.height = p_height; + texture.depth = p_depth; + texture.mipmaps = mipmap_count; + texture.format = p_data[0]->get_format(); + texture.validated_format = validated_format; + + texture.buffer_size_3d = all_data.size(); + texture.buffer_slices_3d = slices; + + texture.rd_type = RD::TEXTURE_TYPE_3D; + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = texture.depth; + rd_format.array_layers = 1; + rd_format.mipmaps = texture.mipmaps; + rd_format.texture_type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<Vector<uint8_t>> data_slices; + data_slices.push_back(all_data); //one slice + + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND(texture.rd_texture.is_null()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND(texture.rd_texture_srgb.is_null()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + +void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) { + Texture *tex = texture_owner.get_or_null(p_base); + ERR_FAIL_COND(!tex); + Texture proxy_tex = *tex; + + proxy_tex.rd_view.format_override = tex->rd_format; + proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); + if (proxy_tex.rd_texture_srgb.is_valid()) { + proxy_tex.rd_view.format_override = tex->rd_format_srgb; + proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); + } + proxy_tex.proxy_to = p_base; + proxy_tex.is_render_target = false; + proxy_tex.is_proxy = true; + proxy_tex.proxies.clear(); + + texture_owner.initialize_rid(p_texture, proxy_tex); + + tex->proxies.push_back(p_texture); +} + +void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) { + ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); + + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->is_render_target); + ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); + ERR_FAIL_COND(p_image->get_format() != tex->format); + + if (tex->type == Texture::TYPE_LAYERED) { + ERR_FAIL_INDEX(p_layer, tex->layers); + } + +#ifdef TOOLS_ENABLED + tex->image_cache_2d.unref(); +#endif + TextureToRDFormat f; + Ref<Image> validated = _validate_texture_format(p_image, f); + + RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data()); +} + +void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { + _texture_2d_update(p_texture, p_image, p_layer, false); +} + +void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->type != Texture::TYPE_3D); + + Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); + if (verr != Image::VALIDATE_3D_OK) { + ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); + } + + Vector<uint8_t> all_data; + { + Vector<Ref<Image>> images; + uint32_t all_data_size = 0; + images.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + Ref<Image> image = p_data[i]; + if (image->get_format() != tex->validated_format) { + image = image->duplicate(); + image->convert(tex->validated_format); + } + all_data_size += images[i]->get_data().size(); + images.push_back(image); + } + + all_data.resize(all_data_size); //consolidate all data here + uint32_t offset = 0; + + for (int i = 0; i < p_data.size(); i++) { + uint32_t s = images[i]->get_data().size(); + memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s); + offset += s; + } + } + + RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data); +} + +void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(!tex->is_proxy); + Texture *proxy_to = texture_owner.get_or_null(p_proxy_to); + ERR_FAIL_COND(!proxy_to); + ERR_FAIL_COND(proxy_to->is_proxy); + + if (tex->proxy_to.is_valid()) { + //unlink proxy + if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { + RD::get_singleton()->free(tex->rd_texture); + tex->rd_texture = RID(); + } + if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { + RD::get_singleton()->free(tex->rd_texture_srgb); + tex->rd_texture_srgb = RID(); + } + Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to); + ERR_FAIL_COND(!prev_tex); + prev_tex->proxies.erase(p_texture); + } + + *tex = *proxy_to; + + tex->proxy_to = p_proxy_to; + tex->is_render_target = false; + tex->is_proxy = true; + tex->proxies.clear(); + proxy_to->proxies.push_back(p_texture); + + tex->rd_view.format_override = tex->rd_format; + tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); + if (tex->rd_texture_srgb.is_valid()) { + tex->rd_view.format_override = tex->rd_format_srgb; + tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); + } +} + +//these two APIs can be used together or in combination with the others. +void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + texture_2d_initialize(p_texture, image); +} + +void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + Vector<Ref<Image>> images; + if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) { + images.push_back(image); + } else { + //cube + for (int i = 0; i < 6; i++) { + images.push_back(image); + } + } + + texture_2d_layered_initialize(p_texture, images, p_layered_type); +} + +void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instantiate(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + image->fill(Color(1, 0, 1, 1)); + + Vector<Ref<Image>> images; + //cube + for (int i = 0; i < 4; i++) { + images.push_back(image); + } + + texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images); +} + +Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + +#ifdef TOOLS_ENABLED + if (tex->image_cache_2d.is_valid() && !tex->is_render_target) { + return tex->image_cache_2d; + } +#endif + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instantiate(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) { + tex->image_cache_2d = image; + } +#endif + + return image; +} + +Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instantiate(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + + return image; +} + +Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); + ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); + + Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + + ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>()); + + Vector<Ref<Image>> ret; + + for (int i = 0; i < tex->buffer_slices_3d.size(); i++) { + const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i]; + ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>()); + ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>()); + Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size); + + Ref<Image> img; + img.instantiate(); + img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); + ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>()); + if (tex->format != tex->validated_format) { + img->convert(tex->format); + } + + ret.push_back(img); + } + + return ret; +} + +void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy + Texture *by_tex = texture_owner.get_or_null(p_by_texture); + ERR_FAIL_COND(!by_tex); + ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy + + if (tex == by_tex) { + return; + } + + if (tex->rd_texture_srgb.is_valid()) { + RD::get_singleton()->free(tex->rd_texture_srgb); + } + RD::get_singleton()->free(tex->rd_texture); + + if (tex->canvas_texture) { + memdelete(tex->canvas_texture); + tex->canvas_texture = nullptr; + } + + Vector<RID> proxies_to_update = tex->proxies; + Vector<RID> proxies_to_redirect = by_tex->proxies; + + *tex = *by_tex; + + tex->proxies = proxies_to_update; //restore proxies, so they can be updated + + if (tex->canvas_texture) { + tex->canvas_texture->diffuse = p_texture; //update + } + + for (int i = 0; i < proxies_to_update.size(); i++) { + texture_proxy_update(proxies_to_update[i], p_texture); + } + for (int i = 0; i < proxies_to_redirect.size(); i++) { + texture_proxy_update(proxies_to_redirect[i], p_texture); + } + //delete last, so proxies can be updated + texture_owner.free(p_by_texture); + + RendererStorageRD::base_singleton->decal_atlas_mark_dirty_on_texture(p_texture); +} + +void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->type != Texture::TYPE_2D); + + tex->width_2d = p_width; + tex->height_2d = p_height; +} + +void TextureStorage::texture_set_path(RID p_texture, const String &p_path) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->path = p_path; +} + +String TextureStorage::texture_get_path(RID p_texture) const { + RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, String()); + + return tex->path; +} + +void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_3d_callback_ud = p_userdata; + tex->detect_3d_callback = p_callback; +} + +void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_normal_callback_ud = p_userdata; + tex->detect_normal_callback = p_callback; +} + +void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND(!tex); + + tex->detect_roughness_callback_ud = p_userdata; + tex->detect_roughness_callback = p_callback; +} + +void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) { +} + +void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { +} + +Size2 TextureStorage::texture_size_with_proxy(RID p_proxy) { + return texture_2d_get_size(p_proxy); +} + +Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { + Ref<Image> image = p_image->duplicate(); + + switch (p_image->get_format()) { + case Image::FORMAT_L8: { + r_format.format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //luminance + case Image::FORMAT_LA8: { + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; + } break; //luminance-alpha + case Image::FORMAT_R8: { + r_format.format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RG8: { + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGB8: { + //this format is not mandatory for specification, check if supported first + if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGBA8: { + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RGBA4444: { + r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RGB565: { + r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RF: { + r_format.format = RD::DATA_FORMAT_R32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float + case Image::FORMAT_RGF: { + r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBF: { + //this format is not mandatory for specification, check if supported first + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + image->convert(Image::FORMAT_RGBAF); + } + + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBAF: { + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case Image::FORMAT_RH: { + r_format.format = RD::DATA_FORMAT_R16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //half float + case Image::FORMAT_RGH: { + r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGBH: { + //this format is not mandatory for specification, check if supported first + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->convert(Image::FORMAT_RGBAH); + } + + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBAH: { + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case Image::FORMAT_RGBE9995: { + r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; +#ifndef _MSC_VER +#warning TODO need to make a function in Image to swap bits for this +#endif + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; + } break; + case Image::FORMAT_DXT1: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //s3tc bc1 + case Image::FORMAT_DXT3: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //bc2 + case Image::FORMAT_DXT5: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; //bc3 + case Image::FORMAT_RGTC_R: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGTC_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_BPTC_RGBA: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //btpc bc7 + case Image::FORMAT_BPTC_RGBF: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->decompress(); + image->convert(Image::FORMAT_RGBAH); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float bc6h + case Image::FORMAT_BPTC_RGBFU: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->decompress(); + image->convert(Image::FORMAT_RGBAH); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //unsigned float bc6hu + case Image::FORMAT_ETC2_R11: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //etc2 + case Image::FORMAT_ETC2_R11S: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_SNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //signed: {} break; NOT srgb. + case Image::FORMAT_ETC2_RG11: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_ETC2_RG11S: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_SNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_ETC: + case Image::FORMAT_ETC2_RGB8: { + //ETC2 is backwards compatible with ETC1, and all modern platforms support it + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_ETC2_RGBA8: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_RGB8A1: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_RA_AS_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_DXT5_RA_AS_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + + default: { + } + } + + return image; +} diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h new file mode 100644 index 0000000000..5d8d165a08 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -0,0 +1,230 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_RD_H +#define TEXTURE_STORAGE_RD_H + +#include "canvas_texture_storage.h" +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/texture_storage.h" + +namespace RendererRD { + +enum DefaultRDTexture { + DEFAULT_RD_TEXTURE_WHITE, + DEFAULT_RD_TEXTURE_BLACK, + DEFAULT_RD_TEXTURE_NORMAL, + DEFAULT_RD_TEXTURE_ANISO, + DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, + DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, + DEFAULT_RD_TEXTURE_3D_WHITE, + DEFAULT_RD_TEXTURE_3D_BLACK, + DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, + DEFAULT_RD_TEXTURE_2D_UINT, + DEFAULT_RD_TEXTURE_MAX +}; + +class Texture { +public: + enum Type { + TYPE_2D, + TYPE_LAYERED, + TYPE_3D + }; + + Type type; + RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; + + RenderingDevice::TextureType rd_type; + RID rd_texture; + RID rd_texture_srgb; + RenderingDevice::DataFormat rd_format; + RenderingDevice::DataFormat rd_format_srgb; + + RD::TextureView rd_view; + + Image::Format format; + Image::Format validated_format; + + int width; + int height; + int depth; + int layers; + int mipmaps; + + int height_2d; + int width_2d; + + struct BufferSlice3D { + Size2i size; + uint32_t offset = 0; + uint32_t buffer_size = 0; + }; + Vector<BufferSlice3D> buffer_slices_3d; + uint32_t buffer_size_3d = 0; + + bool is_render_target; + bool is_proxy; + + Ref<Image> image_cache_2d; + String path; + + RID proxy_to; + Vector<RID> proxies; + + Set<RID> lightmap_users; + + RS::TextureDetectCallback detect_3d_callback = nullptr; + void *detect_3d_callback_ud = nullptr; + + RS::TextureDetectCallback detect_normal_callback = nullptr; + void *detect_normal_callback_ud = nullptr; + + RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; + void *detect_roughness_callback_ud = nullptr; + + CanvasTexture *canvas_texture = nullptr; + + void cleanup(); +}; + +class TextureStorage : public RendererTextureStorage { +private: + static TextureStorage *singleton; + + //textures can be created from threads, so this RID_Owner is thread safe + mutable RID_Owner<Texture, true> texture_owner; + + struct TextureToRDFormat { + RD::DataFormat format; + RD::DataFormat format_srgb; + RD::TextureSwizzle swizzle_r; + RD::TextureSwizzle swizzle_g; + RD::TextureSwizzle swizzle_b; + RD::TextureSwizzle swizzle_a; + TextureToRDFormat() { + format = RD::DATA_FORMAT_MAX; + format_srgb = RD::DATA_FORMAT_MAX; + swizzle_r = RD::TEXTURE_SWIZZLE_R; + swizzle_g = RD::TEXTURE_SWIZZLE_G; + swizzle_b = RD::TEXTURE_SWIZZLE_B; + swizzle_a = RD::TEXTURE_SWIZZLE_A; + } + }; + + Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format); + void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0, bool p_immediate = false); + +public: + static TextureStorage *get_singleton(); + + RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; + + _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { + return default_rd_textures[p_texture]; + } + + TextureStorage(); + virtual ~TextureStorage(); + + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + + virtual bool can_create_resources_async() const override; + + virtual RID texture_allocate() override; + virtual void texture_free(RID p_rid) override; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override; + virtual void texture_proxy_update(RID p_proxy, RID p_base) override; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) override; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override; + virtual void texture_3d_placeholder_initialize(RID p_texture) override; + + virtual Ref<Image> texture_2d_get(RID p_texture) const override; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override; + + virtual void texture_replace(RID p_texture, RID p_by_texture) override; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override; + + virtual void texture_set_path(RID p_texture, const String &p_path) override; + virtual String texture_get_path(RID p_texture) const override; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override; + + virtual Size2 texture_size_with_proxy(RID p_proxy) override; + + //internal usage + + _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { + if (p_texture.is_null()) { + return RID(); + } + RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + + if (!tex) { + return RID(); + } + return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; + } + + _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) { + if (p_texture.is_null()) { + return Size2i(); + } + RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + + if (!tex) { + return Size2i(); + } + return Size2i(tex->width_2d, tex->height_2d); + } +}; + +} // namespace RendererRD + +#endif // !_TEXTURE_STORAGE_RD_H diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index ca3d3a048d..af4c697751 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -121,59 +121,6 @@ public: Set<Dependency *> dependencies; }; - virtual bool can_create_resources_async() const = 0; - /* TEXTURE API */ - - virtual RID texture_allocate() = 0; - - virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0; - virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; - virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; - virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent - - virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; - virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; - virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; - - //these two APIs can be used together or in combination with the others. - virtual void texture_2d_placeholder_initialize(RID p_texture) = 0; - virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0; - virtual void texture_3d_placeholder_initialize(RID p_texture) = 0; - - virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; - - virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; - - virtual void texture_set_path(RID p_texture, const String &p_path) = 0; - virtual String texture_get_path(RID p_texture) const = 0; - - virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; - - virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0; - - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; - - virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; - - virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; - virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; - - /* CANVAS TEXTURE API */ - - virtual RID canvas_texture_allocate() = 0; - virtual void canvas_texture_initialize(RID p_rid) = 0; - - virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; - virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; - - virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; - virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; - /* SHADER API */ virtual RID shader_allocate() = 0; @@ -397,6 +344,9 @@ public: virtual AABB decal_get_aabb(RID p_decal) const = 0; + virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; + virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; + /* VOXEL GI API */ virtual RID voxel_gi_allocate() = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index b448a15d8e..f492c5e9bd 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -293,7 +293,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasRender::Light *cl = F->get(); if (cl->enabled && cl->texture.is_valid()) { //not super efficient.. - Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture); + Size2 tsize = RSG::texture_storage->texture_size_with_proxy(cl->texture); tsize *= cl->scale; Vector2 offset = tsize / 2.0; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index d93aad5d7b..af02e25cd9 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -398,6 +398,8 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) : RendererSceneCull *sr = memnew(RendererSceneCull); RSG::scene = sr; RSG::rasterizer = RendererCompositor::create(); + RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage(); + RSG::texture_storage = RSG::rasterizer->get_texture_storage(); RSG::storage = RSG::rasterizer->get_storage(); RSG::canvas_render = RSG::rasterizer->get_canvas(); sr->set_scene_render(RSG::rasterizer->get_scene()); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 4a8944ccdd..8c93308e38 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -126,54 +126,53 @@ public: #include "servers/server_wrap_mt_common.h" -//from now on, calls forwarded to this singleton -#define ServerName RendererStorage -#define server_name RSG::storage - /* TEXTURE API */ -#define FUNCRIDTEX0(m_type) \ - virtual RID m_type##_create() override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret); \ - } \ - return ret; \ +#define ServerName RendererTextureStorage +#define server_name RSG::texture_storage + +#define FUNCRIDTEX0(m_type) \ + virtual RID m_type##_create() override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret); \ + } \ + return ret; \ } -#define FUNCRIDTEX1(m_type, m_type1) \ - virtual RID m_type##_create(m_type1 p1) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1); \ - } \ - return ret; \ +#define FUNCRIDTEX1(m_type, m_type1) \ + virtual RID m_type##_create(m_type1 p1) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1); \ + } \ + return ret; \ } -#define FUNCRIDTEX2(m_type, m_type1, m_type2) \ - virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1, p2); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2); \ - } \ - return ret; \ +#define FUNCRIDTEX2(m_type, m_type1, m_type2) \ + virtual RID m_type##_create(m_type1 p1, m_type2 p2) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1, p2); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2); \ + } \ + return ret; \ } -#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ - virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \ - RID ret = RSG::storage->texture_allocate(); \ - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \ - RSG::storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \ - } else { \ - command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \ - } \ - return ret; \ +#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \ + } \ + return ret; \ } //these go pass-through, as they can be called from any thread @@ -214,6 +213,13 @@ public: FUNC2(texture_set_force_redraw_if_visible, RID, bool) +//from now on, calls forwarded to this singleton +#undef ServerName +#undef server_name + +#define ServerName RendererStorage +#define server_name RSG::storage + /* SHADER API */ FUNCRIDSPLIT(shader) @@ -246,7 +252,9 @@ public: virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override { RID mesh = RSG::storage->mesh_allocate(); - if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { + // TODO once we have RSG::mesh_storage, add can_create_resources_async and call here instead of texture_storage!! + + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { if (Thread::get_caller_id() == server_thread) { command_queue.flush_if_pending(); } diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp index b8b06b5eea..83aa8959c1 100644 --- a/servers/rendering/rendering_server_globals.cpp +++ b/servers/rendering/rendering_server_globals.cpp @@ -32,6 +32,8 @@ bool RenderingServerGlobals::threaded = false; +RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr; +RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr; RendererStorage *RenderingServerGlobals::storage = nullptr; RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr; RendererCompositor *RenderingServerGlobals::rasterizer = nullptr; diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h index 4351830a5f..2bef490760 100644 --- a/servers/rendering/rendering_server_globals.h +++ b/servers/rendering/rendering_server_globals.h @@ -34,6 +34,8 @@ #include "servers/rendering/renderer_canvas_cull.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_scene.h" +#include "servers/rendering/storage/canvas_texture_storage.h" +#include "servers/rendering/storage/texture_storage.h" class RendererCanvasCull; class RendererViewport; @@ -43,6 +45,8 @@ class RenderingServerGlobals { public: static bool threaded; + static RendererCanvasTextureStorage *canvas_texture_storage; + static RendererTextureStorage *texture_storage; static RendererStorage *storage; static RendererCanvasRender *canvas_render; static RendererCompositor *rasterizer; diff --git a/servers/rendering/storage/SCsub b/servers/rendering/storage/SCsub new file mode 100644 index 0000000000..86681f9c74 --- /dev/null +++ b/servers/rendering/storage/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/rendering/storage/canvas_texture_storage.h b/servers/rendering/storage/canvas_texture_storage.h new file mode 100644 index 0000000000..ad4c67f649 --- /dev/null +++ b/servers/rendering/storage/canvas_texture_storage.h @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* canvas_texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CANVAS_TEXTURE_STORAGE_H +#define CANVAS_TEXTURE_STORAGE_H + +#include "servers/rendering_server.h" + +class RendererCanvasTextureStorage { +public: + virtual ~RendererCanvasTextureStorage(){}; + + virtual RID canvas_texture_allocate() = 0; + virtual void canvas_texture_initialize(RID p_rid) = 0; + virtual void canvas_texture_free(RID p_rid) = 0; + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; +}; + +#endif // !CANVAS_TEXTURE_STORAGE_H diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h new file mode 100644 index 0000000000..bef5e3e146 --- /dev/null +++ b/servers/rendering/storage/texture_storage.h @@ -0,0 +1,80 @@ +/*************************************************************************/ +/* texture_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEXTURE_STORAGE_H +#define TEXTURE_STORAGE_H + +#include "servers/rendering_server.h" + +class RendererTextureStorage { +public: + virtual bool can_create_resources_async() const = 0; + + virtual ~RendererTextureStorage(){}; + + virtual RID texture_allocate() = 0; + virtual void texture_free(RID p_rid) = 0; + + virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0; + virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; + virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; + + //these two APIs can be used together or in combination with the others. + virtual void texture_2d_placeholder_initialize(RID p_texture) = 0; + virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0; + virtual void texture_3d_placeholder_initialize(RID p_texture) = 0; + + virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; + + virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; + + virtual void texture_set_path(RID p_texture, const String &p_path) = 0; + virtual String texture_get_path(RID p_texture) const = 0; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; + + virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; +}; + +#endif // !TEXTURE_STORAGE_H diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index d34fd572ad..a6992014e8 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2580,6 +2580,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture"), &RenderingServer::canvas_item_add_particles); ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &RenderingServer::canvas_item_add_set_transform); ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &RenderingServer::canvas_item_add_clip_ignore); + ClassDB::bind_method(D_METHOD("canvas_item_add_animation_slice", "item", "animation_length", "slice_begin", "slice_end", "offset"), &RenderingServer::canvas_item_add_animation_slice, DEFVAL(0.0)); ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &RenderingServer::canvas_item_set_sort_children_by_y); ClassDB::bind_method(D_METHOD("canvas_item_set_z_index", "item", "z_index"), &RenderingServer::canvas_item_set_z_index); ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &RenderingServer::canvas_item_set_z_as_relative_to_parent); diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 5792572dc1..1a10161a5b 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -88,6 +88,12 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning"); GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid"); + GDVIRTUAL_BIND(_font_set_embolden, "font_rid", "strength"); + GDVIRTUAL_BIND(_font_get_embolden, "font_rid"); + + GDVIRTUAL_BIND(_font_set_transform, "font_rid", "transform"); + GDVIRTUAL_BIND(_font_get_transform, "font_rid"); + GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates"); GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid"); @@ -527,6 +533,30 @@ TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioni return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED; } +void TextServerExtension::font_set_embolden(RID p_font_rid, float p_strength) { + GDVIRTUAL_CALL(_font_set_embolden, p_font_rid, p_strength); +} + +float TextServerExtension::font_get_embolden(RID p_font_rid) const { + float ret; + if (GDVIRTUAL_CALL(_font_get_embolden, p_font_rid, ret)) { + return ret; + } + return 0.f; +} + +void TextServerExtension::font_set_transform(RID p_font_rid, Transform2D p_transform) { + GDVIRTUAL_CALL(_font_set_transform, p_font_rid, p_transform); +} + +Transform2D TextServerExtension::font_get_transform(RID p_font_rid) const { + Transform2D ret; + if (GDVIRTUAL_CALL(_font_get_transform, p_font_rid, ret)) { + return ret; + } + return Transform2D(); +} + void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) { GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates); } diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index d185e44806..7d80467371 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -139,6 +139,16 @@ public: GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning); GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID); + virtual void font_set_embolden(RID p_font_rid, float p_strength) override; + virtual float font_get_embolden(RID p_font_rid) const override; + GDVIRTUAL2(_font_set_embolden, RID, float); + GDVIRTUAL1RC(float, _font_get_embolden, RID); + + virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override; + virtual Transform2D font_get_transform(RID p_font_rid) const override; + GDVIRTUAL2(_font_set_transform, RID, Transform2D); + GDVIRTUAL1RC(Transform2D, _font_get_transform, RID); + virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary); diff --git a/servers/text_server.cpp b/servers/text_server.cpp index e84c0f05cc..aaba79c049 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -241,6 +241,12 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("font_set_subpixel_positioning", "font_rid", "subpixel_positioning"), &TextServer::font_set_subpixel_positioning); ClassDB::bind_method(D_METHOD("font_get_subpixel_positioning", "font_rid"), &TextServer::font_get_subpixel_positioning); + ClassDB::bind_method(D_METHOD("font_set_embolden", "font_rid", "strength"), &TextServer::font_set_embolden); + ClassDB::bind_method(D_METHOD("font_get_embolden", "font_rid"), &TextServer::font_get_embolden); + + ClassDB::bind_method(D_METHOD("font_set_transform", "font_rid", "transform"), &TextServer::font_set_transform); + ClassDB::bind_method(D_METHOD("font_get_transform", "font_rid"), &TextServer::font_get_transform); + ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates); ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates); @@ -1261,11 +1267,11 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p if (p_clip_r > 0) { // Clip right / bottom. if (orientation == ORIENTATION_HORIZONTAL) { - if (ofs.x - p_pos.x > p_clip_r) { + if (ofs.x - p_pos.x + glyphs[i].advance > p_clip_r) { return; } } else { - if (ofs.y - p_pos.y > p_clip_r) { + if (ofs.y - p_pos.y + glyphs[i].advance > p_clip_r) { return; } } @@ -1356,11 +1362,11 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect if (p_clip_r > 0) { // Clip right / bottom. if (orientation == ORIENTATION_HORIZONTAL) { - if (ofs.x - p_pos.x > p_clip_r) { + if (ofs.x - p_pos.x + glyphs[i].advance > p_clip_r) { return; } } else { - if (ofs.y - p_pos.y > p_clip_r) { + if (ofs.y - p_pos.y + glyphs[i].advance > p_clip_r) { return; } } diff --git a/servers/text_server.h b/servers/text_server.h index 38ad496490..83dc3df56d 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -261,6 +261,12 @@ public: virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) = 0; virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const = 0; + virtual void font_set_embolden(RID p_font_rid, float p_strength) = 0; + virtual float font_get_embolden(RID p_font_rid) const = 0; + + virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) = 0; + virtual Transform2D font_get_transform(RID p_font_rid) const = 0; + virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0; diff --git a/tests/core/math/test_vector2.h b/tests/core/math/test_vector2.h index ff60467bf4..9b7800164a 100644 --- a/tests/core/math/test_vector2.h +++ b/tests/core/math/test_vector2.h @@ -90,6 +90,9 @@ TEST_CASE("[Vector2] Interpolation methods") { Vector2(5, 0).slerp(Vector2(0, 5), 0.5).is_equal_approx(Vector2(5, 5) * Math_SQRT12), "Vector2 slerp with non-normalized values should work as expected."); CHECK_MESSAGE( + Vector2(1, 1).slerp(Vector2(2, 2), 0.5).is_equal_approx(Vector2(1.5, 1.5)), + "Vector2 slerp with colinear inputs should behave as expected."); + CHECK_MESSAGE( Vector2().slerp(Vector2(), 0.5) == Vector2(), "Vector2 slerp with both inputs as zero vectors should return a zero vector."); CHECK_MESSAGE( diff --git a/tests/core/math/test_vector3.h b/tests/core/math/test_vector3.h index 847a7c0b3f..6f99fada2b 100644 --- a/tests/core/math/test_vector3.h +++ b/tests/core/math/test_vector3.h @@ -111,6 +111,9 @@ TEST_CASE("[Vector3] Interpolation methods") { Vector3(5, 0, 0).slerp(Vector3(0, 3, 4), 0.5).is_equal_approx(Vector3(3.535533905029296875, 2.121320486068725586, 2.828427314758300781)), "Vector3 slerp with non-normalized values should work as expected."); CHECK_MESSAGE( + Vector3(1, 1, 1).slerp(Vector3(2, 2, 2), 0.5).is_equal_approx(Vector3(1.5, 1.5, 1.5)), + "Vector3 slerp with colinear inputs should behave as expected."); + CHECK_MESSAGE( Vector3().slerp(Vector3(), 0.5) == Vector3(), "Vector3 slerp with both inputs as zero vectors should return a zero vector."); CHECK_MESSAGE( diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp index e537cfa27f..8f46b62ce9 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp @@ -22,6 +22,8 @@ #include "tvgSvgCssStyle.h" +#include <cstring> + /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ @@ -183,4 +185,4 @@ void cssApplyStyleToPostponeds(Array<SvgNodeIdPair>& postponeds, SvgNode* style) cssCopyStyleAttr(nodeIdPair.node, cssNode); } } -}
\ No newline at end of file +} |