diff options
461 files changed, 6161 insertions, 4108 deletions
diff --git a/.github/actions/godot-deps/action.yml b/.github/actions/godot-deps/action.yml index ee4d7d3751..e99167ff2b 100644 --- a/.github/actions/godot-deps/action.yml +++ b/.github/actions/godot-deps/action.yml @@ -12,7 +12,7 @@ runs: steps: # Use python 3.x release (works cross platform) - name: Set up Python 3.x - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: # Semantic version range syntax or exact version of a Python version python-version: ${{ inputs.python-version }} diff --git a/.github/actions/upload-artifact/action.yml b/.github/actions/upload-artifact/action.yml index bc1871b914..ae0e634cbf 100644 --- a/.github/actions/upload-artifact/action.yml +++ b/.github/actions/upload-artifact/action.yml @@ -12,7 +12,7 @@ runs: using: "composite" steps: - name: Upload Godot Artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ${{ inputs.name }} path: ${{ inputs.path }} diff --git a/.github/workflows/android_builds.yml b/.github/workflows/android_builds.yml index a9a580247b..4f54f6629e 100644 --- a/.github/workflows/android_builds.yml +++ b/.github/workflows/android_builds.yml @@ -17,7 +17,7 @@ jobs: name: Template (target=release, tools=no) steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Azure repositories are not reliable, we need to prevent azure giving us packages. - name: Make apt sources.list use the default Ubuntu repositories @@ -27,8 +27,9 @@ jobs: sudo apt-get update - name: Set up Java 11 - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: + distribution: temurin java-version: 11 - name: Setup Godot build cache @@ -38,19 +39,19 @@ jobs: - name: Setup python and scons uses: ./.github/actions/godot-deps - - name: Compilation (armv7) + - name: Compilation (arm32) uses: ./.github/actions/godot-build with: - sconsflags: ${{ env.SCONSFLAGS }} android_arch=armv7 + sconsflags: ${{ env.SCONSFLAGS }} arch=arm32 platform: android target: release tools: false tests: false - - name: Compilation (arm64v8) + - name: Compilation (arm64) uses: ./.github/actions/godot-build with: - sconsflags: ${{ env.SCONSFLAGS }} android_arch=arm64v8 + sconsflags: ${{ env.SCONSFLAGS }} arch=arm64 platform: android target: release tools: false diff --git a/.github/workflows/ios_builds.yml b/.github/workflows/ios_builds.yml index 03277edc1d..bc00fad569 100644 --- a/.github/workflows/ios_builds.yml +++ b/.github/workflows/ios_builds.yml @@ -17,7 +17,7 @@ jobs: name: Template (target=release, tools=no) steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Godot build cache uses: ./.github/actions/godot-cache @@ -26,7 +26,7 @@ jobs: - name: Setup python and scons uses: ./.github/actions/godot-deps - - name: Compilation (arm64v8) + - name: Compilation (arm64) uses: ./.github/actions/godot-build with: sconsflags: ${{ env.SCONSFLAGS }} diff --git a/.github/workflows/javascript_builds.yml b/.github/workflows/javascript_builds.yml index 00c79e8ba0..54bde92b16 100644 --- a/.github/workflows/javascript_builds.yml +++ b/.github/workflows/javascript_builds.yml @@ -19,18 +19,10 @@ jobs: name: Template (target=release, tools=no) steps: - - uses: actions/checkout@v2 - - # Additional cache for Emscripten generated system libraries - - name: Load Emscripten cache - id: javascript-template-emscripten-cache - uses: actions/cache@v2 - with: - path: ${{env.EM_CACHE_FOLDER}} - key: ${{env.EM_VERSION}}-${{github.job}} + - uses: actions/checkout@v3 - name: Set up Emscripten latest - uses: mymindstorm/setup-emsdk@v10 + uses: mymindstorm/setup-emsdk@v11 with: version: ${{env.EM_VERSION}} actions-cache-folder: ${{env.EM_CACHE_FOLDER}} diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index dbb72ae095..2e8bd101e5 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -4,7 +4,7 @@ on: [push, pull_request] # Global Settings env: # Only used for the cache key. Increment version to force clean build. - GODOT_BASE_BRANCH: master-v2 + GODOT_BASE_BRANCH: master SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes DOTNET_NOLOGO: true DOTNET_CLI_TELEMETRY_OPTOUT: false @@ -28,7 +28,7 @@ jobs: tests: false # Disabled due freeze caused by mix Mono build and CI sconsflags: module_mono_enabled=yes doc-test: true - bin: "./bin/godot.linuxbsd.opt.tools.64.mono" + bin: "./bin/godot.linuxbsd.opt.tools.x86_64.mono" build-mono: true proj-conv: true artifact: true @@ -43,7 +43,7 @@ jobs: # 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: true - bin: "./bin/godot.linuxbsd.double.tools.64.san" + bin: "./bin/godot.linuxbsd.double.tools.x86_64.san" build-mono: false # Skip 2GiB artifact speeding up action. artifact: false @@ -54,7 +54,7 @@ jobs: tools: true tests: true sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes linker=lld - bin: "./bin/godot.linuxbsd.tools.64.llvm.san" + bin: "./bin/godot.linuxbsd.tools.x86_64.llvm.san" build-mono: false # Skip 2GiB artifact speeding up action. artifact: false @@ -77,7 +77,7 @@ jobs: artifact: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Linux dependencies shell: bash @@ -102,7 +102,7 @@ jobs: uses: ./.github/actions/godot-deps - name: Set up .NET Sdk - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v2 if: ${{ matrix.build-mono }} with: dotnet-version: '6.0.x' @@ -195,7 +195,7 @@ jobs: # Checkout godot-cpp - name: Checkout godot-cpp if: ${{ matrix.godot-cpp-test }} - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: godotengine/godot-cpp submodules: 'recursive' diff --git a/.github/workflows/macos_builds.yml b/.github/workflows/macos_builds.yml index 0ad0995bb7..be1fb8de85 100644 --- a/.github/workflows/macos_builds.yml +++ b/.github/workflows/macos_builds.yml @@ -4,7 +4,7 @@ on: [push, pull_request] # Global Settings env: # Only used for the cache key. Increment version to force clean build. - GODOT_BASE_BRANCH: master-v3 + GODOT_BASE_BRANCH: master SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes concurrency: @@ -24,7 +24,7 @@ jobs: target: release_debug tools: true tests: true - bin: "./bin/godot.macos.opt.tools.64" + bin: "./bin/godot.macos.opt.tools.x86_64" - name: Template (target=release, tools=no) cache-name: macos-template @@ -34,7 +34,7 @@ jobs: sconsflags: debug_symbols=no steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Godot build cache uses: ./.github/actions/godot-cache diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index fea82791ed..557b67c970 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 # Azure repositories are not reliable, we need to prevent Azure giving us packages. - name: Make apt sources.list use the default Ubuntu repositories diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml index e04d49adde..9033e1ab1d 100644 --- a/.github/workflows/windows_builds.yml +++ b/.github/workflows/windows_builds.yml @@ -5,7 +5,7 @@ on: [push, pull_request] # SCONS_CACHE for windows must be set in the build environment env: # Only used for the cache key. Increment version to force clean build. - GODOT_BASE_BRANCH: master-v2 + GODOT_BASE_BRANCH: master SCONSFLAGS: verbose=yes warnings=all werror=yes module_text_server_fb_enabled=yes SCONS_CACHE_MSVC_CONFIG: true @@ -29,7 +29,7 @@ jobs: tests: true # Skip debug symbols, they're way too big with MSVC. sconsflags: debug_symbols=no - bin: "./bin/godot.windows.opt.tools.64.exe" + bin: "./bin/godot.windows.opt.tools.x86_64.exe" - name: Template (target=release, tools=no) cache-name: windows-template @@ -39,7 +39,7 @@ jobs: sconsflags: debug_symbols=no steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Godot build cache uses: ./.github/actions/godot-cache diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e5565e72ed..a1e8d3a59d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,7 +37,7 @@ Godot runs on a large variety of platforms and operating systems and devices. For bugs that are likely OS-specific and/or graphics-related, please also specify: -- Device (CPU model including architecture, e.g. x86, x86_64, ARM, etc.) +- Device (CPU model including architecture, e.g. x86_64, arm64, etc.) - GPU model (and the driver version in use if you know it) **Bug reports not including the required information may be closed at the diff --git a/SConstruct b/SConstruct index d0d03bd8dc..55ed3771ac 100644 --- a/SConstruct +++ b/SConstruct @@ -55,6 +55,7 @@ _helper_module("modules.modules_builders", "modules/modules_builders.py") import methods import glsl_builders import gles3_builders +from platform_methods import architectures, architecture_aliases if methods.get_cmdline_bool("tools", True): _helper_module("editor.editor_builders", "editor/editor_builders.py") @@ -161,12 +162,11 @@ if profile: opts = Variables(customs, ARGUMENTS) # Target build options -opts.Add("p", "Platform (alias for 'platform')", "") opts.Add("platform", "Target platform (%s)" % ("|".join(platform_list),), "") +opts.Add("p", "Platform (alias for 'platform')", "") opts.Add(BoolVariable("tools", "Build the tools (a.k.a. the Godot editor)", True)) opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release_debug", "release"))) -opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", "") -opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64"))) +opts.Add(EnumVariable("arch", "CPU architecture", "auto", ["auto"] + architectures, architecture_aliases)) opts.Add(EnumVariable("float", "Floating-point precision", "default", ("default", "32", "64"))) opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size", "none"))) opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False)) @@ -502,12 +502,17 @@ if selected_platform in platform_list: # Platform specific flags flag_list = platform_flags[selected_platform] for f in flag_list: - if not (f[0] in ARGUMENTS): # allow command line to override platform flags + if not (f[0] in ARGUMENTS) or ARGUMENTS[f[0]] == "auto": # Allow command line to override platform flags env[f[0]] = f[1] # Must happen after the flags' definition, so that they can be used by platform detect detect.configure(env) + print( + 'Building for platform "%s", architecture "%s", %s, target "%s".' + % (selected_platform, env["arch"], "editor" if env["tools"] else "template", env["target"]) + ) + # Set our C and C++ standard requirements. # C++17 is required as we need guaranteed copy elision as per GH-36436. # Prepending to make it possible to override. @@ -693,13 +698,7 @@ if selected_platform in platform_list: ) suffix += ".debug" - if env["arch"] != "": - suffix += "." + env["arch"] - elif env["bits"] == "32": - suffix += ".32" - elif env["bits"] == "64": - suffix += ".64" - + suffix += "." + env["arch"] suffix += env.extra_suffix sys.path.remove(tmppath) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 26b683db82..d46e242610 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -442,6 +442,15 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) { * If nothing was found, error out. */ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, bool p_upwards, bool p_ignore_override) { + if (!OS::get_singleton()->get_resource_dir().is_empty()) { + // OS will call ProjectSettings->get_resource_path which will be empty if not overridden! + // If the OS would rather use a specific location, then it will not be empty. + resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/"); + if (!resource_path.is_empty() && resource_path[resource_path.length() - 1] == '/') { + resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end. + } + } + // If looking for files in a network client, use it directly if (FileAccessNetworkClient::get_singleton()) { @@ -524,13 +533,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b // (Only Android -when reading from pck- and iOS use this.) if (!OS::get_singleton()->get_resource_dir().is_empty()) { - // OS will call ProjectSettings->get_resource_path which will be empty if not overridden! - // If the OS would rather use a specific location, then it will not be empty. - resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/"); - if (!resource_path.is_empty() && resource_path[resource_path.length() - 1] == '/') { - resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end. - } - Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); if (err == OK && !p_ignore_override) { // Optional, we don't mind if it fails. diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 6ce94fa1f3..bcc87d78c4 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -437,10 +437,6 @@ bool OS::is_stdout_verbose() const { return ::OS::get_singleton()->is_stdout_verbose(); } -void OS::dump_memory_to_file(const String &p_file) { - ::OS::get_singleton()->dump_memory_to_file(p_file.utf8().get_data()); -} - struct OSCoreBindImg { String path; Size2 size; @@ -667,7 +663,6 @@ void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("is_debug_build"), &OS::is_debug_build); - ClassDB::bind_method(D_METHOD("dump_memory_to_file", "file"), &OS::dump_memory_to_file); ClassDB::bind_method(D_METHOD("dump_resources_to_file", "file"), &OS::dump_resources_to_file); ClassDB::bind_method(D_METHOD("print_resources_in_use", "short"), &OS::print_resources_in_use, DEFVAL(false)); ClassDB::bind_method(D_METHOD("print_all_resources", "tofile"), &OS::print_all_resources, DEFVAL("")); diff --git a/core/core_bind.h b/core/core_bind.h index 3624bdf178..642a0c00c7 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -201,7 +201,6 @@ public: String get_model_name() const; - void dump_memory_to_file(const String &p_file); void dump_resources_to_file(const String &p_file); void print_resources_in_use(bool p_short = false); diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 299b60872d..c4d83d4765 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -613,6 +613,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_TYPE); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_HIDE_QUATERNION_EDIT); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE); diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index 8ed3d40c22..72c00bd678 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -115,6 +115,10 @@ FileAccess::CreateFunc FileAccess::get_create_func(AccessType p_access) { return create_func[p_access]; } +FileAccess::AccessType FileAccess::get_access_type() const { + return _access_type; +} + String FileAccess::fix_path(const String &p_path) const { //helper used by file accesses that use a single filesystem diff --git a/core/io/file_access.h b/core/io/file_access.h index 3386800686..fc0eb95d44 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -60,6 +60,7 @@ public: virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) = 0; protected: + AccessType get_access_type() const; String fix_path(const String &p_path) const; virtual Error _open(const String &p_path, int p_mode_flags) = 0; ///< open a file virtual uint64_t _get_modified_time(const String &p_file) = 0; diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index 9cf7c9caba..d09697b951 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -44,7 +44,7 @@ bool ImageFormatLoader::recognize(const String &p_extension) const { return false; } -Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom, bool p_force_linear, float p_scale) { +Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom, uint32_t p_flags, float p_scale) { ERR_FAIL_COND_V_MSG(p_image.is_null(), ERR_INVALID_PARAMETER, "It's not a reference to a valid Image object."); Ref<FileAccess> f = p_custom; @@ -60,7 +60,7 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> if (!loader[i]->recognize(extension)) { continue; } - Error err = loader[i]->load_image(p_image, f, p_force_linear, p_scale); + Error err = loader[i]->load_image(p_image, f, p_flags, p_scale); if (err != OK) { ERR_PRINT("Error loading image: " + p_file); } @@ -152,7 +152,7 @@ Ref<Resource> ResourceFormatLoaderImage::load(const String &p_path, const String Ref<Image> image; image.instantiate(); - Error err = ImageLoader::loader[idx]->load_image(image, f, false, 1.0); + Error err = ImageLoader::loader[idx]->load_image(image, f); if (err != OK) { if (r_error) { diff --git a/core/io/image_loader.h b/core/io/image_loader.h index c91d382c25..cb64d2310e 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -44,11 +44,16 @@ class ImageFormatLoader { friend class ResourceFormatLoaderImage; protected: - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, bool p_force_linear, float p_scale) = 0; + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, uint32_t p_flags = (uint32_t)FLAG_NONE, float p_scale = 1.0) = 0; virtual void get_recognized_extensions(List<String> *p_extensions) const = 0; bool recognize(const String &p_extension) const; public: + enum LoaderFlags { + FLAG_NONE = 0, + FLAG_FORCE_LINEAR = 1, + }; + virtual ~ImageFormatLoader() {} }; @@ -58,7 +63,7 @@ class ImageLoader { protected: public: - static Error load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom = Ref<FileAccess>(), bool p_force_linear = false, float p_scale = 1.0); + static Error load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom = Ref<FileAccess>(), uint32_t p_flags = (uint32_t)ImageFormatLoader::FLAG_NONE, float p_scale = 1.0); static void get_recognized_extensions(List<String> *p_extensions); static ImageFormatLoader *recognize(const String &p_extension); diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h index b3d63c0094..1a80faaa12 100644 --- a/core/math/audio_frame.h +++ b/core/math/audio_frame.h @@ -48,7 +48,7 @@ static inline float undenormalise(volatile float f) { } static const float AUDIO_PEAK_OFFSET = 0.0000000001f; -static const float AUDIO_MIN_PEAK_DB = -200.0f; // linear2db(AUDIO_PEAK_OFFSET) +static const float AUDIO_MIN_PEAK_DB = -200.0f; // linear_to_db(AUDIO_PEAK_OFFSET) struct AudioFrame { //left and right samples diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 463e119add..cae76b182a 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -229,11 +229,11 @@ public: return value; } - static _ALWAYS_INLINE_ double deg2rad(double p_y) { return p_y * (Math_PI / 180.0); } - static _ALWAYS_INLINE_ float deg2rad(float p_y) { return p_y * (float)(Math_PI / 180.0); } + static _ALWAYS_INLINE_ double deg_to_rad(double p_y) { return p_y * (Math_PI / 180.0); } + static _ALWAYS_INLINE_ float deg_to_rad(float p_y) { return p_y * (float)(Math_PI / 180.0); } - static _ALWAYS_INLINE_ double rad2deg(double p_y) { return p_y * (180.0 / Math_PI); } - static _ALWAYS_INLINE_ float rad2deg(float p_y) { return p_y * (float)(180.0 / Math_PI); } + static _ALWAYS_INLINE_ double rad_to_deg(double p_y) { return p_y * (180.0 / Math_PI); } + static _ALWAYS_INLINE_ float rad_to_deg(float p_y) { return p_y * (float)(180.0 / Math_PI); } static _ALWAYS_INLINE_ double lerp(double p_from, double p_to, double p_weight) { return p_from + (p_to - p_from) * p_weight; } static _ALWAYS_INLINE_ float lerp(float p_from, float p_to, float p_weight) { return p_from + (p_to - p_from) * p_weight; } @@ -253,6 +253,35 @@ public: (-p_pre + 3.0f * p_from - 3.0f * p_to + p_post) * (p_weight * p_weight * p_weight)); } + static _ALWAYS_INLINE_ double cubic_interpolate_angle(double p_from, double p_to, double p_pre, double p_post, double p_weight) { + double from_rot = fmod(p_from, Math_TAU); + + double pre_diff = fmod(p_pre - from_rot, Math_TAU); + double pre_rot = from_rot + fmod(2.0 * pre_diff, Math_TAU) - pre_diff; + + double to_diff = fmod(p_to - from_rot, Math_TAU); + double to_rot = from_rot + fmod(2.0 * to_diff, Math_TAU) - to_diff; + + double post_diff = fmod(p_post - to_rot, Math_TAU); + double post_rot = to_rot + fmod(2.0 * post_diff, Math_TAU) - post_diff; + + return cubic_interpolate(from_rot, to_rot, pre_rot, post_rot, p_weight); + } + static _ALWAYS_INLINE_ float cubic_interpolate_angle(float p_from, float p_to, float p_pre, float p_post, float p_weight) { + float from_rot = fmod(p_from, (float)Math_TAU); + + float pre_diff = fmod(p_pre - from_rot, (float)Math_TAU); + float pre_rot = from_rot + fmod(2.0f * pre_diff, (float)Math_TAU) - pre_diff; + + float to_diff = fmod(p_to - from_rot, (float)Math_TAU); + float to_rot = from_rot + fmod(2.0f * to_diff, (float)Math_TAU) - to_diff; + + float post_diff = fmod(p_post - to_rot, (float)Math_TAU); + float post_rot = to_rot + fmod(2.0f * post_diff, (float)Math_TAU) - post_diff; + + return cubic_interpolate(from_rot, to_rot, pre_rot, post_rot, p_weight); + } + static _ALWAYS_INLINE_ double cubic_interpolate_in_time(double p_from, double p_to, double p_pre, double p_post, double p_weight, double p_to_t, double p_pre_t, double p_post_t) { /* Barry-Goldman method */ @@ -276,6 +305,37 @@ public: return Math::lerp(b1, b2, p_to_t == 0 ? 0.5f : t / p_to_t); } + static _ALWAYS_INLINE_ double cubic_interpolate_angle_in_time(double p_from, double p_to, double p_pre, double p_post, double p_weight, + double p_to_t, double p_pre_t, double p_post_t) { + double from_rot = fmod(p_from, Math_TAU); + + double pre_diff = fmod(p_pre - from_rot, Math_TAU); + double pre_rot = from_rot + fmod(2.0 * pre_diff, Math_TAU) - pre_diff; + + double to_diff = fmod(p_to - from_rot, Math_TAU); + double to_rot = from_rot + fmod(2.0 * to_diff, Math_TAU) - to_diff; + + double post_diff = fmod(p_post - to_rot, Math_TAU); + double post_rot = to_rot + fmod(2.0 * post_diff, Math_TAU) - post_diff; + + return cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t); + } + static _ALWAYS_INLINE_ float cubic_interpolate_angle_in_time(float p_from, float p_to, float p_pre, float p_post, float p_weight, + float p_to_t, float p_pre_t, float p_post_t) { + float from_rot = fmod(p_from, (float)Math_TAU); + + float pre_diff = fmod(p_pre - from_rot, (float)Math_TAU); + float pre_rot = from_rot + fmod(2.0f * pre_diff, (float)Math_TAU) - pre_diff; + + float to_diff = fmod(p_to - from_rot, (float)Math_TAU); + float to_rot = from_rot + fmod(2.0f * to_diff, (float)Math_TAU) - to_diff; + + float post_diff = fmod(p_post - to_rot, (float)Math_TAU); + float post_rot = to_rot + fmod(2.0f * post_diff, (float)Math_TAU) - post_diff; + + return cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t); + } + static _ALWAYS_INLINE_ double bezier_interpolate(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) { /* Formula from Wikipedia article on Bezier curves. */ double omt = (1.0 - p_t); @@ -331,11 +391,11 @@ public: static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; } static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; } - static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } - static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log(p_linear) * (float)8.6858896380650365530225783783321; } + static _ALWAYS_INLINE_ double linear_to_db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } + static _ALWAYS_INLINE_ float linear_to_db(float p_linear) { return Math::log(p_linear) * (float)8.6858896380650365530225783783321; } - static _ALWAYS_INLINE_ double db2linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); } - static _ALWAYS_INLINE_ float db2linear(float p_db) { return Math::exp(p_db * (float)0.11512925464970228420089957273422); } + static _ALWAYS_INLINE_ double db_to_linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); } + static _ALWAYS_INLINE_ float db_to_linear(float p_db) { return Math::exp(p_db * (float)0.11512925464970228420089957273422); } static _ALWAYS_INLINE_ double round(double p_val) { return ::round(p_val); } static _ALWAYS_INLINE_ float round(float p_val) { return ::roundf(p_val); } diff --git a/core/math/projection.cpp b/core/math/projection.cpp index edf8bf36cd..863fe6ee79 100644 --- a/core/math/projection.cpp +++ b/core/math/projection.cpp @@ -255,7 +255,7 @@ void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t } real_t sine, cotangent, deltaZ; - real_t radians = Math::deg2rad(p_fovy_degrees / 2.0); + real_t radians = Math::deg_to_rad(p_fovy_degrees / 2.0); deltaZ = p_z_far - p_z_near; sine = Math::sin(radians); @@ -282,7 +282,7 @@ void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t real_t left, right, modeltranslation, ymax, xmax, frustumshift; - ymax = p_z_near * tan(Math::deg2rad(p_fovy_degrees / 2.0)); + ymax = p_z_near * tan(Math::deg_to_rad(p_fovy_degrees / 2.0)); xmax = ymax * p_aspect; frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist; @@ -816,7 +816,7 @@ real_t Projection::get_fov() const { right_plane.normalize(); if ((matrix[8] == 0) && (matrix[9] == 0)) { - return Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0; + return Math::rad_to_deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0; } else { // our frustum is asymmetrical need to calculate the left planes angle separately.. Plane left_plane = Plane(matrix[3] + matrix[0], @@ -825,7 +825,7 @@ real_t Projection::get_fov() const { matrix[15] + matrix[12]); left_plane.normalize(); - return Math::rad2deg(Math::acos(Math::abs(left_plane.normal.x))) + Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))); + return Math::rad_to_deg(Math::acos(Math::abs(left_plane.normal.x))) + Math::rad_to_deg(Math::acos(Math::abs(right_plane.normal.x))); } } diff --git a/core/math/projection.h b/core/math/projection.h index a3d2d7720b..f149d307b3 100644 --- a/core/math/projection.h +++ b/core/math/projection.h @@ -96,7 +96,7 @@ struct Projection { Projection jitter_offseted(const Vector2 &p_offset) const; static real_t get_fovy(real_t p_fovx, real_t p_aspect) { - return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0); + return Math::rad_to_deg(Math::atan(p_aspect * Math::tan(Math::deg_to_rad(p_fovx) * 0.5)) * 2.0); } real_t get_z_far() const; diff --git a/core/object/object.h b/core/object/object.h index 13a40191e6..1784c1fe70 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -95,6 +95,7 @@ enum PropertyHint { PROPERTY_HINT_LOCALIZABLE_STRING, PROPERTY_HINT_NODE_TYPE, ///< a node object type PROPERTY_HINT_HIDE_QUATERNION_EDIT, /// Only Node3D::transform should hide the quaternion editor. + PROPERTY_HINT_PASSWORD, 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 6091079241..45cd7109e2 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -186,10 +186,6 @@ void OS::set_stderr_enabled(bool p_enabled) { _stderr_enabled = p_enabled; } -void OS::dump_memory_to_file(const char *p_file) { - //Memory::dump_static_mem_to_file(p_file); -} - static Ref<FileAccess> _OSPRF; static void _OS_printres(Object *p_obj) { diff --git a/core/os/os.h b/core/os/os.h index be9d73c22d..ff769cc4f1 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -246,7 +246,6 @@ public: virtual bool is_disable_crash_handler() const { return false; } virtual void initialize_debugging() {} - virtual void dump_memory_to_file(const char *p_file); virtual void dump_resources_to_file(const char *p_file); virtual void print_resources_in_use(bool p_short = false); virtual void print_all_resources(String p_to_file = ""); diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 21c9c483a5..1be17405c7 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -367,11 +367,20 @@ struct VariantUtilityFunctions { return Math::cubic_interpolate(from, to, pre, post, weight); } + static inline double cubic_interpolate_angle(double from, double to, double pre, double post, double weight) { + return Math::cubic_interpolate_angle(from, to, pre, post, weight); + } + static inline double cubic_interpolate_in_time(double from, double to, double pre, double post, double weight, double to_t, double pre_t, double post_t) { return Math::cubic_interpolate_in_time(from, to, pre, post, weight, to_t, pre_t, post_t); } + static inline double cubic_interpolate_angle_in_time(double from, double to, double pre, double post, double weight, + double to_t, double pre_t, double post_t) { + return Math::cubic_interpolate_angle_in_time(from, to, pre, post, weight, to_t, pre_t, post_t); + } + static inline double bezier_interpolate(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) { return Math::bezier_interpolate(p_start, p_control_1, p_control_2, p_end, p_t); } @@ -396,20 +405,20 @@ struct VariantUtilityFunctions { return Math::move_toward(from, to, delta); } - static inline double deg2rad(double angle_deg) { - return Math::deg2rad(angle_deg); + static inline double deg_to_rad(double angle_deg) { + return Math::deg_to_rad(angle_deg); } - static inline double rad2deg(double angle_rad) { - return Math::rad2deg(angle_rad); + static inline double rad_to_deg(double angle_rad) { + return Math::rad_to_deg(angle_rad); } - static inline double linear2db(double linear) { - return Math::linear2db(linear); + static inline double linear_to_db(double linear) { + return Math::linear_to_db(linear); } - static inline double db2linear(double db) { - return Math::db2linear(db); + static inline double db_to_linear(double db) { + return Math::db_to_linear(db); } static inline Variant wrap(const Variant &p_x, const Variant &p_min, const Variant &p_max, Callable::CallError &r_error) { @@ -837,13 +846,13 @@ struct VariantUtilityFunctions { r_error.error = Callable::CallError::CALL_OK; } - static inline String var2str(const Variant &p_var) { + static inline String var_to_str(const Variant &p_var) { String vars; VariantWriter::write_to_string(p_var, vars); return vars; } - static inline Variant str2var(const String &p_var) { + static inline Variant str_to_var(const String &p_var) { VariantParser::StreamString ss; ss.s = p_var; @@ -855,7 +864,7 @@ struct VariantUtilityFunctions { return ret; } - static inline PackedByteArray var2bytes(const Variant &p_var) { + static inline PackedByteArray var_to_bytes(const Variant &p_var) { int len; Error err = encode_variant(p_var, nullptr, len, false); if (err != OK) { @@ -875,7 +884,7 @@ struct VariantUtilityFunctions { return barr; } - static inline PackedByteArray var2bytes_with_objects(const Variant &p_var) { + static inline PackedByteArray var_to_bytes_with_objects(const Variant &p_var) { int len; Error err = encode_variant(p_var, nullptr, len, true); if (err != OK) { @@ -895,7 +904,7 @@ struct VariantUtilityFunctions { return barr; } - static inline Variant bytes2var(const PackedByteArray &p_arr) { + static inline Variant bytes_to_var(const PackedByteArray &p_arr) { Variant ret; { const uint8_t *r = p_arr.ptr(); @@ -907,7 +916,7 @@ struct VariantUtilityFunctions { return ret; } - static inline Variant bytes2var_with_objects(const PackedByteArray &p_arr) { + static inline Variant bytes_to_var_with_objects(const PackedByteArray &p_arr) { Variant ret; { const uint8_t *r = p_arr.ptr(); @@ -1419,7 +1428,9 @@ void Variant::_register_variant_utility_functions() { FUNCBINDVR3(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerpf, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(cubic_interpolate, sarray("from", "to", "pre", "post", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(cubic_interpolate_angle, sarray("from", "to", "pre", "post", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(cubic_interpolate_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(cubic_interpolate_angle_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1428,10 +1439,10 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(deg2rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(rad2deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(linear2db, sarray("lin"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(db2linear, sarray("db"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(deg_to_rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(rad_to_deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(linear_to_db, sarray("lin"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(db_to_linear, sarray("db"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDVR3(wrap, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(wrapi, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1479,14 +1490,14 @@ void Variant::_register_variant_utility_functions() { FUNCBINDVARARGV(push_error, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(push_warning, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(var2str, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(str2var, sarray("string"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(var_to_str, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(str_to_var, sarray("string"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(var2bytes, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(bytes2var, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(var_to_bytes, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(bytes_to_var, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(var2bytes_with_objects, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(bytes2var_with_objects, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(var_to_bytes_with_objects, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(bytes_to_var_with_objects, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDR(hash, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index bd500f6b35..71579d5173 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -66,7 +66,7 @@ <description> Returns the arc cosine of [param x] in radians. Use to get the angle of cosine [param x]. [param x] must be between [code]-1.0[/code] and [code]1.0[/code] (inclusive), otherwise, [method acos] will return [constant @GDScript.NAN]. [codeblock] - # c is 0.523599 or 30 degrees if converted with rad2deg(c) + # c is 0.523599 or 30 degrees if converted with rad_to_deg(c) var c = acos(0.866025) [/codeblock] </description> @@ -77,7 +77,7 @@ <description> Returns the arc sine of [param x] in radians. Use to get the angle of sine [param x]. [param x] must be between [code]-1.0[/code] and [code]1.0[/code] (inclusive), otherwise, [method asin] will return [constant @GDScript.NAN]. [codeblock] - # s is 0.523599 or 30 degrees if converted with rad2deg(s) + # s is 0.523599 or 30 degrees if converted with rad_to_deg(s) var s = asin(0.5) [/codeblock] </description> @@ -117,15 +117,15 @@ Returns the point at the given [param t] on a one-dimnesional [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bezier curve[/url] defined by the given [param control_1], [param control_2], and [param end] points. </description> </method> - <method name="bytes2var"> + <method name="bytes_to_var"> <return type="Variant" /> <param index="0" name="bytes" type="PackedByteArray" /> <description> Decodes a byte array back to a [Variant] value, without decoding objects. - [b]Note:[/b] If you need object deserialization, see [method bytes2var_with_objects]. + [b]Note:[/b] If you need object deserialization, see [method bytes_to_var_with_objects]. </description> </method> - <method name="bytes2var_with_objects"> + <method name="bytes_to_var_with_objects"> <return type="Variant" /> <param index="0" name="bytes" type="PackedByteArray" /> <description> @@ -232,9 +232,9 @@ <description> Returns the cosine of angle [param angle_rad] in radians. [codeblock] - cos(PI * 2) # Returns 1.0 - cos(PI) # Returns -1.0 - cos(deg2rad(90)) # Returns 0.0 + cos(PI * 2) # Returns 1.0 + cos(PI) # Returns -1.0 + cos(deg_to_rad(90)) # Returns 0.0 [/codeblock] </description> </method> @@ -260,6 +260,32 @@ Cubic interpolates between two values by the factor defined in [param weight] with pre and post values. </description> </method> + <method name="cubic_interpolate_angle"> + <return type="float" /> + <param index="0" name="from" type="float" /> + <param index="1" name="to" type="float" /> + <param index="2" name="pre" type="float" /> + <param index="3" name="post" type="float" /> + <param index="4" name="weight" type="float" /> + <description> + Cubic interpolates between two rotation values with shortest path by the factor defined in [param weight] with pre and post values. See also [method lerp_angle]. + </description> + </method> + <method name="cubic_interpolate_angle_in_time"> + <return type="float" /> + <param index="0" name="from" type="float" /> + <param index="1" name="to" type="float" /> + <param index="2" name="pre" type="float" /> + <param index="3" name="post" type="float" /> + <param index="4" name="weight" type="float" /> + <param index="5" name="to_t" type="float" /> + <param index="6" name="pre_t" type="float" /> + <param index="7" name="post_t" type="float" /> + <description> + Cubic interpolates between two rotation values with shortest path by the factor defined in [param weight] with pre and post values. See also [method lerp_angle]. + It can perform smoother interpolation than [code]cubic_interpolate()[/code] by the time values. + </description> + </method> <method name="cubic_interpolate_in_time"> <return type="float" /> <param index="0" name="from" type="float" /> @@ -275,21 +301,21 @@ It can perform smoother interpolation than [code]cubic_interpolate()[/code] by the time values. </description> </method> - <method name="db2linear"> + <method name="db_to_linear"> <return type="float" /> <param index="0" name="db" type="float" /> <description> Converts from decibels to linear energy (audio). </description> </method> - <method name="deg2rad"> + <method name="deg_to_rad"> <return type="float" /> <param index="0" name="deg" type="float" /> <description> Converts an angle expressed in degrees to radians. [codeblock] # r is 3.141593 - var r = deg2rad(180) + var r = deg_to_rad(180) [/codeblock] </description> </method> @@ -513,8 +539,8 @@ extends Sprite var elapsed = 0.0 func _process(delta): - var min_angle = deg2rad(0.0) - var max_angle = deg2rad(90.0) + var min_angle = deg_to_rad(0.0) + var max_angle = deg_to_rad(90.0) rotation = lerp_angle(min_angle, max_angle, elapsed) elapsed += delta [/codeblock] @@ -534,7 +560,7 @@ See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep]. </description> </method> - <method name="linear2db"> + <method name="linear_to_db"> <return type="float" /> <param index="0" name="lin" type="float" /> <description> @@ -543,7 +569,7 @@ # "Slider" refers to a node that inherits Range such as HSlider or VSlider. # Its range must be configured to go from 0 to 1. # Change the bus name if you'd like to change the volume of a specific bus only. - AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear2db($Slider.value)) + AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear_to_db($Slider.value)) [/codeblock] </description> </method> @@ -787,13 +813,13 @@ [/codeblock] </description> </method> - <method name="rad2deg"> + <method name="rad_to_deg"> <return type="float" /> <param index="0" name="rad" type="float" /> <description> Converts an angle expressed in radians to degrees. [codeblock] - rad2deg(0.523599) # Returns 30 + rad_to_deg(0.523599) # Returns 30 [/codeblock] </description> </method> @@ -974,8 +1000,8 @@ <description> Returns the sine of angle [param angle_rad] in radians. [codeblock] - sin(0.523599) # Returns 0.5 - sin(deg2rad(90)) # Returns 1.0 + sin(0.523599) # Returns 0.5 + sin(deg_to_rad(90)) # Returns 1.0 [/codeblock] </description> </method> @@ -1054,14 +1080,14 @@ Converts one or more arguments of any type to string in the best way possible. </description> </method> - <method name="str2var"> + <method name="str_to_var"> <return type="Variant" /> <param index="0" name="string" type="String" /> <description> - Converts a formatted string that was returned by [method var2str] to the original value. + Converts a formatted [param string] that was returned by [method var_to_str] to the original value. [codeblock] var a = '{ "a": 1, "b": 2 }' - var b = str2var(a) + var b = str_to_var(a) print(b["a"]) # Prints 1 [/codeblock] </description> @@ -1072,7 +1098,7 @@ <description> Returns the tangent of angle [param angle_rad] in radians. [codeblock] - tan(deg2rad(45)) # Returns 1 + tan(deg_to_rad(45)) # Returns 1 [/codeblock] </description> </method> @@ -1103,29 +1129,29 @@ [/codeblock] </description> </method> - <method name="var2bytes"> + <method name="var_to_bytes"> <return type="PackedByteArray" /> <param index="0" name="variable" type="Variant" /> <description> - Encodes a [Variant] value to a byte array, without encoding objects. Deserialization can be done with [method bytes2var]. - [b]Note:[/b] If you need object serialization, see [method var2bytes_with_objects]. + Encodes a [Variant] value to a byte array, without encoding objects. Deserialization can be done with [method bytes_to_var]. + [b]Note:[/b] If you need object serialization, see [method var_to_bytes_with_objects]. </description> </method> - <method name="var2bytes_with_objects"> + <method name="var_to_bytes_with_objects"> <return type="PackedByteArray" /> <param index="0" name="variable" type="Variant" /> <description> - Encodes a [Variant] value to a byte array. Encoding objects is allowed (and can potentially include code). Deserialization can be done with [method bytes2var_with_objects]. + Encodes a [Variant] value to a byte array. Encoding objects is allowed (and can potentially include code). Deserialization can be done with [method bytes_to_var_with_objects]. </description> </method> - <method name="var2str"> + <method name="var_to_str"> <return type="String" /> <param index="0" name="variable" type="Variant" /> <description> - Converts a Variant [param variable] to a formatted string that can later be parsed using [method str2var]. + Converts a Variant [param variable] to a formatted string that can later be parsed using [method str_to_var]. [codeblock] a = { "a": 1, "b": 2 } - print(var2str(a)) + print(var_to_str(a)) [/codeblock] prints [codeblock] @@ -2711,7 +2737,10 @@ <constant name="PROPERTY_HINT_HIDE_QUATERNION_EDIT" value="45" enum="PropertyHint"> Hints that a quaternion property should disable the temporary euler editor. </constant> - <constant name="PROPERTY_HINT_MAX" value="46" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PASSWORD" value="46" enum="PropertyHint"> + Hints that a string property is a password, and every character is replaced with the secret character. + </constant> + <constant name="PROPERTY_HINT_MAX" value="47" enum="PropertyHint"> </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags"> </constant> diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index faa9ae3569..df0fb11ac7 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -600,8 +600,13 @@ <constant name="INTERPOLATION_CUBIC" value="2" enum="InterpolationType"> Cubic interpolation. </constant> - <constant name="INTERPOLATION_CUBIC_IN_TIME" value="3" enum="InterpolationType"> - Cubic interpolation with uniformed time. + <constant name="INTERPOLATION_LINEAR_ANGLE" value="3" enum="InterpolationType"> + Linear interpolation with shortest path rotation. + [b]Note:[/b] The result value is always normalized and may not match the key value. + </constant> + <constant name="INTERPOLATION_CUBIC_ANGLE" value="4" enum="InterpolationType"> + Cubic interpolation with shortest path rotation. + [b]Note:[/b] The result value is always normalized and may not match the key value. </constant> <constant name="UPDATE_CONTINUOUS" value="0" enum="UpdateMode"> Update between keyframes. diff --git a/doc/classes/AnimationNodeStateMachineTransition.xml b/doc/classes/AnimationNodeStateMachineTransition.xml index beb259b12b..1b5a795b3c 100644 --- a/doc/classes/AnimationNodeStateMachineTransition.xml +++ b/doc/classes/AnimationNodeStateMachineTransition.xml @@ -9,7 +9,7 @@ </tutorials> <members> <member name="advance_condition" type="StringName" setter="set_advance_condition" getter="get_advance_condition" default="&"""> - Turn on auto advance when this condition is set. The provided name will become a boolean parameter on the [AnimationTree] that can be controlled from code (see [url=$DOCS_URL/tutorials/animation/animation_tree.html#controlling-from-code][/url]). For example, if [member AnimationTree.tree_root] is an [AnimationNodeStateMachine] and [member advance_condition] is set to [code]"idle"[/code]: + Turn on auto advance when this condition is set. The provided name will become a boolean parameter on the [AnimationTree] that can be controlled from code (see [url=$DOCS_URL/tutorials/animation/animation_tree.html#controlling-from-code]Using AnimationTree[/url]). For example, if [member AnimationTree.tree_root] is an [AnimationNodeStateMachine] and [member advance_condition] is set to [code]"idle"[/code]: [codeblocks] [gdscript] $animation_tree.set("parameters/conditions/idle", is_on_floor and (linear_velocity.x == 0)) diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index fcdf59e36e..33a129a48e 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -718,7 +718,7 @@ </constant> <constant name="BILLBOARD_PARTICLES" value="3" enum="BillboardMode"> Used for particle systems when assigned to [GPUParticles3D] and [CPUParticles3D] nodes. Enables [code]particles_anim_*[/code] properties. - The [member ParticlesMaterial.anim_speed_min] or [member CPUParticles3D.anim_speed_min] should also be set to a value bigger than zero for the animation to play. + The [member ParticleProcessMaterial.anim_speed_min] or [member CPUParticles3D.anim_speed_min] should also be set to a value bigger than zero for the animation to play. </constant> <constant name="TEXTURE_CHANNEL_RED" value="0" enum="TextureChannel"> Used to read from the red channel of a texture. diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml index 64e9310181..906789d09f 100644 --- a/doc/classes/CPUParticles2D.xml +++ b/doc/classes/CPUParticles2D.xml @@ -15,7 +15,7 @@ <return type="void" /> <param index="0" name="particles" type="Node" /> <description> - Sets this node's properties to match a given [GPUParticles2D] node with an assigned [ParticlesMaterial]. + Sets this node's properties to match a given [GPUParticles2D] node with an assigned [ParticleProcessMaterial]. </description> </method> <method name="get_param_curve" qualifiers="const"> diff --git a/doc/classes/CPUParticles3D.xml b/doc/classes/CPUParticles3D.xml index bb1dcd322f..99fd0501fc 100644 --- a/doc/classes/CPUParticles3D.xml +++ b/doc/classes/CPUParticles3D.xml @@ -14,7 +14,7 @@ <return type="void" /> <param index="0" name="particles" type="Node" /> <description> - Sets this node's properties to match a given [GPUParticles3D] node with an assigned [ParticlesMaterial]. + Sets this node's properties to match a given [GPUParticles3D] node with an assigned [ParticleProcessMaterial]. </description> </method> <method name="get_param_curve" qualifiers="const"> diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index fe1fe498d1..d1fdca5814 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -9,7 +9,7 @@ Canvas items are drawn in tree order. By default, children are on top of their parents so a root [CanvasItem] will be drawn behind everything. This behavior can be changed on a per-item basis. A [CanvasItem] can also be hidden, which will also hide its children. It provides many ways to change parameters such as modulation (for itself and its children) and self modulation (only for itself), as well as its blend mode. Ultimately, a transform notification can be requested, which will notify the node that its global position changed in case the parent tree changed. - [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg2rad]. + [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg_to_rad]. </description> <tutorials> <link title="Viewport and canvas transforms">$DOCS_URL/tutorials/2d/2d_transforms.html</link> @@ -107,6 +107,23 @@ After submitting all animations slices via [method draw_animation_slice], this function can be used to revert drawing to its default state (all subsequent drawing commands will be visible). If you don't care about this particular use case, usage of this function after submitting the slices is not required. </description> </method> + <method name="draw_lcd_texture_rect_region"> + <return type="void" /> + <param index="0" name="texture" type="Texture2D" /> + <param index="1" name="rect" type="Rect2" /> + <param index="2" name="src_rect" type="Rect2" /> + <param index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> + <description> + Draws a textured rectangle region of the font texture with LCD sub-pixel anti-aliasing at a given position, optionally modulated by a color. + Texture is drawn using the following blend operation, blend mode of the [CanvasItemMaterial] is ignored: + [codeblock] + dst.r = texture.r * modulate.r * modulate.a + dst.r * (1.0 - texture.r * modulate.a); + dst.g = texture.g * modulate.g * modulate.a + dst.g * (1.0 - texture.g * modulate.a); + dst.b = texture.b * modulate.b * modulate.a + dst.b * (1.0 - texture.b * modulate.a); + dst.a = modulate.a + dst.a * (1.0 - modulate.a); + [/codeblock] + </description> + </method> <method name="draw_line"> <return type="void" /> <param index="0" name="from" type="Vector2" /> diff --git a/doc/classes/CanvasItemMaterial.xml b/doc/classes/CanvasItemMaterial.xml index 22daf79074..59226840bc 100644 --- a/doc/classes/CanvasItemMaterial.xml +++ b/doc/classes/CanvasItemMaterial.xml @@ -28,7 +28,7 @@ [b]Note:[/b] This property is only used and visible in the editor if [member particles_animation] is [code]true[/code]. </member> <member name="particles_animation" type="bool" setter="set_particles_animation" getter="get_particles_animation" default="false"> - If [code]true[/code], enable spritesheet-based animation features when assigned to [GPUParticles2D] and [CPUParticles2D] nodes. The [member ParticlesMaterial.anim_speed_max] or [member CPUParticles2D.anim_speed_max] should also be set to a positive value for the animation to play. + If [code]true[/code], enable spritesheet-based animation features when assigned to [GPUParticles2D] and [CPUParticles2D] nodes. The [member ParticleProcessMaterial.anim_speed_max] or [member CPUParticles2D.anim_speed_max] should also be set to a positive value for the animation to play. This property (and other [code]particles_anim_*[/code] properties that depend on it) has no effect on other types of nodes. </member> </members> diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml index ff2c3a8855..555137ac45 100644 --- a/doc/classes/CanvasLayer.xml +++ b/doc/classes/CanvasLayer.xml @@ -35,11 +35,11 @@ <member name="custom_viewport" type="Node" setter="set_custom_viewport" getter="get_custom_viewport"> The custom [Viewport] node assigned to the [CanvasLayer]. If [code]null[/code], uses the default viewport instead. </member> - <member name="follow_viewport_enable" type="bool" setter="set_follow_viewport" getter="is_following_viewport" default="false"> + <member name="follow_viewport_enabled" type="bool" setter="set_follow_viewport" getter="is_following_viewport" default="false"> Sets the layer to follow the viewport in order to simulate a pseudo 3D effect. </member> <member name="follow_viewport_scale" type="float" setter="set_follow_viewport_scale" getter="get_follow_viewport_scale" default="1.0"> - Scales the layer when using [member follow_viewport_enable]. Layers moving into the foreground should have increasing scales, while layers moving into the background should have decreasing scales. + Scales the layer when using [member follow_viewport_enabled]. Layers moving into the foreground should have increasing scales, while layers moving into the background should have decreasing scales. </member> <member name="layer" type="int" setter="set_layer" getter="get_layer" default="1"> Layer index for draw order. Lower values are drawn first. diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml index b0594b6409..2f8e1a7bb8 100644 --- a/doc/classes/CharacterBody2D.xml +++ b/doc/classes/CharacterBody2D.xml @@ -131,7 +131,7 @@ <method name="move_and_slide"> <return type="bool" /> <description> - Moves the body based on [member velocity]. If the body collides with another, it will slide along the other body (by default only on floor) rather than stop immediately. If the other body is a [CharacterBody2D] or [RigidDynamicBody2D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes. + Moves the body based on [member velocity]. If the body collides with another, it will slide along the other body (by default only on floor) rather than stop immediately. If the other body is a [CharacterBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes. Modifies [member velocity] if a slide collision occurred. To get the latest collision call [method get_last_slide_collision], for detailed information about collisions that occurred, use [method get_slide_collision]. When the body touches a moving platform, the platform's velocity is automatically added to the body motion. If a collision occurs due to the platform's motion, it will always be first in the slide collisions. The general behavior and available properties change according to the [member motion_mode]. @@ -164,13 +164,13 @@ <member name="motion_mode" type="int" setter="set_motion_mode" getter="get_motion_mode" enum="CharacterBody2D.MotionMode" default="0"> Sets the motion mode which defines the behavior of [method move_and_slide]. See [enum MotionMode] constants for available modes. </member> - <member name="moving_platform_apply_velocity_on_leave" type="int" setter="set_moving_platform_apply_velocity_on_leave" getter="get_moving_platform_apply_velocity_on_leave" enum="CharacterBody2D.MovingPlatformApplyVelocityOnLeave" default="0"> - Sets the behavior to apply when you leave a moving platform. By default, to be physically accurate, when you leave the last platform velocity is applied. See [enum MovingPlatformApplyVelocityOnLeave] constants for available behavior. - </member> - <member name="moving_platform_floor_layers" type="int" setter="set_moving_platform_floor_layers" getter="get_moving_platform_floor_layers" default="4294967295"> + <member name="platform_floor_layers" type="int" setter="set_platform_floor_layers" getter="get_platform_floor_layers" default="4294967295"> Collision layers that will be included for detecting floor bodies that will act as moving platforms to be followed by the [CharacterBody2D]. By default, all floor bodies are detected and propagate their velocity. </member> - <member name="moving_platform_wall_layers" type="int" setter="set_moving_platform_wall_layers" getter="get_moving_platform_wall_layers" default="0"> + <member name="platform_on_leave" type="int" setter="set_platform_on_leave" getter="get_platform_on_leave" enum="CharacterBody2D.PlatformOnLeave" default="0"> + Sets the behavior to apply when you leave a moving platform. By default, to be physically accurate, when you leave the last platform velocity is applied. See [enum PlatformOnLeave] constants for available behavior. + </member> + <member name="platform_wall_layers" type="int" setter="set_platform_wall_layers" getter="get_platform_wall_layers" default="0"> Collision layers that will be included for detecting wall bodies that will act as moving platforms to be followed by the [CharacterBody2D]. By default, all wall bodies are ignored. </member> <member name="safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.08"> @@ -199,13 +199,13 @@ <constant name="MOTION_MODE_FLOATING" value="1" enum="MotionMode"> Apply when there is no notion of floor or ceiling. All collisions will be reported as [code]on_wall[/code]. In this mode, when you slide, the speed will always be constant. This mode is suitable for top-down games. </constant> - <constant name="PLATFORM_VEL_ON_LEAVE_ALWAYS" value="0" enum="MovingPlatformApplyVelocityOnLeave"> + <constant name="PLATFORM_ON_LEAVE_ADD_VELOCITY" value="0" enum="PlatformOnLeave"> Add the last platform velocity to the [member velocity] when you leave a moving platform. </constant> - <constant name="PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY" value="1" enum="MovingPlatformApplyVelocityOnLeave"> + <constant name="PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY" value="1" enum="PlatformOnLeave"> Add the last platform velocity to the [member velocity] when you leave a moving platform, but any downward motion is ignored. It's useful to keep full jump height even when the platform is moving down. </constant> - <constant name="PLATFORM_VEL_ON_LEAVE_NEVER" value="2" enum="MovingPlatformApplyVelocityOnLeave"> + <constant name="PLATFORM_ON_LEAVE_DO_NOTHING" value="2" enum="PlatformOnLeave"> Do nothing when leaving a platform. </constant> </constants> diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml index 7efdeb19b1..6a1975d40f 100644 --- a/doc/classes/CharacterBody3D.xml +++ b/doc/classes/CharacterBody3D.xml @@ -117,7 +117,7 @@ <method name="move_and_slide"> <return type="bool" /> <description> - Moves the body based on [member velocity]. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [CharacterBody3D] or [RigidDynamicBody3D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes. + Moves the body based on [member velocity]. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [CharacterBody3D] or [RigidBody3D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes. Modifies [member velocity] if a slide collision occurred. To get the latest collision call [method get_last_slide_collision], for more detailed information about collisions that occurred, use [method get_slide_collision]. When the body touches a moving platform, the platform's velocity is automatically added to the body motion. If a collision occurs due to the platform's motion, it will always be first in the slide collisions. Returns [code]true[/code] if the body collided, otherwise, returns [code]false[/code]. @@ -149,13 +149,13 @@ <member name="motion_mode" type="int" setter="set_motion_mode" getter="get_motion_mode" enum="CharacterBody3D.MotionMode" default="0"> Sets the motion mode which defines the behavior of [method move_and_slide]. See [enum MotionMode] constants for available modes. </member> - <member name="moving_platform_apply_velocity_on_leave" type="int" setter="set_moving_platform_apply_velocity_on_leave" getter="get_moving_platform_apply_velocity_on_leave" enum="CharacterBody3D.MovingPlatformApplyVelocityOnLeave" default="0"> - Sets the behavior to apply when you leave a moving platform. By default, to be physically accurate, when you leave the last platform velocity is applied. See [enum MovingPlatformApplyVelocityOnLeave] constants for available behavior. - </member> - <member name="moving_platform_floor_layers" type="int" setter="set_moving_platform_floor_layers" getter="get_moving_platform_floor_layers" default="4294967295"> + <member name="platform_floor_layers" type="int" setter="set_platform_floor_layers" getter="get_platform_floor_layers" default="4294967295"> Collision layers that will be included for detecting floor bodies that will act as moving platforms to be followed by the [CharacterBody3D]. By default, all floor bodies are detected and propagate their velocity. </member> - <member name="moving_platform_wall_layers" type="int" setter="set_moving_platform_wall_layers" getter="get_moving_platform_wall_layers" default="0"> + <member name="platform_on_leave" type="int" setter="set_platform_on_leave" getter="get_platform_on_leave" enum="CharacterBody3D.PlatformOnLeave" default="0"> + Sets the behavior to apply when you leave a moving platform. By default, to be physically accurate, when you leave the last platform velocity is applied. See [enum PlatformOnLeave] constants for available behavior. + </member> + <member name="platform_wall_layers" type="int" setter="set_platform_wall_layers" getter="get_platform_wall_layers" default="0"> Collision layers that will be included for detecting wall bodies that will act as moving platforms to be followed by the [CharacterBody3D]. By default, all wall bodies are ignored. </member> <member name="safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.001"> @@ -184,13 +184,13 @@ <constant name="MOTION_MODE_FLOATING" value="1" enum="MotionMode"> Apply when there is no notion of floor or ceiling. All collisions will be reported as [code]on_wall[/code]. In this mode, when you slide, the speed will always be constant. This mode is suitable for games without ground like space games. </constant> - <constant name="PLATFORM_VEL_ON_LEAVE_ALWAYS" value="0" enum="MovingPlatformApplyVelocityOnLeave"> + <constant name="PLATFORM_ON_LEAVE_ADD_VELOCITY" value="0" enum="PlatformOnLeave"> Add the last platform velocity to the [member velocity] when you leave a moving platform. </constant> - <constant name="PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY" value="1" enum="MovingPlatformApplyVelocityOnLeave"> + <constant name="PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY" value="1" enum="PlatformOnLeave"> Add the last platform velocity to the [member velocity] when you leave a moving platform, but any downward motion is ignored. It's useful to keep full jump height even when the platform is moving down. </constant> - <constant name="PLATFORM_VEL_ON_LEAVE_NEVER" value="2" enum="MovingPlatformApplyVelocityOnLeave"> + <constant name="PLATFORM_ON_LEAVE_DO_NOTHING" value="2" enum="PlatformOnLeave"> Do nothing when leaving a platform. </constant> </constants> diff --git a/doc/classes/ConcavePolygonShape2D.xml b/doc/classes/ConcavePolygonShape2D.xml index 902993e439..ee3e4f6de4 100644 --- a/doc/classes/ConcavePolygonShape2D.xml +++ b/doc/classes/ConcavePolygonShape2D.xml @@ -4,7 +4,7 @@ Concave polygon shape resource for 2D physics. </brief_description> <description> - 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. + 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 [RigidBody2D] 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. [b]Warning:[/b] Using this shape for an [Area2D] (via a [CollisionShape2D] node) may give unexpected results: the area will only detect collisions with the segments in the [ConcavePolygonShape2D] (and not with any "inside" of the shape, for example). diff --git a/doc/classes/ConcavePolygonShape3D.xml b/doc/classes/ConcavePolygonShape3D.xml index d22793e52c..f01ca8efaf 100644 --- a/doc/classes/ConcavePolygonShape3D.xml +++ b/doc/classes/ConcavePolygonShape3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> 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]Note:[/b] When used for collision, [ConcavePolygonShape3D] is intended to work with static [PhysicsBody3D] nodes like [StaticBody3D] and will not work with [CharacterBody3D] or [RigidBody3D] 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. [b]Warning:[/b] Using this shape for an [Area3D] (via a [CollisionShape3D] node, created e.g. by using the [i]Create Trimesh Collision Sibling[/i] option in the [i]Mesh[/i] menu that appears when selecting a [MeshInstance3D] node) may give unexpected results: the area will only detect collisions with the triangle faces in the [ConcavePolygonShape3D] (and not with any "inside" of the shape, for example); moreover it will only detect all such collisions if [member backface_collision] is [code]true[/code]. </description> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index b7a9ae235e..a3cd4d0752 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -1145,6 +1145,7 @@ </signal> <signal name="theme_changed"> <description> + Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent. </description> </signal> </signals> @@ -1174,7 +1175,12 @@ Sent when the node loses focus. </constant> <constant name="NOTIFICATION_THEME_CHANGED" value="45"> - Sent when the node's [member theme] changes, right before Godot redraws the control. Happens when you call one of the [code]add_theme_*_override[/code] methods. + Sent when the node needs to refresh its theme items. This happens in one of the following cases: + - The [member theme] property is changed on this node or any of its ancestors. + - The [member theme_type_variation] property is changed on this node. + - One of the node's theme property overrides is changed. + - The node enters the scene tree. + [b]Note:[/b] As an optimization, this notification won't be sent from changes that occur while this node is outside of the scene tree. Instead, all of the theme item updates can be applied at once when the node enters the scene tree. </constant> <constant name="NOTIFICATION_SCROLL_BEGIN" value="47"> Sent when this node is inside a [ScrollContainer] which has begun being scrolled. diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index bcad75215a..c5f61cdfd3 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1068,6 +1068,13 @@ <description> </description> </method> + <method name="window_get_safe_title_margins" qualifiers="const"> + <return type="Vector2i" /> + <param index="0" name="window_id" type="int" default="0" /> + <description> + Returns left and right margins of the title that are safe to use (contains no buttons or other elements) when [constant WINDOW_FLAG_EXTEND_TO_TITLE] flag is set. + </description> + </method> <method name="window_get_size" qualifiers="const"> <return type="Vector2i" /> <param index="0" name="window_id" type="int" default="0" /> @@ -1081,6 +1088,20 @@ Returns the V-Sync mode of the given window. </description> </method> + <method name="window_maximize_on_title_dbl_click" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code], if double-click on a window title should maximize it. + [b]Note:[/b] This method is implemented on macOS. + </description> + </method> + <method name="window_minimize_on_title_dbl_click" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code], if double-click on a window title should minimize it. + [b]Note:[/b] This method is implemented on macOS. + </description> + </method> <method name="window_move_to_foreground"> <return type="void" /> <param index="0" name="window_id" type="int" default="0" /> @@ -1316,6 +1337,9 @@ <constant name="FEATURE_TEXT_TO_SPEECH" value="19" enum="Feature"> Display server supports text-to-speech. See [code]tts_*[/code] methods. </constant> + <constant name="FEATURE_EXTEND_TO_TITLE" value="20" enum="Feature"> + Display server supports expanding window content to the title. See [constant WINDOW_FLAG_EXTEND_TO_TITLE]. + </constant> <constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode"> Makes the mouse cursor visible if it is hidden. </constant> @@ -1446,7 +1470,11 @@ <constant name="WINDOW_FLAG_POPUP" value="5" enum="WindowFlags"> Window is part of menu or [OptionButton] dropdown. This flag can't be changed when window is visible. An active popup window will exclusively receive all input, without stealing focus from its parent. Popup windows are automatically closed when uses click outside it, or when an application is switched. Popup window must have [constant WINDOW_FLAG_TRANSPARENT] set. </constant> - <constant name="WINDOW_FLAG_MAX" value="6" enum="WindowFlags"> + <constant name="WINDOW_FLAG_EXTEND_TO_TITLE" value="6" enum="WindowFlags"> + Window content is expanded to the full size of the window. Unlike borderless window, the frame is left intact and can be used to resize the window, title bar is transparent, but have minimize/maximize/close buttons. + [b]Note:[/b] This flag is implemented on macOS. + </constant> + <constant name="WINDOW_FLAG_MAX" value="7" enum="WindowFlags"> </constant> <constant name="WINDOW_EVENT_MOUSE_ENTER" value="0" enum="WindowEvent"> </constant> @@ -1483,13 +1511,13 @@ Window handle: - Windows: [code]HWND[/code] for the window. - Linux: [code]X11::Window*[/code] for the window. - - MacOS: [code]NSWindow*[/code] for the window. + - macOS: [code]NSWindow*[/code] for the window. - iOS: [code]UIViewController*[/code] for the view controller. - Android: [code]jObject[/code] for the activity. </constant> <constant name="WINDOW_VIEW" value="2" enum="HandleType"> Window view: - - MacOS: [code]NSView*[/code] for the window main view. + - macOS: [code]NSView*[/code] for the window main view. - iOS: [code]UIView*[/code] for the window main view. </constant> <constant name="TTS_UTTERANCE_STARTED" value="0" enum="TTSUtteranceEvent"> diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 4a6a0e7226..67204f2a15 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -44,12 +44,6 @@ Gets the edited property. If your editor is for a single property (added via [method EditorInspectorPlugin._parse_property]), then this will return the property. </description> </method> - <method name="get_tooltip_text" qualifiers="const"> - <return type="String" /> - <description> - Must be implemented to provide a custom tooltip to the property editor. - </description> - </method> <method name="set_bottom_editor"> <return type="void" /> <param index="0" name="editor" type="Control" /> diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index c7ff0a2d59..56c1f6e55a 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -465,15 +465,15 @@ </member> <member name="interface/editor/code_font_contextual_ligatures" type="int" setter="" getter=""> The font ligatures to enable for the currently configured code font. Not all fonts include support for ligatures. - [b]Note:[/b] The default editor code font (Hack) does not have contextual ligatures in its font file. + [b]Note:[/b] The default editor code font ([url=https://www.jetbrains.com/lp/mono/]JetBrains Mono[/url]) has contextual ligatures in its font file. </member> <member name="interface/editor/code_font_custom_opentype_features" type="String" setter="" getter=""> List of custom OpenType features to use, if supported by the currently configured code font. Not all fonts include support for custom OpenType features. The string should follow the OpenType specification. - [b]Note:[/b] The default editor code font (Hack) does not have custom OpenType features in its font file. + [b]Note:[/b] The default editor code font ([url=https://www.jetbrains.com/lp/mono/]JetBrains Mono[/url]) has custom OpenType features in its font file, but there is no documented list yet. </member> <member name="interface/editor/code_font_custom_variations" type="String" setter="" getter=""> List of alternative characters to use, if supported by the currently configured code font. Not all fonts include support for custom variations. The string should follow the OpenType specification. - [b]Note:[/b] The default editor code font (Hack) does not have alternate characters in its font file. + [b]Note:[/b] The default editor code font ([url=https://www.jetbrains.com/lp/mono/]JetBrains Mono[/url]) has alternate characters in its font file, but there is no documented list yet. </member> <member name="interface/editor/code_font_size" type="int" setter="" getter=""> The size of the font in the script editor. This setting does not impact the font size of the Output panel (see [member run/output/font_size]). @@ -495,8 +495,12 @@ The language to use for the editor interface. Translations are provided by the community. If you spot a mistake, [url=https://docs.godotengine.org/en/latest/community/contributing/editor_and_docs_localization.html]contribute to editor translations on Weblate![/url] </member> - <member name="interface/editor/font_antialiased" type="bool" setter="" getter=""> - If [code]true[/code], enables FreeType's font antialiasing on the editor fonts. Most fonts are not designed to look good with antialiasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font. + <member name="interface/editor/expand_to_title" type="bool" setter="" getter=""> + Expanding main editor window content to the title, if supported by [DisplayServer]. See [constant DisplayServer.WINDOW_FLAG_EXTEND_TO_TITLE]. + Specific to the macOS platform. + </member> + <member name="interface/editor/font_antialiasing" type="int" setter="" getter=""> + FreeType's font anti-aliasing mode used to render the editor fonts. Most fonts are not designed to look good with anti-aliasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font. </member> <member name="interface/editor/font_hinting" type="int" setter="" getter=""> The font hinting mode to use for the editor fonts. FreeType supports the following font hinting modes: diff --git a/doc/classes/FontFile.xml b/doc/classes/FontFile.xml index b9b20dc75b..df378d9d2f 100644 --- a/doc/classes/FontFile.xml +++ b/doc/classes/FontFile.xml @@ -543,8 +543,8 @@ </method> </methods> <members> - <member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true"> - If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled. + <member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1"> + Font anti-aliasing mode. </member> <member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()"> Contents of the dynamic font source file. diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 606d2456c5..f41e34c43a 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -5,7 +5,7 @@ </brief_description> <description> 2D particle node used to create a variety of particle systems and effects. [GPUParticles2D] features an emitter that generates some number of particles at a given rate. - Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. + Use the [code]process_material[/code] property to add a [ParticleProcessMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. </description> <tutorials> <link title="Particle systems (2D)">$DOCS_URL/tutorials/2d/particle_systems_2d.html</link> @@ -73,7 +73,7 @@ Particle system starts as if it had already run for this many seconds. </member> <member name="process_material" type="Material" setter="set_process_material" getter="get_process_material"> - [Material] for processing particles. Can be a [ParticlesMaterial] or a [ShaderMaterial]. + [Material] for processing particles. Can be a [ParticleProcessMaterial] or a [ShaderMaterial]. </member> <member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio" default="0.0"> Emission lifetime randomness ratio. diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index fc7b12e64f..e7b436010e 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> 3D particle node used to create a variety of particle systems and effects. [GPUParticles3D] features an emitter that generates some number of particles at a given rate. - Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. + Use the [code]process_material[/code] property to add a [ParticleProcessMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. </description> <tutorials> <link title="Controlling thousands of fish with Particles">$DOCS_URL/tutorials/performance/vertex_animation/controlling_thousands_of_fish.html</link> @@ -105,7 +105,7 @@ Amount of time to preprocess the particles before animation starts. Lets you start the animation some time after particles have started emitting. </member> <member name="process_material" type="Material" setter="set_process_material" getter="get_process_material"> - [Material] for processing particles. Can be a [ParticlesMaterial] or a [ShaderMaterial]. + [Material] for processing particles. Can be a [ParticleProcessMaterial] or a [ShaderMaterial]. </member> <member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio" default="0.0"> Emission randomness ratio. diff --git a/doc/classes/GPUParticlesAttractor3D.xml b/doc/classes/GPUParticlesAttractor3D.xml index e69255cc31..a1c49afcca 100644 --- a/doc/classes/GPUParticlesAttractor3D.xml +++ b/doc/classes/GPUParticlesAttractor3D.xml @@ -18,7 +18,7 @@ <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="4294967295"> The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the attractor. By default, all particles are affected by an attractor. After configuring particle nodes accordingly, specific layers can be unchecked to prevent certain particles from being affected by attractors. For example, this can be used if you're using an attractor as part of a spell effect but don't want the attractor to affect unrelated weather particles at the same position. - Particle attraction can also be disabled on a per-process material basis by setting [member ParticlesMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. + Particle attraction can also be disabled on a per-process material basis by setting [member ParticleProcessMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. </member> <member name="directionality" type="float" setter="set_directionality" getter="get_directionality" default="0.0"> Adjusts how directional the attractor is. At [code]0.0[/code], the attractor is not directional at all: it will attract particles towards its center. At [code]1.0[/code], the attractor is fully directional: particles will always be pushed towards local -Z (or +Z if [member strength] is negative). diff --git a/doc/classes/GPUParticlesCollision3D.xml b/doc/classes/GPUParticlesCollision3D.xml index 435f9781f0..1b744f7ed6 100644 --- a/doc/classes/GPUParticlesCollision3D.xml +++ b/doc/classes/GPUParticlesCollision3D.xml @@ -7,7 +7,7 @@ Particle collision shapes can be used to make particles stop or bounce against them. Particle collision shapes in real-time and can be moved, rotated and scaled during gameplay. Unlike attractors, non-uniform scaling of collision shapes is [i]not[/i] supported. Particle collision shapes can be temporarily disabled by hiding them. - [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. [b]Note:[/b] Particles pushed by a collider that is being moved will not be interpolated, which can result in visible stuttering. This can be alleviated by setting [member GPUParticles3D.fixed_fps] to [code]0[/code] or a value that matches or exceeds the target framerate. </description> @@ -15,9 +15,9 @@ </tutorials> <members> <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="4294967295"> - The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the collision shape. By default, all particles that have [member ParticlesMaterial.collision_enabled] set to [code]true[/code] will be affected by a collision shape. + The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the collision shape. By default, all particles that have [member ParticleProcessMaterial.collision_mode] set to [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] will be affected by a collision shape. After configuring particle nodes accordingly, specific layers can be unchecked to prevent certain particles from being affected by attractors. For example, this can be used if you're using an attractor as part of a spell effect but don't want the attractor to affect unrelated weather particles at the same position. - Particle attraction can also be disabled on a per-process material basis by setting [member ParticlesMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. + Particle attraction can also be disabled on a per-process material basis by setting [member ParticleProcessMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. </member> </members> </class> diff --git a/doc/classes/GPUParticlesCollisionBox3D.xml b/doc/classes/GPUParticlesCollisionBox3D.xml index 60d66ca682..103be18bfd 100644 --- a/doc/classes/GPUParticlesCollisionBox3D.xml +++ b/doc/classes/GPUParticlesCollisionBox3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> Box-shaped 3D particle collision shape affecting [GPUParticles3D] nodes. - [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> diff --git a/doc/classes/GPUParticlesCollisionHeightField3D.xml b/doc/classes/GPUParticlesCollisionHeightField3D.xml index 3fcad43efb..6e996d5fbd 100644 --- a/doc/classes/GPUParticlesCollisionHeightField3D.xml +++ b/doc/classes/GPUParticlesCollisionHeightField3D.xml @@ -7,7 +7,7 @@ Real-time heightmap-shaped 3D particle attractor affecting [GPUParticles3D] nodes. Heightmap shapes allow for efficiently representing collisions for convex and concave objects with a single "floor" (such as terrain). This is less flexible than [GPUParticlesCollisionSDF3D], but it doesn't require a baking step. [GPUParticlesCollisionHeightField3D] can also be regenerated in real-time when it is moved, when the camera moves, or even continuously. This makes [GPUParticlesCollisionHeightField3D] a good choice for weather effects such as rain and snow and games with highly dynamic geometry. However, since heightmaps cannot represent overhangs, [GPUParticlesCollisionHeightField3D] is not suited for indoor particle collision. - [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> diff --git a/doc/classes/GPUParticlesCollisionSDF3D.xml b/doc/classes/GPUParticlesCollisionSDF3D.xml index 29adf4fbc1..8467cfdda1 100644 --- a/doc/classes/GPUParticlesCollisionSDF3D.xml +++ b/doc/classes/GPUParticlesCollisionSDF3D.xml @@ -8,7 +8,7 @@ Signed distance fields (SDF) allow for efficiently representing approximate collision shapes for convex and concave objects of any shape. This is more flexible than [GPUParticlesCollisionHeightField3D], but it requires a baking step. [b]Baking:[/b] The signed distance field texture can be baked by selecting the [GPUParticlesCollisionSDF3D] node in the editor, then clicking [b]Bake SDF[/b] at the top of the 3D viewport. Any [i]visible[/i] [MeshInstance3D]s touching the [member extents] will be taken into account for baking, regardless of their [member GeometryInstance3D.gi_mode]. [b]Note:[/b] Baking a [GPUParticlesCollisionSDF3D]'s [member texture] is only possible within the editor, as there is no bake method exposed for use in exported projects. However, it's still possible to load pre-baked [Texture3D]s into its [member texture] property in an exported project. - [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> diff --git a/doc/classes/GPUParticlesCollisionSphere3D.xml b/doc/classes/GPUParticlesCollisionSphere3D.xml index 6651a732da..ee582108dd 100644 --- a/doc/classes/GPUParticlesCollisionSphere3D.xml +++ b/doc/classes/GPUParticlesCollisionSphere3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> Sphere-shaped 3D particle collision shape affecting [GPUParticles3D] nodes. - [b]Note:[/b] [member ParticlesMaterial.collision_enabled] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 52b2e9a729..0c4c4a5b09 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -61,10 +61,6 @@ Limits the lines of text the node shows on screen. </member> <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" overrides="Control" enum="Control.MouseFilter" default="2" /> - <member name="percent_visible" type="float" setter="set_percent_visible" getter="get_percent_visible" default="1.0"> - The fraction of characters to display, relative to the total number of characters (see [method get_total_character_count]). If set to [code]1.0[/code], all characters are displayed. If set to [code]0.5[/code], only half of the characters will be displayed. This can be useful when animating the text appearing in a dialog box. - [b]Note:[/b] Setting this property updates [member visible_characters] accordingly. - </member> <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="4" /> <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. @@ -89,10 +85,14 @@ </member> <member name="visible_characters" type="int" setter="set_visible_characters" getter="get_visible_characters" default="-1"> The number of characters to display. If set to [code]-1[/code], all characters are displayed. This can be useful when animating the text appearing in a dialog box. - [b]Note:[/b] Setting this property updates [member percent_visible] accordingly. + [b]Note:[/b] Setting this property updates [member visible_ratio] accordingly. </member> <member name="visible_characters_behavior" type="int" setter="set_visible_characters_behavior" getter="get_visible_characters_behavior" enum="TextServer.VisibleCharactersBehavior" default="0"> - Sets the clipping behavior when [member visible_characters] or [member percent_visible] is set. See [enum TextServer.VisibleCharactersBehavior] for more info. + Sets the clipping behavior when [member visible_characters] or [member visible_ratio] is set. See [enum TextServer.VisibleCharactersBehavior] for more info. + </member> + <member name="visible_ratio" type="float" setter="set_visible_ratio" getter="get_visible_ratio" default="1.0"> + The fraction of characters to display, relative to the total number of characters (see [method get_total_character_count]). If set to [code]1.0[/code], all characters are displayed. If set to [code]0.5[/code], only half of the characters will be displayed. This can be useful when animating the text appearing in a dialog box. + [b]Note:[/b] Setting this property updates [member visible_characters] accordingly. </member> </members> <theme_items> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 20703f680c..5ca2a22749 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -65,7 +65,7 @@ </description> </method> <method name="get_scroll_offset" qualifiers="const"> - <return type="int" /> + <return type="float" /> <description> Returns the scroll offset due to [member caret_column], as a number of characters. </description> diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml index 30ad13ec93..bf3aff2c58 100644 --- a/doc/classes/NavigationAgent2D.xml +++ b/doc/classes/NavigationAgent2D.xml @@ -126,7 +126,7 @@ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1"> A bitfield determining what navigation layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new navigation layers. </member> - <member name="neighbor_dist" type="float" setter="set_neighbor_dist" getter="get_neighbor_dist" default="500.0"> + <member name="neighbor_distance" type="float" setter="set_neighbor_distance" getter="get_neighbor_distance" default="500.0"> The distance to search for other agents. </member> <member name="path_desired_distance" type="float" setter="set_path_desired_distance" getter="get_path_desired_distance" default="1.0"> @@ -136,7 +136,7 @@ The maximum distance the agent is allowed away from the ideal path to the final location. This can happen due to trying to avoid collisions. When the maximum distance is exceeded, it recalculates the ideal path. </member> <member name="radius" type="float" setter="set_radius" getter="get_radius" default="10.0"> - The radius of the avoidance agent. This is the "body" of the avoidance agent and not the avoidance maneuver starting radius (which is controlled by [member neighbor_dist]). + The radius of the avoidance agent. This is the "body" of the avoidance agent and not the avoidance maneuver starting radius (which is controlled by [member neighbor_distance]). Does not affect normal pathfinding. To change an actor's pathfinding radius bake [NavigationMesh] resources with a different [member NavigationMesh.agent_radius] property and use different navigation maps for each actor size. </member> <member name="target_desired_distance" type="float" setter="set_target_desired_distance" getter="get_target_desired_distance" default="1.0"> diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml index 22c468cb6b..7c48f0b52b 100644 --- a/doc/classes/NavigationAgent3D.xml +++ b/doc/classes/NavigationAgent3D.xml @@ -132,7 +132,7 @@ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1"> A bitfield determining what navigation layers of navigation regions this NavigationAgent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new navigation layers. </member> - <member name="neighbor_dist" type="float" setter="set_neighbor_dist" getter="get_neighbor_dist" default="50.0"> + <member name="neighbor_distance" type="float" setter="set_neighbor_distance" getter="get_neighbor_distance" default="50.0"> The distance to search for other agents. </member> <member name="path_desired_distance" type="float" setter="set_path_desired_distance" getter="get_path_desired_distance" default="1.0"> @@ -142,7 +142,7 @@ The maximum distance the agent is allowed away from the ideal path to the final location. This can happen due to trying to avoid collisions. When the maximum distance is exceeded, it recalculates the ideal path. </member> <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> - The radius of the avoidance agent. This is the "body" of the avoidance agent and not the avoidance maneuver starting radius (which is controlled by [member neighbor_dist]). + The radius of the avoidance agent. This is the "body" of the avoidance agent and not the avoidance maneuver starting radius (which is controlled by [member neighbor_distance]). Does not affect normal pathfinding. To change an actor's pathfinding radius bake [NavigationMesh] resources with a different [member NavigationMesh.agent_radius] property and use different navigation maps for each actor size. </member> <member name="target_desired_distance" type="float" setter="set_target_desired_distance" getter="get_target_desired_distance" default="1.0"> diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index 2067a237dc..b85c1c6649 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -72,10 +72,10 @@ Sets the maximum speed of the agent. Must be positive. </description> </method> - <method name="agent_set_neighbor_dist" qualifiers="const"> + <method name="agent_set_neighbor_distance" qualifiers="const"> <return type="void" /> <param index="0" name="agent" type="RID" /> - <param index="1" name="dist" type="float" /> + <param index="1" name="distance" type="float" /> <description> Sets the maximum distance to other agents this agent takes into account in the navigation. The larger this number, the longer the running time of the simulation. If the number is too low, the simulation will not be safe. </description> diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 92da5cca21..5b2a8fc08b 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -72,10 +72,10 @@ Sets the maximum speed of the agent. Must be positive. </description> </method> - <method name="agent_set_neighbor_dist" qualifiers="const"> + <method name="agent_set_neighbor_distance" qualifiers="const"> <return type="void" /> <param index="0" name="agent" type="RID" /> - <param index="1" name="dist" type="float" /> + <param index="1" name="distance" type="float" /> <description> Sets the maximum distance to other agents this agent takes into account in the navigation. The larger this number, the longer the running time of the simulation. If the number is too low, the simulation will not be safe. </description> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 429a9abf51..b882425960 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -241,7 +241,7 @@ <description> Returns a child node by its index (see [method get_child_count]). This method is often used for iterating all children of a node. Negative indices access the children from the last one. - If [param include_internal] is [code]true[/code], internal children are skipped (see [code]internal[/code] parameter in [method add_child]). + If [param include_internal] is [code]false[/code], internal children are skipped (see [code]internal[/code] parameter in [method add_child]). To access a child node via its name, use [method get_node]. </description> </method> diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml index 53b93beb40..c8e2f1ac68 100644 --- a/doc/classes/Node3D.xml +++ b/doc/classes/Node3D.xml @@ -6,7 +6,7 @@ <description> Most basic 3D game object, with a 3D [Transform3D] and visibility settings. All other 3D game objects inherit from Node3D. Use [Node3D] as a parent node to move, scale, rotate and show/hide children in a 3D project. Affine operations (rotate, scale, translate) happen in parent's local coordinate system, unless the [Node3D] object is set as top-level. Affine operations in this coordinate system correspond to direct affine operations on the [Node3D]'s transform. The word local below refers to this coordinate system. The coordinate system that is attached to the [Node3D] object itself is referred to as object-local coordinate system. - [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg2rad]. + [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg_to_rad]. </description> <tutorials> <link title="Introduction to 3D">$DOCS_URL/tutorials/3d/introduction_to_3d.html</link> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index e4b5404c2c..e180c73733 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -88,14 +88,6 @@ [b]Note:[/b] When [method delay_usec] is called on the main thread, it will freeze the project and will prevent it from redrawing and registering input until the delay has passed. When using [method delay_usec] as part of an [EditorPlugin] or [EditorScript], it will freeze the editor but won't freeze the project if it is currently running (since the project is an independent child process). </description> </method> - <method name="dump_memory_to_file"> - <return type="void" /> - <param index="0" name="file" type="String" /> - <description> - Dumps the memory allocation ringlist to a file (only works in debug). - Entry format per line: "Address - Size - Description". - </description> - </method> <method name="dump_resources_to_file"> <return type="void" /> <param index="0" name="file" type="String" /> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index c7fe7d8c37..754d3ac73d 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -22,12 +22,12 @@ AddChild(scene); [/csharp] [/codeblocks] - [b]Example of saving a node with different owners:[/b] The following example creates 3 objects: [Node2D] ([code]node[/code]), [RigidDynamicBody2D] ([code]body[/code]) and [CollisionObject2D] ([code]collision[/code]). [code]collision[/code] is a child of [code]body[/code] which is a child of [code]node[/code]. Only [code]body[/code] is owned by [code]node[/code] and [code]pack[/code] will therefore only save those two nodes, but not [code]collision[/code]. + [b]Example of saving a node with different owners:[/b] The following example creates 3 objects: [Node2D] ([code]node[/code]), [RigidBody2D] ([code]body[/code]) and [CollisionObject2D] ([code]collision[/code]). [code]collision[/code] is a child of [code]body[/code] which is a child of [code]node[/code]. Only [code]body[/code] is owned by [code]node[/code] and [code]pack[/code] will therefore only save those two nodes, but not [code]collision[/code]. [codeblocks] [gdscript] # Create the objects. var node = Node2D.new() - var body = RigidDynamicBody2D.new() + var body = RigidBody2D.new() var collision = CollisionShape2D.new() # Create the object hierarchy. @@ -48,7 +48,7 @@ [csharp] // Create the objects. var node = new Node2D(); - var body = new RigidDynamicBody2D(); + var body = new RigidBody2D(); var collision = new CollisionShape2D(); // Create the object hierarchy. diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticleProcessMaterial.xml index fe4caaa10c..1526658eed 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticleProcessMaterial.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ParticlesMaterial" inherits="Material" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="ParticleProcessMaterial" inherits="Material" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Particle properties for [GPUParticles3D] and [GPUParticles2D] nodes. </brief_description> <description> - ParticlesMaterial defines particle properties and behavior. It is used in the [code]process_material[/code] of [GPUParticles3D] and [GPUParticles2D] emitter nodes. + ParticleProcessMaterial defines particle properties and behavior. It is used in the [code]process_material[/code] of [GPUParticles3D] and [GPUParticles2D] emitter nodes. Some of this material's properties are applied to each particle when emitted, while others can have a [CurveTexture] applied to vary values over the lifetime of the particle. Particle animation is available only in [GPUParticles2D]. To use it, attach a [CanvasItemMaterial], with [member CanvasItemMaterial.particles_animation] enabled, to the particles node. </description> @@ -13,35 +13,35 @@ <methods> <method name="get_param_max" qualifiers="const"> <return type="float" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <description> Returns the maximum value range for the given parameter. </description> </method> <method name="get_param_min" qualifiers="const"> <return type="float" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <description> Returns the minimum value range for the given parameter. </description> </method> <method name="get_param_texture" qualifiers="const"> <return type="Texture2D" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <description> Returns the [Texture2D] used by the specified parameter. </description> </method> <method name="get_particle_flag" qualifiers="const"> <return type="bool" /> - <param index="0" name="particle_flag" type="int" enum="ParticlesMaterial.ParticleFlags" /> + <param index="0" name="particle_flag" type="int" enum="ParticleProcessMaterial.ParticleFlags" /> <description> Returns [code]true[/code] if the specified particle flag is enabled. See [enum ParticleFlags] for options. </description> </method> <method name="set_param_max"> <return type="void" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <param index="1" name="value" type="float" /> <description> Sets the maximum value range for the given parameter. @@ -49,7 +49,7 @@ </method> <method name="set_param_min"> <return type="void" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <param index="1" name="value" type="float" /> <description> Sets the minimum value range for the given parameter. @@ -57,7 +57,7 @@ </method> <method name="set_param_texture"> <return type="void" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <param index="1" name="texture" type="Texture2D" /> <description> Sets the [Texture2D] for the specified [enum Parameter]. @@ -65,7 +65,7 @@ </method> <method name="set_particle_flag"> <return type="void" /> - <param index="0" name="particle_flag" type="int" enum="ParticlesMaterial.ParticleFlags" /> + <param index="0" name="particle_flag" type="int" enum="ParticleProcessMaterial.ParticleFlags" /> <param index="1" name="enable" type="bool" /> <description> If [code]true[/code], enables the specified particle flag. See [enum ParticleFlags] for options. @@ -115,14 +115,15 @@ <member name="attractor_interaction_enabled" type="bool" setter="set_attractor_interaction_enabled" getter="is_attractor_interaction_enabled" default="true"> True if the interaction with particle attractors is enabled. </member> - <member name="collision_bounce" type="float" setter="set_collision_bounce" getter="get_collision_bounce" default="0.0"> - Collision bounciness. + <member name="collision_bounce" type="float" setter="set_collision_bounce" getter="get_collision_bounce"> + The particles' bounciness. Values range from [code]0[/code] (no bounce) to [code]1[/code] (full bounciness). Only effective if [member collision_mode] is [constant COLLISION_RIGID]. </member> - <member name="collision_enabled" type="bool" setter="set_collision_enabled" getter="is_collision_enabled" default="false"> - True if collisions are enabled for this particle system. + <member name="collision_friction" type="float" setter="set_collision_friction" getter="get_collision_friction"> + The particles' friction. Values range from [code]0[/code] (frictionless) to [code]1[/code] (maximum friction). Only effective if [member collision_mode] is [constant COLLISION_RIGID]. </member> - <member name="collision_friction" type="float" setter="set_collision_friction" getter="get_collision_friction" default="0.0"> - Collision friction. + <member name="collision_mode" type="int" setter="set_collision_mode" getter="get_collision_mode" enum="ParticleProcessMaterial.CollisionMode" default="0"> + The particles' collision mode. + [b]Note:[/b] Particles can only collide with [GPUParticlesCollision3D] nodes, not [PhysicsBody3D] nodes. To make particles collide with various objects, you can add [GPUParticlesCollision3D] nodes as children of [PhysicsBody3D] nodes. </member> <member name="collision_use_scale" type="bool" setter="set_collision_use_scale" getter="is_collision_using_scale" default="false"> Should collision take scale into account. @@ -175,7 +176,7 @@ <member name="emission_ring_radius" type="float" setter="set_emission_ring_radius" getter="get_emission_ring_radius"> The radius of the ring when using the emitter [constant EMISSION_SHAPE_RING]. </member> - <member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="ParticlesMaterial.EmissionShape" default="0"> + <member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="ParticleProcessMaterial.EmissionShape" default="0"> Particles will be emitted inside this region. Use [enum EmissionShape] constants for values. </member> <member name="emission_sphere_radius" type="float" setter="set_emission_sphere_radius" getter="get_emission_sphere_radius"> @@ -260,7 +261,7 @@ </member> <member name="sub_emitter_keep_velocity" type="bool" setter="set_sub_emitter_keep_velocity" getter="get_sub_emitter_keep_velocity" default="false"> </member> - <member name="sub_emitter_mode" type="int" setter="set_sub_emitter_mode" getter="get_sub_emitter_mode" enum="ParticlesMaterial.SubEmitterMode" default="0"> + <member name="sub_emitter_mode" type="int" setter="set_sub_emitter_mode" getter="get_sub_emitter_mode" enum="ParticleProcessMaterial.SubEmitterMode" default="0"> </member> <member name="tangential_accel_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> Each particle's tangential acceleration will vary along this [CurveTexture]. @@ -404,5 +405,17 @@ <constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode"> Represents the size of the [enum SubEmitterMode] enum. </constant> + <constant name="COLLISION_DISABLED" value="0" enum="CollisionMode"> + No collision for particles. Particles will go through [GPUParticlesCollision3D] nodes. + </constant> + <constant name="COLLISION_RIGID" value="1" enum="CollisionMode"> + [RigidBody3D]-style collision for particles using [GPUParticlesCollision3D] nodes. + </constant> + <constant name="COLLISION_HIDE_ON_CONTACT" value="2" enum="CollisionMode"> + Hide particles instantly when colliding with a [GPUParticlesCollision3D] node. This can be combined with a subemitter that uses the [constant COLLISION_RIGID] collision mode to "replace" the parent particle with the subemitter on impact. + </constant> + <constant name="COLLISION_MAX" value="3" enum="CollisionMode"> + Represents the size of the [enum CollisionMode] enum. + </constant> </constants> </class> diff --git a/doc/classes/PathFollow2D.xml b/doc/classes/PathFollow2D.xml index ae4a4b2886..09d6872e10 100644 --- a/doc/classes/PathFollow2D.xml +++ b/doc/classes/PathFollow2D.xml @@ -5,7 +5,7 @@ </brief_description> <description> This node takes its parent [Path2D], and returns the coordinates of a point within it, given a distance from the first vertex. - It is useful for making other nodes follow a path, without coding the movement pattern. For that, the nodes must be children of this node. The descendant nodes will then move accordingly when setting an offset in this node. + It is useful for making other nodes follow a path, without coding the movement pattern. For that, the nodes must be children of this node. The descendant nodes will then move accordingly when setting the [member progress] in this node. </description> <tutorials> </tutorials> @@ -24,15 +24,15 @@ <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="true"> If [code]true[/code], any offset outside the path's length will wrap around, instead of stopping at the ends. Use it for cyclic paths. </member> - <member name="offset" type="float" setter="set_offset" getter="get_offset" default="0.0"> - The distance along the path in pixels. + <member name="progress" type="float" setter="set_progress" getter="get_progress" default="0.0"> + The distance along the path, in pixels. Changing this value sets this node's position to a point within the path. + </member> + <member name="progress_ratio" type="float" setter="set_progress_ratio" getter="get_progress_ratio" default="0.0"> + The distance along the path as a number in the range 0.0 (for the first vertex) to 1.0 (for the last). This is just another way of expressing the progress within the path, as the offset supplied is multiplied internally by the path's length. </member> <member name="rotates" type="bool" setter="set_rotates" getter="is_rotating" default="true"> If [code]true[/code], this node rotates to follow the path, with the +X direction facing forward on the path. </member> - <member name="unit_offset" type="float" setter="set_unit_offset" getter="get_unit_offset" default="0.0"> - The distance along the path as a number in the range 0.0 (for the first vertex) to 1.0 (for the last). This is just another way of expressing the offset within the path, as the offset supplied is multiplied internally by the path's length. - </member> <member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0"> The node's offset perpendicular to the curve. </member> diff --git a/doc/classes/PathFollow3D.xml b/doc/classes/PathFollow3D.xml index f9fab07be5..ba7207be8f 100644 --- a/doc/classes/PathFollow3D.xml +++ b/doc/classes/PathFollow3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> This node takes its parent [Path3D], and returns the coordinates of a point within it, given a distance from the first vertex. - It is useful for making other nodes follow a path, without coding the movement pattern. For that, the nodes must be children of this node. The descendant nodes will then move accordingly when setting an offset in this node. + It is useful for making other nodes follow a path, without coding the movement pattern. For that, the nodes must be children of this node. The descendant nodes will then move accordingly when setting the [member progress] in this node. </description> <tutorials> </tutorials> @@ -21,15 +21,15 @@ <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="true"> If [code]true[/code], any offset outside the path's length will wrap around, instead of stopping at the ends. Use it for cyclic paths. </member> - <member name="offset" type="float" setter="set_offset" getter="get_offset" default="0.0"> - The distance from the first vertex, measured in 3D units along the path. This sets this node's position to a point within the path. + <member name="progress" type="float" setter="set_progress" getter="get_progress" default="0.0"> + The distance from the first vertex, measured in 3D units along the path. Changing this value sets this node's position to a point within the path. + </member> + <member name="progress_ratio" type="float" setter="set_progress_ratio" getter="get_progress_ratio" default="0.0"> + The distance from the first vertex, considering 0.0 as the first vertex and 1.0 as the last. This is just another way of expressing the progress within the path, as the progress supplied is multiplied internally by the path's length. </member> <member name="rotation_mode" type="int" setter="set_rotation_mode" getter="get_rotation_mode" enum="PathFollow3D.RotationMode" default="3"> Allows or forbids rotation on one or more axes, depending on the [enum RotationMode] constants being used. </member> - <member name="unit_offset" type="float" setter="set_unit_offset" getter="get_unit_offset" default="0.0"> - The distance from the first vertex, considering 0.0 as the first vertex and 1.0 as the last. This is just another way of expressing the offset within the path, as the offset supplied is multiplied internally by the path's length. - </member> <member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0"> The node's offset perpendicular to the curve. </member> diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml index 92fa1040af..381fa3e9ef 100644 --- a/doc/classes/Performance.xml +++ b/doc/classes/Performance.xml @@ -171,7 +171,7 @@ The amount of render buffer memory used (in bytes). [i]Lower is better.[/i] </constant> <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="16" enum="Monitor"> - Number of active [RigidDynamicBody2D] nodes in the game. [i]Lower is better.[/i] + Number of active [RigidBody2D] nodes in the game. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_2D_COLLISION_PAIRS" value="17" enum="Monitor"> Number of collision pairs in the 2D physics engine. [i]Lower is better.[/i] @@ -180,7 +180,7 @@ Number of islands in the 2D physics engine. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="19" enum="Monitor"> - Number of active [RigidDynamicBody3D] and [VehicleBody3D] nodes in the game. [i]Lower is better.[/i] + Number of active [RigidBody3D] and [VehicleBody3D] nodes in the game. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_3D_COLLISION_PAIRS" value="20" enum="Monitor"> Number of collision pairs in the 3D physics engine. [i]Lower is better.[/i] diff --git a/doc/classes/PhysicalBone2D.xml b/doc/classes/PhysicalBone2D.xml index 738568ed03..26fce1a90b 100644 --- a/doc/classes/PhysicalBone2D.xml +++ b/doc/classes/PhysicalBone2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicalBone2D" inherits="RigidDynamicBody2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="PhysicalBone2D" inherits="RigidBody2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> A 2D node that can be used for physically aware bones in 2D. </brief_description> <description> - The [code]PhysicalBone2D[/code] node is a [RigidDynamicBody2D]-based node that can be used to make [Bone2D] nodes in a [Skeleton2D] react to physics. This node is very similar to the [PhysicalBone3D] node, just for 2D instead of 3D. + The [code]PhysicalBone2D[/code] node is a [RigidBody2D]-based node that can be used to make [Bone2D] nodes in a [Skeleton2D] react to physics. This node is very similar to the [PhysicalBone3D] node, just for 2D instead of 3D. [b]Note:[/b] To have the Bone2D nodes visually follow the [code]PhysicalBone2D[/code] node, use a [SkeletonModification2DPhysicalBones] modification on the [Skeleton2D] node with the [Bone2D] nodes. [b]Note:[/b] The PhysicalBone2D node does not automatically create a [Joint2D] node to keep [code]PhysicalBone2D[/code] nodes together. You will need to create these manually. For most cases, you want to use a [PinJoint2D] node. The [code]PhysicalBone2D[/code] node can automatically configure the [Joint2D] node once it's been created as a child node. </description> diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml index 93c9f83ff2..fdc3a44e9d 100644 --- a/doc/classes/PhysicsDirectBodyState2D.xml +++ b/doc/classes/PhysicsDirectBodyState2D.xml @@ -4,7 +4,7 @@ Direct access object to a physics body in the [PhysicsServer2D]. </brief_description> <description> - Provides direct access to a physics body in the [PhysicsServer2D], allowing safe changes to physics properties. This object is passed via the direct state callback of dynamic bodies, and is intended for changing the direct state of that body. See [method RigidDynamicBody2D._integrate_forces]. + Provides direct access to a physics body in the [PhysicsServer2D], allowing safe changes to physics properties. This object is passed via the direct state callback of rigid bodies, and is intended for changing the direct state of that body. See [method RigidBody2D._integrate_forces]. </description> <tutorials> <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> @@ -146,7 +146,7 @@ <return type="int" /> <description> Returns the number of contacts this body has with other bodies. - [b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidDynamicBody2D.contact_monitor]. + [b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidBody2D.contact_monitor]. </description> </method> <method name="get_contact_local_normal" qualifiers="const"> diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml index 62eb9f6ac4..efe63e4093 100644 --- a/doc/classes/PhysicsDirectBodyState3D.xml +++ b/doc/classes/PhysicsDirectBodyState3D.xml @@ -4,7 +4,7 @@ Direct access object to a physics body in the [PhysicsServer3D]. </brief_description> <description> - Provides direct access to a physics body in the [PhysicsServer3D], allowing safe changes to physics properties. This object is passed via the direct state callback of dynamic bodies, and is intended for changing the direct state of that body. See [method RigidDynamicBody3D._integrate_forces]. + Provides direct access to a physics body in the [PhysicsServer3D], allowing safe changes to physics properties. This object is passed via the direct state callback of rigid bodies, and is intended for changing the direct state of that body. See [method RigidBody3D._integrate_forces]. </description> <tutorials> <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> @@ -146,7 +146,7 @@ <return type="int" /> <description> Returns the number of contacts this body has with other bodies. - [b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidDynamicBody3D.contact_monitor]. + [b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidBody3D.contact_monitor]. </description> </method> <method name="get_contact_impulse" qualifiers="const"> diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 7ba52c40c6..5ae7423a71 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -980,11 +980,11 @@ <constant name="BODY_MODE_KINEMATIC" value="1" enum="BodyMode"> Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path. </constant> - <constant name="BODY_MODE_DYNAMIC" value="2" enum="BodyMode"> - Constant for dynamic bodies. In this mode, a body can be pushed by other bodies and has forces applied. + <constant name="BODY_MODE_RIGID" value="2" enum="BodyMode"> + Constant for rigid bodies. In this mode, a body can be pushed by other bodies and has forces applied. </constant> - <constant name="BODY_MODE_DYNAMIC_LINEAR" value="3" enum="BodyMode"> - Constant for linear dynamic bodies. In this mode, a body is dynamic but can not rotate, and only its linear velocity is affected by external forces. + <constant name="BODY_MODE_RIGID_LINEAR" value="3" enum="BodyMode"> + Constant for linear rigid bodies. In this mode, a body can not rotate, and only its linear velocity is affected by external forces. </constant> <constant name="BODY_PARAM_BOUNCE" value="0" enum="BodyParameter"> Constant to set/get a body's bounce factor. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index d4796fe2cf..da9e10c420 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1340,11 +1340,11 @@ <constant name="BODY_MODE_KINEMATIC" value="1" enum="BodyMode"> Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path. </constant> - <constant name="BODY_MODE_DYNAMIC" value="2" enum="BodyMode"> - Constant for dynamic bodies. In this mode, a body can be pushed by other bodies and has forces applied. + <constant name="BODY_MODE_RIGID" value="2" enum="BodyMode"> + Constant for rigid bodies. In this mode, a body can be pushed by other bodies and has forces applied. </constant> - <constant name="BODY_MODE_DYNAMIC_LINEAR" value="3" enum="BodyMode"> - Constant for linear dynamic bodies. In this mode, a body is dynamic but can not rotate, and only its linear velocity is affected by external forces. + <constant name="BODY_MODE_RIGID_LINEAR" value="3" enum="BodyMode"> + Constant for linear rigid bodies. In this mode, a body can not rotate, and only its linear velocity is affected by external forces. </constant> <constant name="BODY_PARAM_BOUNCE" value="0" enum="BodyParameter"> Constant to set/get a body's bounce factor. diff --git a/doc/classes/PlaneMesh.xml b/doc/classes/PlaneMesh.xml index 6b3a7ed548..564b6fe743 100644 --- a/doc/classes/PlaneMesh.xml +++ b/doc/classes/PlaneMesh.xml @@ -4,7 +4,7 @@ Class representing a planar [PrimitiveMesh]. </brief_description> <description> - Class representing a planar [PrimitiveMesh]. This flat mesh does not have a thickness. By default, this mesh is aligned on the X and Z axes; this default rotation isn't suited for use with billboarded materials. For billboarded materials, use [QuadMesh] instead. + Class representing a planar [PrimitiveMesh]. This flat mesh does not have a thickness. By default, this mesh is aligned on the X and Z axes; this default rotation isn't suited for use with billboarded materials. For billboarded materials, change [member orientation] to [constant FACE_Z]. [b]Note:[/b] When using a large textured [PlaneMesh] (e.g. as a floor), you may stumble upon UV jittering issues depending on the camera angle. To solve this, increase [member subdivide_depth] and [member subdivide_width] until you no longer notice UV jittering. </description> <tutorials> @@ -13,6 +13,9 @@ <member name="center_offset" type="Vector3" setter="set_center_offset" getter="get_center_offset" default="Vector3(0, 0, 0)"> Offset of the generated plane. Useful for particles. </member> + <member name="orientation" type="int" setter="set_orientation" getter="get_orientation" enum="PlaneMesh.Orientation" default="1"> + Direction that the [PlaneMesh] is facing. See [enum Orientation] for options. + </member> <member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(2, 2)"> Size of the generated plane. </member> @@ -23,4 +26,15 @@ Number of subdivision along the X axis. </member> </members> + <constants> + <constant name="FACE_X" value="0" enum="Orientation"> + [PlaneMesh] will face the positive X-axis. + </constant> + <constant name="FACE_Y" value="1" enum="Orientation"> + [PlaneMesh] will face the positive Y-axis. This matches the behaviour of the [PlaneMesh] in Godot 3.x. + </constant> + <constant name="FACE_Z" value="2" enum="Orientation"> + [PlaneMesh] will face the positive Z-axis. This matches the behvaiour of the QuadMesh in Godot 3.x. + </constant> + </constants> </class> diff --git a/doc/classes/Polygon2D.xml b/doc/classes/Polygon2D.xml index 5d5c69aadd..12f8055180 100644 --- a/doc/classes/Polygon2D.xml +++ b/doc/classes/Polygon2D.xml @@ -79,10 +79,10 @@ <member name="internal_vertex_count" type="int" setter="set_internal_vertex_count" getter="get_internal_vertex_count" default="0"> </member> <member name="invert_border" type="float" setter="set_invert_border" getter="get_invert_border" default="100.0"> - Added padding applied to the bounding box when using [code]invert[/code]. Setting this value too small may result in a "Bad Polygon" error. + Added padding applied to the bounding box when [member invert_enabled] is set to [code]true[/code]. Setting this value too small may result in a "Bad Polygon" error. </member> - <member name="invert_enable" type="bool" setter="set_invert" getter="get_invert" default="false"> - If [code]true[/code], polygon will be inverted, containing the area outside the defined points and extending to the [code]invert_border[/code]. + <member name="invert_enabled" type="bool" setter="set_invert_enabled" getter="get_invert_enabled" default="false"> + If [code]true[/code], the polygon will be inverted, containing the area outside the defined points and extending to the [member invert_border]. </member> <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)"> The offset applied to each vertex. diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml index 7046a21f68..1b9ecdbfa0 100644 --- a/doc/classes/PrimitiveMesh.xml +++ b/doc/classes/PrimitiveMesh.xml @@ -4,7 +4,7 @@ Base class for all primitive meshes. Handles applying a [Material] to a primitive mesh. </brief_description> <description> - Base class for all primitive meshes. Handles applying a [Material] to a primitive mesh. Examples include [BoxMesh], [CapsuleMesh], [CylinderMesh], [PlaneMesh], [PrismMesh], [QuadMesh], and [SphereMesh]. + Base class for all primitive meshes. Handles applying a [Material] to a primitive mesh. Examples include [BoxMesh], [CapsuleMesh], [CylinderMesh], [PlaneMesh], [PrismMesh], and [SphereMesh]. </description> <tutorials> </tutorials> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index a2e202b218..bafd5d57d9 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -648,8 +648,8 @@ <member name="gui/theme/custom_font" type="String" setter="" getter="" default=""""> Path to a custom [Font] resource to use as default for all GUI elements of the project. </member> - <member name="gui/theme/default_font_antialiased" type="bool" setter="" getter="" default="true"> - If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontFile.antialiased]. + <member name="gui/theme/default_font_antialiasing" type="int" setter="" getter="" default="1"> + Font anti-aliasing mode. See [member FontFile.antialiasing], </member> <member name="gui/theme/default_font_generate_mipmaps" type="bool" setter="" getter="" default="false"> If set to [code]true[/code], the default font will have mipmaps generated. This prevents text from looking grainy when a [Control] is scaled down, or when a [Label3D] is viewed from a long distance (if [member Label3D.texture_filter] is set to a mode that displays mipmaps). @@ -669,6 +669,9 @@ </member> <member name="gui/theme/default_theme_scale" type="float" setter="" getter="" default="1.0"> </member> + <member name="gui/theme/lcd_subpixel_layout" type="int" setter="" getter="" default="1"> + LCD sub-pixel layout used for font anti-aliasing. See [enum TextServer.FontLCDSubpixelLayout]. + </member> <member name="gui/timers/incremental_search_max_interval_msec" type="int" setter="" getter="" default="2000"> Timer setting for incremental search in [Tree], [ItemList], etc. controls (in milliseconds). </member> @@ -1640,13 +1643,13 @@ Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware. See also bilinear scaling 3d [member rendering/scaling_3d/mode] for supersampling, which provides higher quality but is much more expensive. </member> <member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0"> - Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. The blurriness can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]). + Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. The blurriness is partially counteracted by automatically using a negative mipmap LOD bias (see [member rendering/textures/default_filters/texture_mipmap_bias]). Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled]. </member> <member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false"> </member> <member name="rendering/anti_aliasing/quality/use_taa" type="bool" setter="" getter="" default="false"> - Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]). + Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which is partially counteracted by automatically using a negative mipmap LOD bias (see [member rendering/textures/default_filters/texture_mipmap_bias]). [b]Note:[/b] The implementation is not complete yet, some visual instances such as particles and skinned meshes may show artifacts. </member> <member name="rendering/anti_aliasing/screen_space_roughness_limiter/amount" type="float" setter="" getter="" default="0.25"> @@ -1949,7 +1952,8 @@ [b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time. </member> <member name="rendering/textures/default_filters/texture_mipmap_bias" type="float" setter="" getter="" default="0.0"> - Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias. + Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). + Enabling temporal antialiasing ([member rendering/anti_aliasing/quality/use_taa]) will automatically apply a [code]-0.5[/code] offset to this value, while enabling FXAA ([member rendering/anti_aliasing/quality/screen_space_aa]) will automatically apply a [code]-0.25[/code] offset to this value. If both TAA and FXAA are enbled at the same time, an offset of [code]-0.75[/code] is applied to this value. [b]Note:[/b] If [member rendering/scaling_3d/scale] is lower than [code]1.0[/code] (exclusive), [member rendering/textures/default_filters/texture_mipmap_bias] is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]log2(scaling_3d_scale) + mipmap_bias[/code]. [b]Note:[/b] This property is only read when the project starts. To change the mipmap LOD bias at run-time, set [member Viewport.texture_mipmap_bias] instead. </member> diff --git a/doc/classes/QuadMesh.xml b/doc/classes/QuadMesh.xml deleted file mode 100644 index d641ebaa1f..0000000000 --- a/doc/classes/QuadMesh.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="QuadMesh" inherits="PrimitiveMesh" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> - <brief_description> - Class representing a square mesh. - </brief_description> - <description> - Class representing a square [PrimitiveMesh]. This flat mesh does not have a thickness. By default, this mesh is aligned on the X and Y axes; this default rotation is more suited for use with billboarded materials. Unlike [PlaneMesh], this mesh doesn't provide subdivision options. - </description> - <tutorials> - <link title="GUI in 3D Demo">https://godotengine.org/asset-library/asset/127</link> - <link title="2D in 3D Demo">https://godotengine.org/asset-library/asset/129</link> - </tutorials> - <members> - <member name="center_offset" type="Vector3" setter="set_center_offset" getter="get_center_offset" default="Vector3(0, 0, 0)"> - Offset of the generated Quad. Useful for particles. - </member> - <member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(1, 1)"> - Size on the X and Y axes. - </member> - </members> -</class> diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index 2f0b9dae72..718a161323 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -227,6 +227,14 @@ <description> </description> </method> + <method name="draw_list_set_blend_constants"> + <return type="void" /> + <param index="0" name="draw_list" type="int" /> + <param index="1" name="color" type="Color" /> + <description> + Sets blend constants for draw list, blend constants are used only if the graphics pipeline is created with [code]DYNAMIC_STATE_BLEND_CONSTANTS[/code] flag set. + </description> + </method> <method name="draw_list_set_push_constant"> <return type="void" /> <param index="0" name="draw_list" type="int" /> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index a12bd71454..639db6b3b5 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -176,6 +176,16 @@ <description> </description> </method> + <method name="canvas_item_add_lcd_texture_rect_region"> + <return type="void" /> + <param index="0" name="item" type="RID" /> + <param index="1" name="rect" type="Rect2" /> + <param index="2" name="texture" type="RID" /> + <param index="3" name="src_rect" type="Rect2" /> + <param index="4" name="modulate" type="Color" /> + <description> + </description> + </method> <method name="canvas_item_add_line"> <return type="void" /> <param index="0" name="item" type="RID" /> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index f96e136a57..f4cbf4c442 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -480,10 +480,6 @@ <member name="override_selected_font_color" type="bool" setter="set_override_selected_font_color" getter="is_overriding_selected_font_color" default="false"> If [code]true[/code], the label uses the custom font color. </member> - <member name="percent_visible" type="float" setter="set_percent_visible" getter="get_percent_visible" default="1.0"> - The fraction of characters to display, relative to the total number of characters (see [method get_total_character_count]). If set to [code]1.0[/code], all characters are displayed. If set to [code]0.5[/code], only half of the characters will be displayed. This can be useful when animating the text appearing in a dialog box. - [b]Note:[/b] Setting this property updates [member visible_characters] accordingly. - </member> <member name="progress_bar_delay" type="int" setter="set_progress_bar_delay" getter="get_progress_bar_delay" default="1000"> The delay after which the loading progress bar is displayed, in milliseconds. Set to [code]-1[/code] to disable progress bar entirely. [b]Note:[/b] Progress bar is displayed only if [member threaded] is enabled. @@ -521,10 +517,14 @@ </member> <member name="visible_characters" type="int" setter="set_visible_characters" getter="get_visible_characters" default="-1"> The number of characters to display. If set to [code]-1[/code], all characters are displayed. This can be useful when animating the text appearing in a dialog box. - [b]Note:[/b] Setting this property updates [member percent_visible] accordingly. + [b]Note:[/b] Setting this property updates [member visible_ratio] accordingly. </member> <member name="visible_characters_behavior" type="int" setter="set_visible_characters_behavior" getter="get_visible_characters_behavior" enum="TextServer.VisibleCharactersBehavior" default="0"> - Sets the clipping behavior when [member visible_characters] or [member percent_visible] is set. See [enum TextServer.VisibleCharactersBehavior] for more info. + Sets the clipping behavior when [member visible_characters] or [member visible_ratio] is set. See [enum TextServer.VisibleCharactersBehavior] for more info. + </member> + <member name="visible_ratio" type="float" setter="set_visible_ratio" getter="get_visible_ratio" default="1.0"> + The fraction of characters to display, relative to the total number of characters (see [method get_total_character_count]). If set to [code]1.0[/code], all characters are displayed. If set to [code]0.5[/code], only half of the characters will be displayed. This can be useful when animating the text appearing in a dialog box. + [b]Note:[/b] Setting this property updates [member visible_characters] accordingly. </member> </members> <signals> diff --git a/doc/classes/RigidDynamicBody2D.xml b/doc/classes/RigidBody2D.xml index 445e6d94ea..9eedc3a24c 100644 --- a/doc/classes/RigidDynamicBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RigidDynamicBody2D" inherits="PhysicsBody2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="RigidBody2D" inherits="PhysicsBody2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Physics Body which is moved by 2D physics simulation. Useful for objects that have gravity and can be pushed by other objects. </brief_description> <description> - This node implements simulated 2D physics. You do not control a RigidDynamicBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. + This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. You can switch the body's behavior using [member lock_rotation], [member freeze], and [member freeze_mode]. - [b]Note:[/b] You should not change a RigidDynamicBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. + [b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. Please also keep in mind that physics bodies manage their own transform which overwrites the ones you set. So any direct or indirect transformation (including scaling of the node or its parent) will be visible in the editor only, and immediately reset at runtime. If you need to override the default physics behavior or add a transformation at runtime, you can write a custom force integration. See [member custom_integrator]. </description> @@ -100,10 +100,17 @@ <method name="get_colliding_bodies" qualifiers="const"> <return type="Node2D[]" /> <description> - Returns a list of the bodies colliding with this one. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. + Returns a list of the bodies colliding with this one. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of collisions is updated once per frame and before the physics step. Consider using signals instead. </description> </method> + <method name="get_contact_count" qualifiers="const"> + <return type="int" /> + <description> + Returns the number of contacts this body has with other bodies. By default, this returns 0 unless bodies are configured to monitor contacts (see [member contact_monitor]). + [b]Note:[/b] To retrieve the colliding bodies, use [method get_colliding_bodies]. + </description> + </method> <method name="set_axis_velocity"> <return type="void" /> <param index="0" name="axis_velocity" type="Vector2" /> @@ -117,7 +124,7 @@ Damps the body's rotation. By default, the body will use the [b]Default Angular Damp[/b] in [b]Project > Project Settings > Physics > 2d[/b] or any value override set by an [Area2D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/2d/default_angular_damp] for more details about damping. </member> - <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidDynamicBody2D.DampMode" default="0"> + <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidBody2D.DampMode" default="0"> Defines how [member angular_damp] is applied. See [enum DampMode] for possible values. </member> <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity" default="0.0"> @@ -130,7 +137,7 @@ The body's custom center of mass, relative to the body's origin position, when [member center_of_mass_mode] is set to [constant CENTER_OF_MASS_MODE_CUSTOM]. This is the balanced point of the body, where applied forces only cause linear acceleration. Applying forces outside of the center of mass causes angular acceleration. When [member center_of_mass_mode] is set to [constant CENTER_OF_MASS_MODE_AUTO] (default value), the center of mass is automatically computed. </member> - <member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidDynamicBody2D.CenterOfMassMode" default="0"> + <member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidBody2D.CenterOfMassMode" default="0"> Defines the way the body's center of mass is set. See [enum CenterOfMassMode] for possible values. </member> <member name="constant_force" type="Vector2" setter="set_constant_force" getter="get_constant_force" default="Vector2(0, 0)"> @@ -142,13 +149,10 @@ See [method add_constant_torque]. </member> <member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false"> - If [code]true[/code], the body will emit signals when it collides with another RigidDynamicBody2D. See also [member contacts_reported]. + If [code]true[/code], the RigidBody2D will emit signals when it collides with another RigidBody2D. + [b]Note:[/b] By default the maximum contacts reported is set to 0, meaning nothing will be recorded, see [member max_contacts_reported]. </member> - <member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported" default="0"> - The maximum number of contacts that will be recorded. Requires [member contact_monitor] to be set to [code]true[/code]. - [b]Note:[/b] The number of contacts is different from the number of collisions. Collisions between parallel edges will result in two contacts (one at each end). - </member> - <member name="continuous_cd" type="int" setter="set_continuous_collision_detection_mode" getter="get_continuous_collision_detection_mode" enum="RigidDynamicBody2D.CCDMode" default="0"> + <member name="continuous_cd" type="int" setter="set_continuous_collision_detection_mode" getter="get_continuous_collision_detection_mode" enum="RigidBody2D.CCDMode" default="0"> Continuous collision detection mode. Continuous collision detection tries to predict where a moving body will collide instead of moving it and correcting its movement after collision. Continuous collision detection is slower, but more precise and misses fewer collisions with small, fast-moving objects. Raycasting and shapecasting methods are available. See [enum CCDMode] for details. </member> @@ -160,7 +164,7 @@ See [member freeze_mode] to set the body's behavior when frozen. For a body that is always frozen, use [StaticBody2D] or [AnimatableBody2D] instead. </member> - <member name="freeze_mode" type="int" setter="set_freeze_mode" getter="get_freeze_mode" enum="RigidDynamicBody2D.FreezeMode" default="0"> + <member name="freeze_mode" type="int" setter="set_freeze_mode" getter="get_freeze_mode" enum="RigidBody2D.FreezeMode" default="0"> The body's freeze mode. Can be used to set the body's behavior when [member freeze] is enabled. See [enum FreezeMode] for possible values. For a body that is always frozen, use [StaticBody2D] or [AnimatableBody2D] instead. </member> @@ -175,7 +179,7 @@ Damps the body's movement. By default, the body will use the [b]Default Linear Damp[/b] in [b]Project > Project Settings > Physics > 2d[/b] or any value override set by an [Area2D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/2d/default_linear_damp] for more details about damping. </member> - <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidDynamicBody2D.DampMode" default="0"> + <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidBody2D.DampMode" default="0"> Defines how [member linear_damp] is applied. See [enum DampMode] for possible values. </member> <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector2(0, 0)"> @@ -187,6 +191,10 @@ <member name="mass" type="float" setter="set_mass" getter="get_mass" default="1.0"> The body's mass. </member> + <member name="max_contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported" default="0"> + The maximum number of contacts that will be recorded. Requires a value greater than 0 and [member contact_monitor] to be set to [code]true[/code] to start to register contacts. Use [method get_contact_count] to retrieve the count or [method get_colliding_bodies] to retrieve bodies that have been collided with. + [b]Note:[/b] The number of contacts is different from the number of collisions. Collisions between parallel edges will result in two contacts (one at each end), and collisions between parallel faces will result in four contacts (one at each corner). + </member> <member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override"> The physics material override for the body. If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one. @@ -199,14 +207,14 @@ <signal name="body_entered"> <param index="0" name="body" type="Node" /> <description> - Emitted when a collision with another [PhysicsBody2D] or [TileMap] occurs. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. + Emitted when a collision with another [PhysicsBody2D] or [TileMap] occurs. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap]. </description> </signal> <signal name="body_exited"> <param index="0" name="body" type="Node" /> <description> - Emitted when the collision with another [PhysicsBody2D] or [TileMap] ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. + Emitted when the collision with another [PhysicsBody2D] or [TileMap] ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap]. </description> </signal> @@ -216,11 +224,11 @@ <param index="2" name="body_shape_index" type="int" /> <param index="3" name="local_shape_index" type="int" /> <description> - Emitted when one of this RigidDynamicBody2D's [Shape2D]s collides with another [PhysicsBody2D] or [TileMap]'s [Shape2D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. + Emitted when one of this RigidBody2D's [Shape2D]s collides with another [PhysicsBody2D] or [TileMap]'s [Shape2D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. [param body_rid] the [RID] of the other [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D]. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap]. [param body_shape_index] the index of the [Shape2D] of the other [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code]. - [param local_shape_index] the index of the [Shape2D] of this RigidDynamicBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. + [param local_shape_index] the index of the [Shape2D] of this RigidBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. </description> </signal> <signal name="body_shape_exited"> @@ -229,11 +237,11 @@ <param index="2" name="body_shape_index" type="int" /> <param index="3" name="local_shape_index" type="int" /> <description> - Emitted when the collision between one of this RigidDynamicBody2D's [Shape2D]s and another [PhysicsBody2D] or [TileMap]'s [Shape2D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. + Emitted when the collision between one of this RigidBody2D's [Shape2D]s and another [PhysicsBody2D] or [TileMap]'s [Shape2D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. [param body_rid] the [RID] of the other [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D]. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap]. [param body_shape_index] the index of the [Shape2D] of the other [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code]. - [param local_shape_index] the index of the [Shape2D] of this RigidDynamicBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. + [param local_shape_index] the index of the [Shape2D] of this RigidBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. </description> </signal> <signal name="sleeping_state_changed"> diff --git a/doc/classes/RigidDynamicBody3D.xml b/doc/classes/RigidBody3D.xml index 7072134250..3ee3f25df1 100644 --- a/doc/classes/RigidDynamicBody3D.xml +++ b/doc/classes/RigidBody3D.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RigidDynamicBody3D" inherits="PhysicsBody3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="RigidBody3D" inherits="PhysicsBody3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Physics Body which is moved by 3D physics simulation. Useful for objects that have gravity and can be pushed by other objects. </brief_description> <description> - This is the node that implements full 3D physics. This means that you do not control a RigidDynamicBody3D directly. Instead, you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. + This is the node that implements full 3D physics. This means that you do not control a RigidBody3D directly. Instead, you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. You can switch the body's behavior using [member lock_rotation], [member freeze], and [member freeze_mode]. - [b]Note:[/b] Don't change a RigidDynamicBody3D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed Hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop may result in strange behavior. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. + [b]Note:[/b] Don't change a RigidBody3D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed Hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop may result in strange behavior. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. If you need to override the default physics behavior, you can write a custom force integration function. See [member custom_integrator]. </description> <tutorials> @@ -100,14 +100,21 @@ <method name="get_colliding_bodies" qualifiers="const"> <return type="Node3D[]" /> <description> - Returns a list of the bodies colliding with this one. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. + Returns a list of the bodies colliding with this one. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of collisions is updated once per frame and before the physics step. Consider using signals instead. </description> </method> + <method name="get_contact_count" qualifiers="const"> + <return type="int" /> + <description> + Returns the number of contacts this body has with other bodies. By default, this returns 0 unless bodies are configured to monitor contacts (see [member contact_monitor]). + [b]Note:[/b] To retrieve the colliding bodies, use [method get_colliding_bodies]. + </description> + </method> <method name="get_inverse_inertia_tensor" qualifiers="const"> <return type="Basis" /> <description> - Returns the inverse inertia tensor basis. This is used to calculate the angular acceleration resulting from a torque applied to the [RigidDynamicBody3D]. + Returns the inverse inertia tensor basis. This is used to calculate the angular acceleration resulting from a torque applied to the [RigidBody3D]. </description> </method> <method name="set_axis_velocity"> @@ -123,11 +130,11 @@ Damps the body's rotation. By default, the body will use the [b]Default Angular Damp[/b] in [b]Project > Project Settings > Physics > 3d[/b] or any value override set by an [Area3D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/3d/default_angular_damp] for more details about damping. </member> - <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidDynamicBody3D.DampMode" default="0"> + <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidBody3D.DampMode" default="0"> Defines how [member angular_damp] is applied. See [enum DampMode] for possible values. </member> <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity" default="Vector3(0, 0, 0)"> - The RigidDynamicBody3D's rotational velocity in [i]radians[/i] per second. + The RigidBody3D's rotational velocity in [i]radians[/i] per second. </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true"> If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping]. @@ -136,7 +143,7 @@ The body's custom center of mass, relative to the body's origin position, when [member center_of_mass_mode] is set to [constant CENTER_OF_MASS_MODE_CUSTOM]. This is the balanced point of the body, where applied forces only cause linear acceleration. Applying forces outside of the center of mass causes angular acceleration. When [member center_of_mass_mode] is set to [constant CENTER_OF_MASS_MODE_AUTO] (default value), the center of mass is automatically computed. </member> - <member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidDynamicBody3D.CenterOfMassMode" default="0"> + <member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidBody3D.CenterOfMassMode" default="0"> Defines the way the body's center of mass is set. See [enum CenterOfMassMode] for possible values. </member> <member name="constant_force" type="Vector3" setter="set_constant_force" getter="get_constant_force" default="Vector3(0, 0, 0)"> @@ -148,11 +155,8 @@ See [method add_constant_torque]. </member> <member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false"> - If [code]true[/code], the RigidDynamicBody3D will emit signals when it collides with another RigidDynamicBody3D. See also [member contacts_reported]. - </member> - <member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported" default="0"> - The maximum number of contacts that will be recorded. Requires [member contact_monitor] to be set to [code]true[/code]. - [b]Note:[/b] The number of contacts is different from the number of collisions. Collisions between parallel edges will result in two contacts (one at each end), and collisions between parallel faces will result in four contacts (one at each corner). + If [code]true[/code], the RigidBody3D will emit signals when it collides with another RigidBody3D. + [b]Note:[/b] By default the maximum contacts reported is set to 0, meaning nothing will be recorded, see [member max_contacts_reported]. </member> <member name="continuous_cd" type="bool" setter="set_use_continuous_collision_detection" getter="is_using_continuous_collision_detection" default="false"> If [code]true[/code], continuous collision detection is used. @@ -166,12 +170,12 @@ See [member freeze_mode] to set the body's behavior when frozen. For a body that is always frozen, use [StaticBody3D] or [AnimatableBody3D] instead. </member> - <member name="freeze_mode" type="int" setter="set_freeze_mode" getter="get_freeze_mode" enum="RigidDynamicBody3D.FreezeMode" default="0"> + <member name="freeze_mode" type="int" setter="set_freeze_mode" getter="get_freeze_mode" enum="RigidBody3D.FreezeMode" default="0"> The body's freeze mode. Can be used to set the body's behavior when [member freeze] is enabled. See [enum FreezeMode] for possible values. For a body that is always frozen, use [StaticBody3D] or [AnimatableBody3D] instead. </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale" default="1.0"> - This is multiplied by the global 3D gravity setting found in [b]Project > Project Settings > Physics > 3d[/b] to produce RigidDynamicBody3D's gravity. For example, a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. + This is multiplied by the global 3D gravity setting found in [b]Project > Project Settings > Physics > 3d[/b] to produce RigidBody3D's gravity. For example, a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. </member> <member name="inertia" type="Vector3" setter="set_inertia" getter="get_inertia" default="Vector3(0, 0, 0)"> The body's moment of inertia. This is like mass, but for rotation: it determines how much torque it takes to rotate the body on each axis. The moment of inertia is usually computed automatically from the mass and the shapes, but this property allows you to set a custom value. @@ -181,7 +185,7 @@ Damps the body's movement. By default, the body will use the [b]Default Linear Damp[/b] in [b]Project > Project Settings > Physics > 3d[/b] or any value override set by an [Area3D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/3d/default_linear_damp] for more details about damping. </member> - <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidDynamicBody3D.DampMode" default="0"> + <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidBody3D.DampMode" default="0"> Defines how [member linear_damp] is applied. See [enum DampMode] for possible values. </member> <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector3(0, 0, 0)"> @@ -193,6 +197,10 @@ <member name="mass" type="float" setter="set_mass" getter="get_mass" default="1.0"> The body's mass. </member> + <member name="max_contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported" default="0"> + The maximum number of contacts that will be recorded. Requires a value greater than 0 and [member contact_monitor] to be set to [code]true[/code] to start to register contacts. Use [method get_contact_count] to retrieve the count or [method get_colliding_bodies] to retrieve bodies that have been collided with. + [b]Note:[/b] The number of contacts is different from the number of collisions. Collisions between parallel edges will result in two contacts (one at each end), and collisions between parallel faces will result in four contacts (one at each corner). + </member> <member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override"> The physics material override for the body. If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one. @@ -205,14 +213,14 @@ <signal name="body_entered"> <param index="0" name="body" type="Node" /> <description> - Emitted when a collision with another [PhysicsBody3D] or [GridMap] occurs. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. + Emitted when a collision with another [PhysicsBody3D] or [GridMap] occurs. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap]. </description> </signal> <signal name="body_exited"> <param index="0" name="body" type="Node" /> <description> - Emitted when the collision with another [PhysicsBody3D] or [GridMap] ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. + Emitted when the collision with another [PhysicsBody3D] or [GridMap] ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap]. </description> </signal> @@ -222,11 +230,11 @@ <param index="2" name="body_shape_index" type="int" /> <param index="3" name="local_shape_index" type="int" /> <description> - Emitted when one of this RigidDynamicBody3D's [Shape3D]s collides with another [PhysicsBody3D] or [GridMap]'s [Shape3D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. + Emitted when one of this RigidBody3D's [Shape3D]s collides with another [PhysicsBody3D] or [GridMap]'s [Shape3D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. [param body_rid] the [RID] of the other [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D]. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap]. [param body_shape_index] the index of the [Shape3D] of the other [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code]. - [param local_shape_index] the index of the [Shape3D] of this RigidDynamicBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. + [param local_shape_index] the index of the [Shape3D] of this RigidBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. </description> </signal> <signal name="body_shape_exited"> @@ -235,11 +243,11 @@ <param index="2" name="body_shape_index" type="int" /> <param index="3" name="local_shape_index" type="int" /> <description> - Emitted when the collision between one of this RigidDynamicBody3D's [Shape3D]s and another [PhysicsBody3D] or [GridMap]'s [Shape3D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. + Emitted when the collision between one of this RigidBody3D's [Shape3D]s and another [PhysicsBody3D] or [GridMap]'s [Shape3D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. [param body_rid] the [RID] of the other [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D]. [GridMap]s are detected if the Meshes have [Shape3D]s. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap]. [param body_shape_index] the index of the [Shape3D] of the other [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code]. - [param local_shape_index] the index of the [Shape3D] of this RigidDynamicBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. + [param local_shape_index] the index of the [Shape3D] of this RigidBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. </description> </signal> <signal name="sleeping_state_changed"> diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index 69b9988641..45ca330b87 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -20,15 +20,6 @@ Adds a bone, with name [param name]. [method get_bone_count] will become the bone index. </description> </method> - <method name="add_bone_child"> - <return type="void" /> - <param index="0" name="bone_idx" type="int" /> - <param index="1" name="child_bone_idx" type="int" /> - <description> - Takes the given bone pose/transform and converts it to a world transform, relative to the [Skeleton3D] node. - This is useful for using the bone transform in calculations with transforms from [Node3D]-based nodes. - </description> - </method> <method name="clear_bones"> <return type="void" /> <description> @@ -240,7 +231,7 @@ <param index="0" name="exception" type="RID" /> <description> Adds a collision exception to the physical bone. - Works just like the [RigidDynamicBody3D] node. + Works just like the [RigidBody3D] node. </description> </method> <method name="physical_bones_remove_collision_exception"> @@ -248,7 +239,7 @@ <param index="0" name="exception" type="RID" /> <description> Removes a collision exception to the physical bone. - Works just like the [RigidDynamicBody3D] node. + Works just like the [RigidBody3D] node. </description> </method> <method name="physical_bones_start_simulation"> @@ -272,15 +263,6 @@ Binds the given Skin to the Skeleton. </description> </method> - <method name="remove_bone_child"> - <return type="void" /> - <param index="0" name="bone_idx" type="int" /> - <param index="1" name="child_bone_idx" type="int" /> - <description> - Removes the passed in child bone index, [param child_bone_idx], from the passed-in bone, [param bone_idx], if it exists. - [b]Note:[/b] This does not remove the child bone, but instead it removes the connection it has to the parent bone. - </description> - </method> <method name="reset_bone_pose"> <return type="void" /> <param index="0" name="bone_idx" type="int" /> @@ -294,14 +276,6 @@ Sets all bone poses to rests. </description> </method> - <method name="set_bone_children"> - <return type="void" /> - <param index="0" name="bone_idx" type="int" /> - <param index="1" name="bone_children" type="PackedInt32Array" /> - <description> - Sets the children for the passed in bone, [param bone_idx], to the passed-in array of bone indexes, [param bone_children]. - </description> - </method> <method name="set_bone_enabled"> <return type="void" /> <param index="0" name="bone_idx" type="int" /> diff --git a/doc/classes/SoftDynamicBody3D.xml b/doc/classes/SoftBody3D.xml index 7f0a1d94d0..7006bca6f0 100644 --- a/doc/classes/SoftDynamicBody3D.xml +++ b/doc/classes/SoftBody3D.xml @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SoftDynamicBody3D" inherits="MeshInstance3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="SoftBody3D" inherits="MeshInstance3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> A soft mesh physics body. </brief_description> <description> A deformable physics body. Used to create elastic or deformable objects such as cloth, rubber, or other flexible materials. - [b]Note:[/b] There are many known bugs in [SoftDynamicBody3D]. Therefore, it's not recommended to use them for things that can affect gameplay (such as a player character made entirely out of soft bodies). + [b]Note:[/b] There are many known bugs in [SoftBody3D]. Therefore, it's not recommended to use them for things that can affect gameplay (such as a player character made entirely out of soft bodies). </description> <tutorials> <link title="SoftBody">$DOCS_URL/tutorials/physics/soft_body.html</link> @@ -92,16 +92,16 @@ </methods> <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> - The physics layers this SoftDynamicBody3D [b]is in[/b]. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. + The physics layers this SoftBody3D [b]is in[/b]. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The physics layers this SoftDynamicBody3D [b]scans[/b]. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. + The physics layers this SoftBody3D [b]scans[/b]. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01"> </member> - <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftDynamicBody3D.DisableMode" default="0"> + <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftBody3D.DisableMode" default="0"> Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. </member> <member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0"> @@ -109,23 +109,23 @@ <member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5"> </member> <member name="parent_collision_ignore" type="NodePath" setter="set_parent_collision_ignore" getter="get_parent_collision_ignore" default="NodePath("")"> - [NodePath] to a [CollisionObject3D] this SoftDynamicBody3D should avoid clipping. + [NodePath] to a [CollisionObject3D] this SoftBody3D should avoid clipping. </member> <member name="pressure_coefficient" type="float" setter="set_pressure_coefficient" getter="get_pressure_coefficient" default="0.0"> </member> <member name="ray_pickable" type="bool" setter="set_ray_pickable" getter="is_ray_pickable" default="true"> - If [code]true[/code], the [SoftDynamicBody3D] will respond to [RayCast3D]s. + If [code]true[/code], the [SoftBody3D] will respond to [RayCast3D]s. </member> <member name="simulation_precision" type="int" setter="set_simulation_precision" getter="get_simulation_precision" default="5"> Increasing this value will improve the resulting simulation, but can affect performance. Use with care. </member> <member name="total_mass" type="float" setter="set_total_mass" getter="get_total_mass" default="1.0"> - The SoftDynamicBody3D's mass. + The SoftBody3D's mass. </member> </members> <constants> <constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode"> - When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [SoftDynamicBody3D]. + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [SoftBody3D]. Automatically re-added to the physics simulation when the [Node] is processed again. </constant> <constant name="DISABLE_MODE_KEEP_ACTIVE" value="1" enum="DisableMode"> diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml index e6e3559ae0..21c160b780 100644 --- a/doc/classes/StaticBody2D.xml +++ b/doc/classes/StaticBody2D.xml @@ -5,7 +5,7 @@ </brief_description> <description> Static body for 2D physics. - A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidDynamicBody2D], it doesn't consume any CPU resources as long as they don't move. + A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody2D], it doesn't consume any CPU resources as long as they don't move. They have extra functionalities to move and affect other bodies: [b]Static transform change:[/b] Static bodies can be moved by animation or script. In this case, they are just teleported and don't affect other bodies on their path. [b]Constant velocity:[/b] When [member constant_linear_velocity] or [member constant_angular_velocity] is set, static bodies don't move themselves but affect touching bodies as if they were moving. This is useful for simulating conveyor belts or conveyor wheels. diff --git a/doc/classes/StaticBody3D.xml b/doc/classes/StaticBody3D.xml index a29f5fc147..daa71d1168 100644 --- a/doc/classes/StaticBody3D.xml +++ b/doc/classes/StaticBody3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> Static body for 3D physics. - A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidDynamicBody3D], it doesn't consume any CPU resources as long as they don't move. + A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody3D], it doesn't consume any CPU resources as long as they don't move. They have extra functionalities to move and affect other bodies: [b]Static transform change:[/b] Static bodies can be moved by animation or script. In this case, they are just teleported and don't affect other bodies on their path. [b]Constant velocity:[/b] When [member constant_linear_velocity] or [member constant_angular_velocity] is set, static bodies don't move themselves but affect touching bodies as if they were moving. This is useful for simulating conveyor belts or conveyor wheels. diff --git a/doc/classes/SubViewport.xml b/doc/classes/SubViewport.xml index b62c294f2c..7020cae1de 100644 --- a/doc/classes/SubViewport.xml +++ b/doc/classes/SubViewport.xml @@ -25,7 +25,7 @@ The update mode when the sub-viewport is used as a render target. </member> <member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i(512, 512)"> - The width and height of the sub-viewport. + The width and height of the sub-viewport. Must be set to a value greater than or equal to 2 pixels on both dimensions. Otherwise, nothing will be displayed. </member> <member name="size_2d_override" type="Vector2i" setter="set_size_2d_override" getter="get_size_2d_override" default="Vector2i(0, 0)"> The 2D size override of the sub-viewport. If either the width or height is [code]0[/code], the override is disabled. diff --git a/doc/classes/SystemFont.xml b/doc/classes/SystemFont.xml index b7454cc7d2..c235843f3b 100644 --- a/doc/classes/SystemFont.xml +++ b/doc/classes/SystemFont.xml @@ -13,8 +13,8 @@ <tutorials> </tutorials> <members> - <member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true"> - If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled. + <member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1"> + Font anti-aliasing mode. </member> <member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]"> Array of fallback [Font]s. diff --git a/doc/classes/TextMesh.xml b/doc/classes/TextMesh.xml index 17a0ca32e4..678b95cc72 100644 --- a/doc/classes/TextMesh.xml +++ b/doc/classes/TextMesh.xml @@ -11,6 +11,9 @@ <tutorials> </tutorials> <members> + <member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="TextServer.AutowrapMode" default="0"> + If set to something other than [constant TextServer.AUTOWRAP_OFF], the text gets wrapped inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. To see how each mode behaves, see [enum TextServer.AutowrapMode]. + </member> <member name="curve_step" type="float" setter="set_curve_step" getter="get_curve_step" default="0.5"> Step (in pixels) used to approximate Bézier curves. </member> @@ -29,6 +32,12 @@ <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for text shaping algorithms, if left empty current locale is used instead. </member> + <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0"> + Vertical space between lines in multiline [TextMesh]. + </member> + <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)"> + The text drawing offset (in pixels). + </member> <member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01"> The size of one pixel's width on the text to scale it in 3D. </member> @@ -47,6 +56,9 @@ <member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase" default="false"> If [code]true[/code], all the text displays as UPPERCASE. </member> + <member name="vertical_alignment" type="int" setter="set_vertical_alignment" getter="get_vertical_alignment" enum="VerticalAlignment" default="1"> + Controls the text's vertical alignment. Supports top, center, bottom. Set it to one of the [enum VerticalAlignment] constants. + </member> <member name="width" type="float" setter="set_width" getter="get_width" default="500.0"> Text width (in pixels), used for fill alignment. </member> diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 9c4f7857c7..aad83211f5 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -98,6 +98,13 @@ [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update. </description> </method> + <method name="font_get_antialiasing" qualifiers="const"> + <return type="int" enum="TextServer.FontAntialiasing" /> + <param index="0" name="font_rid" type="RID" /> + <description> + Returns font anti-aliasing mode. + </description> + </method> <method name="font_get_ascent" qualifiers="const"> <return type="float" /> <param index="0" name="font_rid" type="RID" /> @@ -447,13 +454,6 @@ Returns [code]true[/code] if a Unicode [param char] is available in the font. </description> </method> - <method name="font_is_antialiased" qualifiers="const"> - <return type="bool" /> - <param index="0" name="font_rid" type="RID" /> - <description> - Returns [code]true[/code] if font 8-bit anitialiased glyph rendering is supported and enabled. - </description> - </method> <method name="font_is_force_autohinter" qualifiers="const"> <return type="bool" /> <param index="0" name="font_rid" type="RID" /> @@ -556,12 +556,12 @@ Renders the range of characters to the font cache texture. </description> </method> - <method name="font_set_antialiased"> + <method name="font_set_antialiasing"> <return type="void" /> <param index="0" name="font_rid" type="RID" /> - <param index="1" name="antialiased" type="bool" /> + <param index="1" name="antialiasing" type="int" enum="TextServer.FontAntialiasing" /> <description> - If set to [code]true[/code], 8-bit antialiased glyph rendering is used, otherwise 1-bit rendering is used. Used by dynamic fonts only. + Sets font anti-aliasing mode. </description> </method> <method name="font_set_ascent"> @@ -1539,6 +1539,32 @@ </method> </methods> <constants> + <constant name="FONT_ANTIALIASING_NONE" value="0" enum="FontAntialiasing"> + Font glyphs are rasterized as 1-bit bitmaps. + </constant> + <constant name="FONT_ANTIALIASING_GRAY" value="1" enum="FontAntialiasing"> + Font glyphs are rasterized as 8-bit grayscale anti-aliased bitmaps. + </constant> + <constant name="FONT_ANTIALIASING_LCD" value="2" enum="FontAntialiasing"> + Font glyphs are rasterized for LCD screens. + LCD sub-pixel layout is determined by the value of [code]gui/theme/lcd_subpixel_layout[/code] project settings. + LCD sub-pixel anti-aliasing mode is suitable only for rendering horizontal, unscaled text in 2D. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_NONE" value="0" enum="FontLCDSubpixelLayout"> + Unknown or unsupported sub-pixel layout, LCD sub-pixel anti-aliasing is disabled. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_HRGB" value="1" enum="FontLCDSubpixelLayout"> + Horizontal RGB sub-pixel layout. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_HBGR" value="2" enum="FontLCDSubpixelLayout"> + Horizontal BGR sub-pixel layout. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_VRGB" value="3" enum="FontLCDSubpixelLayout"> + Vertical RGB sub-pixel layout. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_VBGR" value="4" enum="FontLCDSubpixelLayout"> + Vertical BGR sub-pixel layout. + </constant> <constant name="DIRECTION_AUTO" value="0" enum="Direction"> Text direction is determined based on contents and current locale. </constant> @@ -1606,13 +1632,13 @@ Displays glyphs that are mapped to the first [member Label.visible_characters] or [member RichTextLabel.visible_characters] characters from the beginning of the text. </constant> <constant name="VC_GLYPHS_AUTO" value="2" enum="VisibleCharactersBehavior"> - Displays [member Label.percent_visible] or [member RichTextLabel.percent_visible] glyphs, starting from the left or from the right, depending on [member Control.layout_direction] value. + Displays [member Label.visible_ratio] or [member RichTextLabel.visible_ratio] glyphs, starting from the left or from the right, depending on [member Control.layout_direction] value. </constant> <constant name="VC_GLYPHS_LTR" value="3" enum="VisibleCharactersBehavior"> - Displays [member Label.percent_visible] or [member RichTextLabel.percent_visible] glyphs, starting from the left. + Displays [member Label.visible_ratio] or [member RichTextLabel.visible_ratio] glyphs, starting from the left. </constant> <constant name="VC_GLYPHS_RTL" value="4" enum="VisibleCharactersBehavior"> - Displays [member Label.percent_visible] or [member RichTextLabel.percent_visible] glyphs, starting from the right. + Displays [member Label.visible_ratio] or [member RichTextLabel.visible_ratio] glyphs, starting from the right. </constant> <constant name="OVERRUN_NO_TRIMMING" value="0" enum="OverrunBehavior"> No text trimming is performed. diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index 9eb7188846..23eb25dc10 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -91,6 +91,13 @@ Draws single glyph outline of size [param outline_size] into a canvas item at the position, using [param font_rid] at the size [param size]. </description> </method> + <method name="font_get_antialiasing" qualifiers="virtual const"> + <return type="int" enum="TextServer.FontAntialiasing" /> + <param index="0" name="font_rid" type="RID" /> + <description> + Returns font anti-aliasing mode. + </description> + </method> <method name="font_get_ascent" qualifiers="virtual const"> <return type="float" /> <param index="0" name="font_rid" type="RID" /> @@ -437,13 +444,6 @@ Returns [code]true[/code] if a Unicode [param char] is available in the font. </description> </method> - <method name="font_is_antialiased" qualifiers="virtual const"> - <return type="bool" /> - <param index="0" name="font_rid" type="RID" /> - <description> - Returns [code]true[/code] if font 8-bit anitialiased glyph rendering is supported and enabled. - </description> - </method> <method name="font_is_force_autohinter" qualifiers="virtual const"> <return type="bool" /> <param index="0" name="font_rid" type="RID" /> @@ -544,12 +544,12 @@ Renders the range of characters to the font cache texture. </description> </method> - <method name="font_set_antialiased" qualifiers="virtual"> + <method name="font_set_antialiasing" qualifiers="virtual"> <return type="void" /> <param index="0" name="font_rid" type="RID" /> - <param index="1" name="antialiased" type="bool" /> + <param index="1" name="antialiasing" type="int" enum="TextServer.FontAntialiasing" /> <description> - If set to [code]true[/code], 8-bit antialiased glyph rendering is used, otherwise 1-bit rendering is used. Used by dynamic fonts only. + Sets font anti-aliasing mode. </description> </method> <method name="font_set_ascent" qualifiers="virtual"> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index 5530759628..e76c696021 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -41,7 +41,7 @@ <return type="void" /> <param index="0" name="to_position" type="int" /> <description> - Adds a layer at the given position [param to_position] in the array. If [param to_position] is -1, adds it at the end of the array. + Adds a layer at the given position [param to_position] in the array. If [param to_position] is negative, the position is counted from the end, with [code]-1[/code] adding the layer at the end of the array. </description> </method> <method name="clear"> @@ -285,14 +285,16 @@ <param index="1" name="enabled" type="bool" /> <description> Enables or disables the layer [param layer]. A disabled layer is not processed at all (no rendering, no physics, etc...). + If [param layer] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_modulate"> <return type="void" /> <param index="0" name="layer" type="int" /> - <param index="1" name="enabled" type="Color" /> + <param index="1" name="modulate" type="Color" /> <description> Sets a layer's color. It will be multiplied by tile's color and TileMap's modulate. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_name"> @@ -301,6 +303,7 @@ <param index="1" name="name" type="String" /> <description> Sets a layer's name. This is mostly useful in the editor. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_y_sort_enabled"> @@ -310,6 +313,7 @@ <description> Enables or disables a layer's Y-sorting. If a layer is Y-sorted, the layer will behave as a CanvasItem node where each of its tile gets Y-sorted. Y-sorted layers should usually be on different Z-index values than not Y-sorted layers, otherwise, each of those layer will be Y-sorted as whole with the Y-sorted one. This is usually an undesired behvaior. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_y_sort_origin"> @@ -319,6 +323,7 @@ <description> Sets a layer's Y-sort origin value. This Y-sort origin value is added to each tile's Y-sort origin value. This allows, for example, to fake a different height level on each layer. This can be useful for top-down view games. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_z_index"> @@ -327,6 +332,7 @@ <param index="1" name="z_index" type="int" /> <description> Sets a layers Z-index value. This Z-index is added to each tile's Z-index value. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_pattern"> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 19fe2e2bfc..2197947126 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -304,7 +304,7 @@ <return type="Vector2" /> <param index="0" name="angle" type="float" /> <description> - Returns the vector rotated by [param angle] (in radians). See also [method @GlobalScope.deg2rad]. + Returns the vector rotated by [param angle] (in radians). See also [method @GlobalScope.deg_to_rad]. </description> </method> <method name="round" qualifiers="const"> diff --git a/doc/classes/VehicleBody3D.xml b/doc/classes/VehicleBody3D.xml index 08309a8ecc..e1689133de 100644 --- a/doc/classes/VehicleBody3D.xml +++ b/doc/classes/VehicleBody3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VehicleBody3D" inherits="RigidDynamicBody3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="VehicleBody3D" inherits="RigidBody3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Physics body that simulates the behavior of a car. </brief_description> @@ -13,14 +13,14 @@ </tutorials> <members> <member name="brake" type="float" setter="set_brake" getter="get_brake" default="0.0"> - Slows down the vehicle by applying a braking force. The vehicle is only slowed down if the wheels are in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidDynamicBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. + Slows down the vehicle by applying a braking force. The vehicle is only slowed down if the wheels are in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. </member> <member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0"> - Accelerates the vehicle by applying an engine force. The vehicle is only sped up if the wheels that have [member VehicleWheel3D.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. + Accelerates the vehicle by applying an engine force. The vehicle is only sped up if the wheels that have [member VehicleWheel3D.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. [b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. A negative value will result in the vehicle reversing. </member> - <member name="mass" type="float" setter="set_mass" getter="get_mass" overrides="RigidDynamicBody3D" default="40.0" /> + <member name="mass" type="float" setter="set_mass" getter="get_mass" overrides="RigidBody3D" default="40.0" /> <member name="steering" type="float" setter="set_steering" getter="get_steering" default="0.0"> The steering angle for the vehicle, in radians. Setting this to a non-zero value will result in the vehicle turning when it's moving. Wheels that have [member VehicleWheel3D.use_as_steering] set to [code]true[/code] will automatically be rotated. </member> diff --git a/doc/classes/VehicleWheel3D.xml b/doc/classes/VehicleWheel3D.xml index ac126f824e..827c7e8f57 100644 --- a/doc/classes/VehicleWheel3D.xml +++ b/doc/classes/VehicleWheel3D.xml @@ -39,7 +39,7 @@ </methods> <members> <member name="brake" type="float" setter="set_brake" getter="get_brake" default="0.0"> - Slows down the wheel by applying a braking force. The wheel is only slowed down if it is in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidDynamicBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. + Slows down the wheel by applying a braking force. The wheel is only slowed down if it is in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. </member> <member name="damping_compression" type="float" setter="set_damping_compression" getter="get_damping_compression" default="0.83"> The damping applied to the spring when the spring is being compressed. This value should be between 0.0 (no damping) and 1.0. A value of 0.0 means the car will keep bouncing as the spring keeps its energy. A good value for this is around 0.3 for a normal car, 0.5 for a race car. @@ -48,7 +48,7 @@ The damping applied to the spring when relaxing. This value should be between 0.0 (no damping) and 1.0. This value should always be slightly higher than the [member damping_compression] property. For a [member damping_compression] value of 0.3, try a relaxation value of 0.5. </member> <member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0"> - Accelerates the wheel by applying an engine force. The wheel is only sped up if it is in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. + Accelerates the wheel by applying an engine force. The wheel is only sped up if it is in contact with a surface. The [member RigidBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. [b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. A negative value will result in the wheel reversing. </member> @@ -56,7 +56,7 @@ The steering angle for the wheel, in radians. Setting this to a non-zero value will result in the vehicle turning when it's moving. </member> <member name="suspension_max_force" type="float" setter="set_suspension_max_force" getter="get_suspension_max_force" default="6000.0"> - The maximum force the spring can resist. This value should be higher than a quarter of the [member RigidDynamicBody3D.mass] of the [VehicleBody3D] or the spring will not carry the weight of the vehicle. Good results are often obtained by a value that is about 3× to 4× this number. + The maximum force the spring can resist. This value should be higher than a quarter of the [member RigidBody3D.mass] of the [VehicleBody3D] or the spring will not carry the weight of the vehicle. Good results are often obtained by a value that is about 3× to 4× this number. </member> <member name="suspension_stiffness" type="float" setter="set_suspension_stiffness" getter="get_suspension_stiffness" default="5.88"> This value defines the stiffness of the suspension. Use a value lower than 50 for an off-road car, a value between 50 and 100 for a race car and try something around 200 for something like a Formula 1 car. diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 93e7e20f5a..0071834ccd 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -266,7 +266,8 @@ <member name="snap_2d_vertices_to_pixel" type="bool" setter="set_snap_2d_vertices_to_pixel" getter="is_snap_2d_vertices_to_pixel_enabled" default="false"> </member> <member name="texture_mipmap_bias" type="float" setter="set_texture_mipmap_bias" getter="get_texture_mipmap_bias" default="0.0"> - Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member ProjectSettings.rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias. + Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). + Enabling temporal antialiasing ([member use_taa]) will automatically apply a [code]-0.5[/code] offset to this value, while enabling FXAA ([member screen_space_aa]) will automatically apply a [code]-0.25[/code] offset to this value. If both TAA and FXAA are enbled at the same time, an offset of [code]-0.75[/code] is applied to this value. [b]Note:[/b] If [member scaling_3d_scale] is lower than [code]1.0[/code] (exclusive), [member texture_mipmap_bias] is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]log2(scaling_3d_scale) + mipmap_bias[/code]. To control this property on the root viewport, set the [member ProjectSettings.rendering/textures/default_filters/texture_mipmap_bias] project setting. </member> diff --git a/doc/classes/VisibleOnScreenEnabler3D.xml b/doc/classes/VisibleOnScreenEnabler3D.xml index 5e03870005..a3f925ed3a 100644 --- a/doc/classes/VisibleOnScreenEnabler3D.xml +++ b/doc/classes/VisibleOnScreenEnabler3D.xml @@ -4,7 +4,7 @@ Enables certain nodes only when approximately visible. </brief_description> <description> - The VisibleOnScreenEnabler3D will disable [RigidDynamicBody3D] and [AnimationPlayer] nodes when they are not visible. It will only affect other nodes within the same scene as the VisibleOnScreenEnabler3D itself. + The VisibleOnScreenEnabler3D will disable [RigidBody3D] and [AnimationPlayer] nodes when they are not visible. It will only affect other nodes within the same scene as the VisibleOnScreenEnabler3D itself. If you just want to receive notifications, use [VisibleOnScreenNotifier3D] instead. [b]Note:[/b] VisibleOnScreenEnabler3D uses an approximate heuristic for performance reasons. It doesn't take walls and other occlusion into account. The heuristic is an implementation detail and may change in future versions. If you need precise visibility checking, use another method such as adding an [Area3D] node as a child of a [Camera3D] node and/or [method Vector3.dot]. [b]Note:[/b] VisibleOnScreenEnabler3D will not affect nodes added after scene initialization. diff --git a/doc/classes/VisualShader.xml b/doc/classes/VisualShader.xml index ecfb9000b2..a2089ae2b8 100644 --- a/doc/classes/VisualShader.xml +++ b/doc/classes/VisualShader.xml @@ -206,17 +206,19 @@ </constant> <constant name="VARYING_TYPE_FLOAT" value="0" enum="VaryingType"> </constant> - <constant name="VARYING_TYPE_VECTOR_2D" value="1" enum="VaryingType"> + <constant name="VARYING_TYPE_INT" value="1" enum="VaryingType"> </constant> - <constant name="VARYING_TYPE_VECTOR_3D" value="2" enum="VaryingType"> + <constant name="VARYING_TYPE_VECTOR_2D" value="2" enum="VaryingType"> </constant> - <constant name="VARYING_TYPE_VECTOR_4D" value="3" enum="VaryingType"> + <constant name="VARYING_TYPE_VECTOR_3D" value="3" enum="VaryingType"> </constant> - <constant name="VARYING_TYPE_COLOR" value="4" enum="VaryingType"> + <constant name="VARYING_TYPE_VECTOR_4D" value="4" enum="VaryingType"> </constant> - <constant name="VARYING_TYPE_TRANSFORM" value="5" enum="VaryingType"> + <constant name="VARYING_TYPE_BOOLEAN" value="5" enum="VaryingType"> </constant> - <constant name="VARYING_TYPE_MAX" value="6" enum="VaryingType"> + <constant name="VARYING_TYPE_TRANSFORM" value="6" enum="VaryingType"> + </constant> + <constant name="VARYING_TYPE_MAX" value="7" enum="VaryingType"> </constant> <constant name="NODE_ID_INVALID" value="-1"> </constant> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index ce7ad1e64e..2c0a694ef9 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -342,6 +342,9 @@ If [code]true[/code], the [Window] will be in exclusive mode. Exclusive windows are always on top of their parent and will block all input going to the parent [Window]. Needs [member transient] enabled to work. </member> + <member name="extend_to_title" type="bool" setter="set_flag" getter="get_flag" default="false"> + If [code]true[/code], the [Window] contents is expanded to the full size of the window, window title bar is transparent. + </member> <member name="max_size" type="Vector2i" setter="set_max_size" getter="get_max_size" default="Vector2i(0, 0)"> If non-zero, the [Window] can't be resized to be bigger than this size. [b]Note:[/b] This property will be ignored if the value is lower than [member min_size]. @@ -448,7 +451,7 @@ </signal> <signal name="theme_changed"> <description> - Emitted when the [member theme] is modified or changed to another [Theme]. + Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent. </description> </signal> <signal name="visibility_changed"> @@ -467,6 +470,13 @@ <constant name="NOTIFICATION_VISIBILITY_CHANGED" value="30"> Emitted when [Window]'s visibility changes, right before [signal visibility_changed]. </constant> + <constant name="NOTIFICATION_THEME_CHANGED" value="32"> + Sent when the node needs to refresh its theme items. This happens in one of the following cases: + - The [member theme] property is changed on this node or any of its ancestors. + - The [member theme_type_variation] property is changed on this node. + - The node enters the scene tree. + [b]Note:[/b] As an optimization, this notification won't be sent from changes that occur while this node is outside of the scene tree. Instead, all of the theme item updates can be applied at once when the node enters the scene tree. + </constant> <constant name="MODE_WINDOWED" value="0" enum="Mode"> Windowed mode, i.e. [Window] doesn't occupy whole screen (unless set to the size of the screen). </constant> @@ -503,7 +513,10 @@ <constant name="FLAG_POPUP" value="5" enum="Flags"> Whether the window is popup or a regular window. Set with [member popup_window]. </constant> - <constant name="FLAG_MAX" value="6" enum="Flags"> + <constant name="FLAG_EXTEND_TO_TITLE" value="6" enum="Flags"> + Window contents is expanded to the full size of the window, window title bar is transparent. + </constant> + <constant name="FLAG_MAX" value="7" enum="Flags"> Max value of the [enum Flags]. </constant> <constant name="CONTENT_SCALE_MODE_DISABLED" value="0" enum="ContentScaleMode"> diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 1f40641b80..f4c87da9e9 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -168,9 +168,8 @@ Error AudioDriverALSA::init() { return ERR_CANT_OPEN; } - active = false; - thread_exited = false; - exit_thread = false; + active.clear(); + exit_thread.clear(); Error err = init_device(); if (err == OK) { @@ -183,11 +182,11 @@ Error AudioDriverALSA::init() { void AudioDriverALSA::thread_func(void *p_udata) { AudioDriverALSA *ad = static_cast<AudioDriverALSA *>(p_udata); - while (!ad->exit_thread) { + while (!ad->exit_thread.is_set()) { ad->lock(); ad->start_counting_ticks(); - if (!ad->active) { + if (!ad->active.is_set()) { for (uint64_t i = 0; i < ad->period_size * ad->channels; i++) { ad->samples_out.write[i] = 0; } @@ -203,7 +202,7 @@ void AudioDriverALSA::thread_func(void *p_udata) { int todo = ad->period_size; int total = 0; - while (todo && !ad->exit_thread) { + while (todo && !ad->exit_thread.is_set()) { int16_t *src = (int16_t *)ad->samples_out.ptr(); int wrote = snd_pcm_writei(ad->pcm_handle, (void *)(src + (total * ad->channels)), todo); @@ -222,8 +221,8 @@ void AudioDriverALSA::thread_func(void *p_udata) { wrote = snd_pcm_recover(ad->pcm_handle, wrote, 0); if (wrote < 0) { ERR_PRINT("ALSA: Failed and can't recover: " + String(snd_strerror(wrote))); - ad->active = false; - ad->exit_thread = true; + ad->active.clear(); + ad->exit_thread.set(); } } } @@ -241,8 +240,8 @@ void AudioDriverALSA::thread_func(void *p_udata) { err = ad->init_device(); if (err != OK) { - ad->active = false; - ad->exit_thread = true; + ad->active.clear(); + ad->exit_thread.set(); } } } @@ -250,12 +249,10 @@ void AudioDriverALSA::thread_func(void *p_udata) { ad->stop_counting_ticks(); ad->unlock(); } - - ad->thread_exited = true; } void AudioDriverALSA::start() { - active = true; + active.set(); } int AudioDriverALSA::get_mix_rate() const { @@ -327,7 +324,7 @@ void AudioDriverALSA::finish_device() { } void AudioDriverALSA::finish() { - exit_thread = true; + exit_thread.set(); thread.wait_to_finish(); finish_device(); diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h index 3f9d9b33fb..fa1dba38ed 100644 --- a/drivers/alsa/audio_driver_alsa.h +++ b/drivers/alsa/audio_driver_alsa.h @@ -35,6 +35,7 @@ #include "core/os/mutex.h" #include "core/os/thread.h" +#include "core/templates/safe_refcount.h" #include "servers/audio_server.h" #include "asound-so_wrap.h" @@ -64,9 +65,8 @@ class AudioDriverALSA : public AudioDriver { snd_pcm_uframes_t period_size; int channels = 0; - bool active = false; - bool thread_exited = false; - mutable bool exit_thread = false; + SafeFlag active; + SafeFlag exit_thread; public: const char *get_name() const { diff --git a/drivers/alsamidi/midi_driver_alsamidi.cpp b/drivers/alsamidi/midi_driver_alsamidi.cpp index c334146dd2..d2a0076023 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.cpp +++ b/drivers/alsamidi/midi_driver_alsamidi.cpp @@ -79,7 +79,7 @@ void MIDIDriverALSAMidi::thread_func(void *p_udata) { int expected_size = 255; int bytes = 0; - while (!md->exit_thread) { + while (!md->exit_thread.is_set()) { int ret; md->lock(); @@ -149,14 +149,14 @@ Error MIDIDriverALSAMidi::open() { } snd_device_name_free_hint(hints); - exit_thread = false; + exit_thread.clear(); thread.start(MIDIDriverALSAMidi::thread_func, this); return OK; } void MIDIDriverALSAMidi::close() { - exit_thread = true; + exit_thread.set(); thread.wait_to_finish(); for (int i = 0; i < connected_inputs.size(); i++) { @@ -193,7 +193,7 @@ PackedStringArray MIDIDriverALSAMidi::get_connected_inputs() { } MIDIDriverALSAMidi::MIDIDriverALSAMidi() { - exit_thread = false; + exit_thread.clear(); } MIDIDriverALSAMidi::~MIDIDriverALSAMidi() { diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h index b0fa8c297a..ac3530b1b2 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.h +++ b/drivers/alsamidi/midi_driver_alsamidi.h @@ -36,6 +36,7 @@ #include "core/os/midi_driver.h" #include "core/os/mutex.h" #include "core/os/thread.h" +#include "core/templates/safe_refcount.h" #include "core/templates/vector.h" #include "../alsa/asound-so_wrap.h" @@ -47,7 +48,7 @@ class MIDIDriverALSAMidi : public MIDIDriver { Vector<snd_rawmidi_t *> connected_inputs; - bool exit_thread; + SafeFlag exit_thread; static void thread_func(void *p_udata); diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index 51fb1f99e0..1db85e2a60 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -215,6 +215,7 @@ OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon, } ad->lock(); + ad->start_counting_ticks(); AudioBufferList bufferList; bufferList.mNumberBuffers = 1; @@ -237,6 +238,7 @@ OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon, ERR_PRINT("AudioUnitRender failed, code: " + itos(result)); } + ad->stop_counting_ticks(); ad->unlock(); return result; diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 28802f571c..b397d0c665 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -322,6 +322,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou RID prev_material; uint32_t index = 0; GLES3::CanvasShaderData::BlendMode last_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX; + Color last_blend_color; GLES3::CanvasShaderData *shader_data_cache = nullptr; state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE); @@ -378,8 +379,80 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX; - if (last_blend_mode != blend_mode) { - if (last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) { + _render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index, blend_mode, last_blend_mode, last_blend_color); + } + // Render last command + _render_batch(index); +} + +void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index, GLES3::CanvasShaderData::BlendMode p_blend_mode, GLES3::CanvasShaderData::BlendMode &r_last_blend_mode, Color &r_last_blend_color) { + // Used by Polygon and Mesh. + static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP }; + + RS::CanvasItemTextureFilter current_filter = state.default_filter; + RS::CanvasItemTextureRepeat current_repeat = state.default_repeat; + + if (p_item->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { + current_filter = p_item->texture_filter; + } + + if (p_item->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { + current_repeat = p_item->texture_repeat; + } + + Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; + Transform2D draw_transform; // Used by transform command + + Color base_color = p_item->final_modulate; + + uint32_t base_flags = 0; + + bool reclip = false; + + bool skipping = false; + + const Item::Command *c = p_item->commands; + while (c) { + if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) { + c = c->next; + continue; + } + + if (c->type != Item::Command::TYPE_MESH) { + // For Meshes, this gets updated below. + _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world); + } + + for (int i = 0; i < 4; i++) { + state.instance_data_array[r_index].modulation[i] = 0.0; + state.instance_data_array[r_index].ninepatch_margins[i] = 0.0; + state.instance_data_array[r_index].src_rect[i] = 0.0; + state.instance_data_array[r_index].dst_rect[i] = 0.0; + state.instance_data_array[r_index].lights[i] = uint32_t(0); + } + state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0; + state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0; + + state.instance_data_array[r_index].pad[0] = 0.0; + state.instance_data_array[r_index].pad[1] = 0.0; + + state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config + + GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode; + Color blend_color; + + if (c->type == Item::Command::TYPE_RECT) { + const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c); + if (rect->flags & CANVAS_RECT_LCD) { + blend_mode = GLES3::CanvasShaderData::BLEND_MODE_LCD; + blend_color = rect->modulate; + } + } + + if (r_last_blend_mode != blend_mode || r_last_blend_color != blend_color) { + _render_batch(r_index); + + if (r_last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) { // re-enable it glEnable(GL_BLEND); } else if (blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) { @@ -392,6 +465,16 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou // Nothing to do here. } break; + case GLES3::CanvasShaderData::BLEND_MODE_LCD: { + glBlendEquation(GL_FUNC_ADD); + if (state.transparent_render_target) { + glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE); + } + glBlendColor(blend_color.r, blend_color.g, blend_color.b, blend_color.a); + + } break; case GLES3::CanvasShaderData::BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); if (state.transparent_render_target) { @@ -437,68 +520,10 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou } break; } - last_blend_mode = blend_mode; - } - - _render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index); - } - // Render last command - _render_batch(index); -} - -void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index) { - // Used by Polygon and Mesh. - static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP }; - - RS::CanvasItemTextureFilter current_filter = state.default_filter; - RS::CanvasItemTextureRepeat current_repeat = state.default_repeat; - - if (p_item->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { - current_filter = p_item->texture_filter; - } - - if (p_item->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { - current_repeat = p_item->texture_repeat; - } - - Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; - Transform2D draw_transform; // Used by transform command - - Color base_color = p_item->final_modulate; - - uint32_t base_flags = 0; - - bool reclip = false; - - bool skipping = false; - - const Item::Command *c = p_item->commands; - while (c) { - if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) { - c = c->next; - continue; - } - - if (c->type != Item::Command::TYPE_MESH) { - // For Meshes, this gets updated below. - _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world); + r_last_blend_mode = blend_mode; + r_last_blend_color = blend_color; } - for (int i = 0; i < 4; i++) { - state.instance_data_array[r_index].modulation[i] = 0.0; - state.instance_data_array[r_index].ninepatch_margins[i] = 0.0; - state.instance_data_array[r_index].src_rect[i] = 0.0; - state.instance_data_array[r_index].dst_rect[i] = 0.0; - state.instance_data_array[r_index].lights[i] = uint32_t(0); - } - state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0; - state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0; - - state.instance_data_array[r_index].pad[0] = 0.0; - state.instance_data_array[r_index].pad[1] = 0.0; - - state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config - switch (c->type) { case Item::Command::TYPE_RECT: { const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c); @@ -569,6 +594,8 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item state.instance_data_array[r_index].msdf[1] = rect->outline; // Outline size. state.instance_data_array[r_index].msdf[2] = 0.f; // Reserved. state.instance_data_array[r_index].msdf[3] = 0.f; // Reserved. + } else if (rect->flags & CANVAS_RECT_LCD) { + state.instance_data_array[r_index].flags |= FLAGS_USE_LCD; } state.instance_data_array[r_index].modulation[0] = rect->modulate.r * base_color.r; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index f920e37130..372ac00493 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -73,6 +73,7 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender { FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), FLAGS_USE_MSDF = (1 << 28), + FLAGS_USE_LCD = (1 << 29), }; enum { @@ -249,7 +250,7 @@ public: 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 _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false); - void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index); + void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index, GLES3::CanvasShaderData::BlendMode p_blend_mode, GLES3::CanvasShaderData::BlendMode &r_last_blend_mode, Color &r_last_blend_color); void _render_batch(uint32_t &p_max_index); void _bind_instance_data_buffer(uint32_t p_max_index); void _allocate_instance_data_buffer(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 9bbe960d86..cb479dda39 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -648,7 +648,7 @@ void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const Pag float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); if (angular_diameter > 0.0) { - angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); } else { angular_diameter = 0.0; } @@ -1518,7 +1518,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b light_data.color[2] = linear_col.b; float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); - light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset + light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR); @@ -1645,7 +1645,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION); float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE); - light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle)); + light_data.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle)); light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 4df818cd4c..5ec25327be 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -473,7 +473,13 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - + } else if (bool(draw_data[draw_data_instance].flags & FLAGS_USE_LCD)) { + vec4 lcd_sample = texture(color_texture, uv); + if (lcd_sample.a == 1.0) { + color.rgb = lcd_sample.rgb * color.a; + } else { + color = vec4(0.0, 0.0, 0.0, 0.0); + } } else { #else { diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl index 852dccf415..6b61fe9375 100644 --- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl +++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl @@ -25,6 +25,7 @@ #define FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 27) #define FLAGS_USE_MSDF uint(1 << 28) +#define FLAGS_USE_LCD uint(1 << 29) // must be always 128 bytes long struct DrawData { diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index 2e4bfdc15b..e2781bfbc0 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -318,7 +318,7 @@ AABB LightStorage::light_get_aabb(RID p_light) const { switch (light->type) { case RS::LIGHT_SPOT: { float len = light->param[RS::LIGHT_PARAM_RANGE]; - float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; + float size = Math::tan(Math::deg_to_rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); }; case RS::LIGHT_OMNI: { diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index d135357f6a..a2a7554821 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -142,6 +142,7 @@ struct CanvasShaderData : public ShaderData { BLEND_MODE_MUL, BLEND_MODE_PMALPHA, BLEND_MODE_DISABLED, + BLEND_MODE_LCD, }; bool valid; diff --git a/drivers/png/SCsub b/drivers/png/SCsub index 39d296e7cf..ad7aaf1ee8 100644 --- a/drivers/png/SCsub +++ b/drivers/png/SCsub @@ -37,7 +37,7 @@ if env["builtin_libpng"]: import os # Enable ARM NEON instructions on 32-bit Android to compile more optimized code. - use_neon = "android_arch" in env and env["android_arch"] == "armv7" and os.name != "nt" + use_neon = env["platform"] == "android" and env["arch"] == "arm32" and os.name != "nt" if use_neon: env_png.Append(CPPDEFINES=[("PNG_ARM_NEON_OPT", 2)]) else: diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index 917bfec574..8d2f8a7ed6 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -36,7 +36,7 @@ #include <string.h> -Error ImageLoaderPNG::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) { +Error ImageLoaderPNG::load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale) { const uint64_t buffer_size = f->get_length(); Vector<uint8_t> file_buffer; Error err = file_buffer.resize(buffer_size); @@ -48,7 +48,7 @@ Error ImageLoaderPNG::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_f f->get_buffer(writer, buffer_size); } const uint8_t *reader = file_buffer.ptr(); - return PNGDriverCommon::png_to_image(reader, buffer_size, p_force_linear, p_image); + return PNGDriverCommon::png_to_image(reader, buffer_size, p_flags & FLAG_FORCE_LINEAR, p_image); } void ImageLoaderPNG::get_recognized_extensions(List<String> *p_extensions) const { diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index 9bcfb720d3..91c3c8925f 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -40,7 +40,7 @@ private: static Ref<Image> load_mem_png(const uint8_t *p_png, int p_size); public: - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale); + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderPNG(); }; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index b18d383119..b25cf1d5b4 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -285,9 +285,8 @@ Error AudioDriverPulseAudio::init() { return ERR_CANT_OPEN; } - active = false; - thread_exited = false; - exit_thread = false; + active.clear(); + exit_thread.clear(); mix_rate = GLOBAL_GET("audio/driver/mix_rate"); @@ -384,7 +383,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { size_t avail_bytes = 0; uint64_t default_device_msec = OS::get_singleton()->get_ticks_msec(); - while (!ad->exit_thread) { + while (!ad->exit_thread.is_set()) { size_t read_bytes = 0; size_t written_bytes = 0; @@ -392,7 +391,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { ad->lock(); ad->start_counting_ticks(); - if (!ad->active) { + if (!ad->active.is_set()) { ad->samples_out.fill(0); } else { ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw()); @@ -462,8 +461,8 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { err = ad->init_device(); if (err != OK) { - ad->active = false; - ad->exit_thread = true; + ad->active.clear(); + ad->exit_thread.set(); break; } } @@ -501,8 +500,8 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { Error err = ad->init_device(); if (err != OK) { ERR_PRINT("PulseAudio: init_device error"); - ad->active = false; - ad->exit_thread = true; + ad->active.clear(); + ad->exit_thread.set(); break; } @@ -555,8 +554,8 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { err = ad->capture_init_device(); if (err != OK) { - ad->active = false; - ad->exit_thread = true; + ad->active.clear(); + ad->exit_thread.set(); break; } } @@ -571,12 +570,10 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { OS::get_singleton()->delay_usec(1000); } } - - ad->thread_exited = true; } void AudioDriverPulseAudio::start() { - active = true; + active.set(); } int AudioDriverPulseAudio::get_mix_rate() const { @@ -661,7 +658,7 @@ void AudioDriverPulseAudio::finish() { return; } - exit_thread = true; + exit_thread.set(); thread.wait_to_finish(); finish_device(); diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 27c684578e..85e328b49f 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -35,6 +35,7 @@ #include "core/os/mutex.h" #include "core/os/thread.h" +#include "core/templates/safe_refcount.h" #include "servers/audio_server.h" #include "pulse-so_wrap.h" @@ -70,9 +71,8 @@ class AudioDriverPulseAudio : public AudioDriver { PackedStringArray pa_devices; PackedStringArray pa_rec_devices; - bool active = false; - bool thread_exited = false; - mutable bool exit_thread = false; + SafeFlag active; + SafeFlag exit_thread; float latency = 0; diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 2debba1b83..f2d78636d7 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -7543,6 +7543,16 @@ RenderingDeviceVulkan::DrawList *RenderingDeviceVulkan::_get_draw_list_ptr(DrawL } } +void RenderingDeviceVulkan::draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) { + DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_COND(!dl); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); +#endif + + vkCmdSetBlendConstants(dl->command_buffer, p_color.components); +} + void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) { DrawList *dl = _get_draw_list_ptr(p_list); ERR_FAIL_COND(!dl); diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 6572de7c52..6007e1ab4d 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -1155,6 +1155,7 @@ public: virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); + virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color); virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline); virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index); virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array); diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index 8f5e35b251..fb90b776cf 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -501,11 +501,11 @@ Error AudioDriverWASAPI::init_capture_device(bool reinit) { } Error AudioDriverWASAPI::audio_device_finish(AudioDeviceWASAPI *p_device) { - if (p_device->active) { + if (p_device->active.is_set()) { if (p_device->audio_client) { p_device->audio_client->Stop(); } - p_device->active = false; + p_device->active.clear(); } SAFE_RELEASE(p_device->audio_client) @@ -533,8 +533,7 @@ Error AudioDriverWASAPI::init() { ERR_PRINT("WASAPI: init_render_device error"); } - exit_thread = false; - thread_exited = false; + exit_thread.clear(); thread.start(thread_func, this); @@ -684,7 +683,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { uint32_t avail_frames = 0; uint32_t write_ofs = 0; - while (!ad->exit_thread) { + while (!ad->exit_thread.is_set()) { uint32_t read_frames = 0; uint32_t written_frames = 0; @@ -692,7 +691,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { ad->lock(); ad->start_counting_ticks(); - if (ad->audio_output.active) { + if (ad->audio_output.active.is_set()) { ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw()); } else { for (int i = 0; i < ad->samples_in.size(); i++) { @@ -758,7 +757,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { } } else { ERR_PRINT("WASAPI: Get buffer error"); - ad->exit_thread = true; + ad->exit_thread.set(); } } } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { @@ -807,7 +806,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { write_ofs = 0; } - if (ad->audio_input.active) { + if (ad->audio_input.active.is_set()) { UINT32 packet_length = 0; BYTE *data; UINT32 num_frames_available; @@ -886,8 +885,6 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { OS::get_singleton()->delay_usec(1000); } } - - ad->thread_exited = true; } void AudioDriverWASAPI::start() { @@ -896,7 +893,7 @@ void AudioDriverWASAPI::start() { if (hr != S_OK) { ERR_PRINT("WASAPI: Start failed"); } else { - audio_output.active = true; + audio_output.active.set(); } } } @@ -910,7 +907,7 @@ void AudioDriverWASAPI::unlock() { } void AudioDriverWASAPI::finish() { - exit_thread = true; + exit_thread.set(); thread.wait_to_finish(); finish_capture_device(); @@ -924,19 +921,19 @@ Error AudioDriverWASAPI::capture_start() { return err; } - if (audio_input.active) { + if (audio_input.active.is_set()) { return FAILED; } audio_input.audio_client->Start(); - audio_input.active = true; + audio_input.active.set(); return OK; } Error AudioDriverWASAPI::capture_stop() { - if (audio_input.active) { + if (audio_input.active.is_set()) { audio_input.audio_client->Stop(); - audio_input.active = false; + audio_input.active.clear(); return OK; } diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index d71e2e914b..c30a54c042 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -35,6 +35,7 @@ #include "core/os/mutex.h" #include "core/os/thread.h" +#include "core/templates/safe_refcount.h" #include "servers/audio_server.h" #include <audioclient.h> @@ -48,7 +49,7 @@ class AudioDriverWASAPI : public AudioDriver { IAudioClient *audio_client = nullptr; IAudioRenderClient *render_client = nullptr; IAudioCaptureClient *capture_client = nullptr; - bool active = false; + SafeFlag active; WORD format_tag = 0; WORD bits_per_sample = 0; @@ -76,8 +77,7 @@ class AudioDriverWASAPI : public AudioDriver { float real_latency = 0.0; bool using_audio_client_3 = false; - bool thread_exited = false; - mutable bool exit_thread = false; + SafeFlag exit_thread; static _FORCE_INLINE_ void write_sample(WORD format_tag, int bits_per_sample, BYTE *buffer, int i, int32_t sample); static _FORCE_INLINE_ int32_t read_sample(WORD format_tag, int bits_per_sample, BYTE *buffer, int i); diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp index c32c7cf1e5..6c48c1a844 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.cpp +++ b/drivers/xaudio2/audio_driver_xaudio2.cpp @@ -38,9 +38,8 @@ const char *AudioDriverXAudio2::get_name() const { } Error AudioDriverXAudio2::init() { - active = false; - thread_exited = false; - exit_thread = false; + active.clear(); + exit_thread.clear(); pcm_open = false; samples_in = nullptr; @@ -86,17 +85,19 @@ Error AudioDriverXAudio2::init() { void AudioDriverXAudio2::thread_func(void *p_udata) { AudioDriverXAudio2 *ad = static_cast<AudioDriverXAudio2 *>(p_udata); - while (!ad->exit_thread) { - if (!ad->active) { + while (!ad->exit_thread.is_set()) { + if (!ad->active.is_set()) { for (int i = 0; i < AUDIO_BUFFERS; i++) { ad->xaudio_buffer[i].Flags = XAUDIO2_END_OF_STREAM; } } else { ad->lock(); + ad->start_counting_ticks(); ad->audio_server_process(ad->buffer_size, ad->samples_in); + ad->stop_counting_ticks(); ad->unlock(); for (unsigned int i = 0; i < ad->buffer_size * ad->channels; i++) { @@ -117,12 +118,10 @@ void AudioDriverXAudio2::thread_func(void *p_udata) { } } } - - ad->thread_exited = true; } void AudioDriverXAudio2::start() { - active = true; + active.set(); HRESULT hr = source_voice->Start(0); ERR_FAIL_COND_MSG(hr != S_OK, "Error starting XAudio2 driver. Error code: " + itos(hr) + "."); } @@ -154,7 +153,7 @@ void AudioDriverXAudio2::unlock() { } void AudioDriverXAudio2::finish() { - exit_thread = true; + exit_thread.set(); thread.wait_to_finish(); if (source_voice) { diff --git a/drivers/xaudio2/audio_driver_xaudio2.h b/drivers/xaudio2/audio_driver_xaudio2.h index 81432ceb8e..0f64d54a1f 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.h +++ b/drivers/xaudio2/audio_driver_xaudio2.h @@ -33,6 +33,7 @@ #include "core/os/mutex.h" #include "core/os/thread.h" +#include "core/templates/safe_refcount.h" #include "servers/audio_server.h" #include <mmsystem.h> @@ -77,9 +78,8 @@ class AudioDriverXAudio2 : public AudioDriver { int channels = 0; - bool active = false; - bool thread_exited = false; - mutable bool exit_thread = false; + SafeFlag active; + SafeFlag exit_thread; bool pcm_open = false; WAVEFORMATEX wave_format = { 0 }; diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 462f314471..648e950fd4 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -1061,6 +1061,9 @@ void ActionMapEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { action_list_search->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + if (!actions_cache.is_empty()) { + update_action_list(); + } } break; } } diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 5df413f0a7..86d08de430 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -2122,11 +2122,12 @@ void AnimationTrackEdit::_notification(int p_what) { get_theme_icon(SNAME("InterpWrapClamp"), SNAME("EditorIcons")), get_theme_icon(SNAME("InterpWrapLoop"), SNAME("EditorIcons")), }; - Ref<Texture2D> interp_icon[4] = { + Ref<Texture2D> interp_icon[5] = { get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")), get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")), get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")), - get_theme_icon(SNAME("InterpCubicInTime"), SNAME("EditorIcons")) + get_theme_icon(SNAME("InterpLinearAngle"), SNAME("EditorIcons")), + get_theme_icon(SNAME("InterpCubicAngle"), SNAME("EditorIcons")), }; Ref<Texture2D> cont_icon[4] = { get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), @@ -2849,7 +2850,23 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { menu->add_icon_item(get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")), TTR("Nearest"), MENU_INTERPOLATION_NEAREST); menu->add_icon_item(get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")), TTR("Linear"), MENU_INTERPOLATION_LINEAR); menu->add_icon_item(get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")), TTR("Cubic"), MENU_INTERPOLATION_CUBIC); - menu->add_icon_item(get_theme_icon(SNAME("InterpCubicInTime"), SNAME("EditorIcons")), TTR("CubicInTime"), MENU_INTERPOLATION_CUBIC_IN_TIME); + // Check is angle property. + AnimationPlayerEditor *ape = AnimationPlayerEditor::get_singleton(); + if (ape) { + AnimationPlayer *ap = ape->get_player(); + if (ap) { + NodePath path = animation->track_get_path(track); + Node *nd = ap->get_node(ap->get_root())->get_node(NodePath(path.get_concatenated_names())); + StringName prop = path.get_concatenated_subnames(); + PropertyInfo prop_info; + ClassDB::get_property_info(nd->get_class(), prop, &prop_info); + bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.find("radians") != -1; + if (is_angle) { + menu->add_icon_item(get_theme_icon(SNAME("InterpLinearAngle"), SNAME("EditorIcons")), TTR("Linear Angle"), MENU_INTERPOLATION_LINEAR_ANGLE); + menu->add_icon_item(get_theme_icon(SNAME("InterpCubicAngle"), SNAME("EditorIcons")), TTR("Cubic Angle"), MENU_INTERPOLATION_CUBIC_ANGLE); + } + } + } menu->reset_size(); Vector2 popup_pos = get_screen_position() + interp_mode_rect.position + Vector2(0, interp_mode_rect.size.height); @@ -3191,7 +3208,8 @@ void AnimationTrackEdit::_menu_selected(int p_index) { case MENU_INTERPOLATION_NEAREST: case MENU_INTERPOLATION_LINEAR: case MENU_INTERPOLATION_CUBIC: - case MENU_INTERPOLATION_CUBIC_IN_TIME: { + case MENU_INTERPOLATION_LINEAR_ANGLE: + case MENU_INTERPOLATION_CUBIC_ANGLE: { Animation::InterpolationType interp_mode = Animation::InterpolationType(p_index - MENU_INTERPOLATION_NEAREST); undo_redo->create_action(TTR("Change Animation Interpolation Mode")); undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", track, interp_mode); @@ -6045,6 +6063,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { Vector<int> keys = E->value; int len = keys.size() - 1; + // Special case for angle interpolation. + bool is_using_angle = animation->track_get_interpolation_type(track) == Animation::INTERPOLATION_LINEAR_ANGLE || animation->track_get_interpolation_type(track) == Animation::INTERPOLATION_CUBIC_ANGLE; + // Make insert queue. Vector<Pair<double, Variant>> insert_queue; for (int i = 0; i < len; i++) { @@ -6054,6 +6075,12 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { double to_t = animation->track_get_key_time(track, keys[i + 1]); Variant from_v = animation->track_get_key_value(track, keys[i]); Variant to_v = animation->track_get_key_value(track, keys[i + 1]); + if (is_using_angle) { + real_t a = from_v; + real_t b = to_v; + real_t to_diff = fmod(b - a, Math_TAU); + to_v = a + fmod(2.0 * to_diff, Math_TAU) - to_diff; + } Variant delta_v; Variant::sub(to_v, from_v, delta_v); double duration = to_t - from_t; @@ -6195,10 +6222,14 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { do_bake |= b_bs && type == Animation::TYPE_BLEND_SHAPE; do_bake |= b_v && type == Animation::TYPE_VALUE; if (do_bake && !animation->track_is_compressed(i)) { - if (animation->track_get_interpolation_type(i) == Animation::INTERPOLATION_NEAREST) { - continue; // Nearest interpolation cannot be baked. + Animation::InterpolationType it = animation->track_get_interpolation_type(i); + if (it == Animation::INTERPOLATION_NEAREST) { + continue; // Nearest and Angle interpolation cannot be baked. } + // Special case for angle interpolation. + bool is_using_angle = it == Animation::INTERPOLATION_LINEAR_ANGLE || it == Animation::INTERPOLATION_CUBIC_ANGLE; + // Make insert queue. Vector<Pair<double, Variant>> insert_queue; @@ -6262,7 +6293,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { } // Insert keys. - undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", i, Animation::INTERPOLATION_LINEAR); + undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", i, is_using_angle ? Animation::INTERPOLATION_LINEAR_ANGLE : Animation::INTERPOLATION_LINEAR); for (int j = insert_queue.size() - 1; j >= 0; j--) { undo_redo->add_do_method(animation.ptr(), "track_insert_key", i, insert_queue[j].first, insert_queue[j].second); undo_redo->add_undo_method(animation.ptr(), "track_remove_key", i, j); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 9cf3269fd0..990ee5f6be 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -144,7 +144,8 @@ class AnimationTrackEdit : public Control { MENU_INTERPOLATION_NEAREST, MENU_INTERPOLATION_LINEAR, MENU_INTERPOLATION_CUBIC, - MENU_INTERPOLATION_CUBIC_IN_TIME, + MENU_INTERPOLATION_LINEAR_ANGLE, + MENU_INTERPOLATION_CUBIC_ANGLE, MENU_LOOP_WRAP, MENU_LOOP_CLAMP, MENU_KEY_INSERT, @@ -501,7 +502,7 @@ class AnimationTrackEditor : public VBoxContainer { NodePath full_path; NodePath base_path; Animation::TrackType track_type = Animation::TYPE_ANIMATION; - Animation::InterpolationType interp_type = Animation::INTERPOLATION_CUBIC_IN_TIME; + Animation::InterpolationType interp_type = Animation::INTERPOLATION_CUBIC_ANGLE; Animation::UpdateMode update_mode = Animation::UPDATE_CAPTURE; Animation::LoopMode loop_mode = Animation::LOOP_PINGPONG; bool loop_wrap = false; diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 6c86b341da..dc8a64d904 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -840,6 +840,9 @@ void ConnectionsDock::_handle_signal_menu_option(int p_option) { disconnect_all_dialog->set_text(vformat(TTR("Are you sure you want to remove all connections from the \"%s\" signal?"), signal_name)); disconnect_all_dialog->popup_centered(); } break; + case COPY_NAME: { + DisplayServer::get_singleton()->clipboard_set(item->get_metadata(0).operator Dictionary()["name"]); + } break; } } @@ -1164,6 +1167,7 @@ ConnectionsDock::ConnectionsDock() { signal_menu->connect("id_pressed", callable_mp(this, &ConnectionsDock::_handle_signal_menu_option)); signal_menu->add_item(TTR("Connect..."), CONNECT); signal_menu->add_item(TTR("Disconnect All"), DISCONNECT_ALL); + signal_menu->add_item(TTR("Copy Name"), COPY_NAME); slot_menu = memnew(PopupMenu); add_child(slot_menu); diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h index 7e7192019b..352c5c99d6 100644 --- a/editor/connections_dialog.h +++ b/editor/connections_dialog.h @@ -177,13 +177,14 @@ class ConnectionsDock : public VBoxContainer { //Right-click Pop-up Menu Options. enum SignalMenuOption { CONNECT, - DISCONNECT_ALL + DISCONNECT_ALL, + COPY_NAME, }; enum SlotMenuOption { EDIT, GO_TO_SCRIPT, - DISCONNECT + DISCONNECT, }; Node *selected_node = nullptr; diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index a02051c8ee..fffe77f1c4 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -37,7 +37,7 @@ #include "scene/resources/default_theme/default_theme.h" #include "scene/resources/font.h" -Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { +Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { Ref<FontFile> font; font.instantiate(); @@ -45,7 +45,7 @@ Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hin font->set_data(data); font->set_multichannel_signed_distance_field(p_msdf); - font->set_antialiased(p_aa); + font->set_antialiasing(p_aa); font->set_hinting(p_hinting); font->set_force_autohinter(p_autohint); font->set_subpixel_positioning(p_font_subpixel_positioning); @@ -57,13 +57,13 @@ Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hin return font; } -Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { +Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { Ref<FontFile> font; font.instantiate(); font->set_data_ptr(p_data, p_size); font->set_multichannel_signed_distance_field(p_msdf); - font->set_antialiased(p_aa); + font->set_antialiasing(p_aa); font->set_hinting(p_hinting); font->set_force_autohinter(p_autohint); font->set_subpixel_positioning(p_font_subpixel_positioning); @@ -91,7 +91,7 @@ Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, Ty void editor_register_fonts(Ref<Theme> p_theme) { Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - bool font_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/font_antialiased"); + TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)EditorSettings::get_singleton()->get("interface/editor/font_antialiasing"); int font_hinting_setting = (int)EditorSettings::get_singleton()->get("interface/editor/font_hinting"); TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EditorSettings::get_singleton()->get("interface/editor/font_subpixel_positioning"); @@ -123,47 +123,47 @@ void editor_register_fonts(Ref<Theme> p_theme) { const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE; const float embolden_strength = 0.6; - Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false); - Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true); + Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false); + Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, true); TypedArray<Font> fallbacks; - Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); default_font->set_fallbacks(fallbacks); default_font_msdf->set_fallbacks(fallbacks); - Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false); - Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true); + Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false); + Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, true); TypedArray<Font> fallbacks_bold; - Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold); Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold); default_font_bold->set_fallbacks(fallbacks_bold); default_font_bold_msdf->set_fallbacks(fallbacks_bold); - Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning); default_font_mono->set_fallbacks(fallbacks); // Init base font configs and load custom fonts. @@ -174,7 +174,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> default_fc; default_fc.instantiate(); if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font); @@ -191,7 +191,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> default_fc_msdf; default_fc_msdf.instantiate(); if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_msdf); @@ -208,7 +208,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> bold_fc; bold_fc.instantiate(); if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_bold); @@ -216,7 +216,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { } bold_fc->set_base_font(custom_font); } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_bold); @@ -234,7 +234,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> bold_fc_msdf; bold_fc_msdf.instantiate(); if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_bold_msdf); @@ -242,7 +242,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { } bold_fc_msdf->set_base_font(custom_font); } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_bold_msdf); @@ -260,7 +260,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> mono_fc; mono_fc.instantiate(); if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_mono); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 73683eeb73..1095321053 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -340,6 +340,8 @@ void EditorProperty::_notification(int p_what) { draw_string(font, Point2(ofs, v_ofs + font->get_ascent(font_size)), label, HORIZONTAL_ALIGNMENT_LEFT, text_limit, font_size, color); } + ofs = size.width; + if (keying) { Ref<Texture2D> key; @@ -349,7 +351,7 @@ void EditorProperty::_notification(int p_what) { key = get_theme_icon(SNAME("Key"), SNAME("EditorIcons")); } - ofs = size.width - key->get_width() - get_theme_constant(SNAME("hseparator"), SNAME("Tree")); + ofs -= key->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree")); Color color2(1, 1, 1); if (keying_hover) { @@ -373,7 +375,7 @@ void EditorProperty::_notification(int p_what) { close = get_theme_icon(SNAME("Close"), SNAME("EditorIcons")); - ofs = size.width - close->get_width() - get_theme_constant(SNAME("hseparator"), SNAME("Tree")); + ofs -= close->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree")); Color color2(1, 1, 1); if (delete_hover) { @@ -894,14 +896,9 @@ static Control *make_help_bit(const String &p_text, bool p_property) { } Control *EditorProperty::make_custom_tooltip(const String &p_text) const { - tooltip_text = p_text; return make_help_bit(p_text, true); } -String EditorProperty::get_tooltip_text() const { - return tooltip_text; -} - void EditorProperty::menu_option(int p_option) { switch (p_option) { case MENU_COPY_PROPERTY: { @@ -949,7 +946,6 @@ void EditorProperty::_bind_methods() { ClassDB::bind_method(D_METHOD("get_edited_property"), &EditorProperty::get_edited_property); ClassDB::bind_method(D_METHOD("get_edited_object"), &EditorProperty::get_edited_object); - ClassDB::bind_method(D_METHOD("get_tooltip_text"), &EditorProperty::get_tooltip_text); ClassDB::bind_method(D_METHOD("update_property"), &EditorProperty::update_property); ClassDB::bind_method(D_METHOD("add_focusable", "control"), &EditorProperty::add_focusable); @@ -1127,7 +1123,6 @@ void EditorInspectorCategory::_notification(int p_what) { } Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) const { - tooltip_text = p_text; return make_help_bit(p_text, false); } @@ -1146,14 +1141,6 @@ Size2 EditorInspectorCategory::get_minimum_size() const { return ms; } -void EditorInspectorCategory::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_tooltip_text"), &EditorInspectorCategory::get_tooltip_text); -} - -String EditorInspectorCategory::get_tooltip_text() const { - return tooltip_text; -} - EditorInspectorCategory::EditorInspectorCategory() { } diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 905e13b3a9..474078853a 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -117,8 +117,6 @@ private: Control *bottom_editor = nullptr; PopupMenu *menu = nullptr; - mutable String tooltip_text; - HashMap<StringName, Variant> cache; GDVIRTUAL0(_update_property) @@ -199,8 +197,6 @@ public: void set_object_and_property(Object *p_object, const StringName &p_property); virtual Control *make_custom_tooltip(const String &p_text) const override; - String get_tooltip_text() const; - void set_draw_top_bg(bool p_draw) { draw_top_bg = p_draw; } bool can_revert_to_default() const { return can_revert; } @@ -254,18 +250,13 @@ class EditorInspectorCategory : public Control { Ref<Texture2D> icon; String label; - mutable String tooltip_text; - protected: void _notification(int p_what); - static void _bind_methods(); public: virtual Size2 get_minimum_size() const override; virtual Control *make_custom_tooltip(const String &p_text) const override; - String get_tooltip_text() const; - EditorInspectorCategory(); }; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index dc03a1f270..f540e2b2a1 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -252,6 +252,11 @@ void EditorLog::_rebuild_log() { } void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) { + if (!is_inside_tree()) { + // The log will be built all at once when it enters the tree and has its theme items. + return; + } + // Only add the message to the log if it passes the filters. bool filter_active = type_filter_map[p_message.type]->is_active(); String search_text = search_box->get_text(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4aedd98bd3..375aa26de9 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2432,7 +2432,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { String run_filename; - if (p_current || (editor_data.get_edited_scene_root() && !p_custom.is_empty() && p_custom == editor_data.get_edited_scene_root()->get_scene_file_path())) { + if ((p_current && p_custom.is_empty()) || (editor_data.get_edited_scene_root() && !p_custom.is_empty() && p_custom == editor_data.get_edited_scene_root()->get_scene_file_path())) { Node *scene = editor_data.get_edited_scene_root(); if (!scene) { @@ -2494,15 +2494,19 @@ void EditorNode::_run(bool p_current, const String &p_custom) { emit_signal(SNAME("play_pressed")); if (p_current) { + run_current_filename = run_filename; play_scene_button->set_pressed(true); play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); + play_scene_button->set_tooltip(TTR("Reload the played scene.")); } else if (!p_custom.is_empty()) { run_custom_filename = p_custom; play_custom_scene_button->set_pressed(true); play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); + play_custom_scene_button->set_tooltip(TTR("Reload the played scene.")); } else { play_button->set_pressed(true); play_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); + play_button->set_tooltip(TTR("Reload the played scene.")); } stop_button->set_disabled(false); @@ -2527,9 +2531,22 @@ void EditorNode::_run_native(const Ref<EditorExportPreset> &p_preset) { } } +void EditorNode::_reset_play_buttons() { + play_button->set_pressed(false); + play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); + play_button->set_tooltip(TTR("Play the project.")); + play_scene_button->set_pressed(false); + play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); + play_scene_button->set_tooltip(TTR("Play the edited scene.")); + play_custom_scene_button->set_pressed(false); + play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); + play_custom_scene_button->set_tooltip(TTR("Play a custom scene.")); +} + void EditorNode::_android_build_source_selected(const String &p_file) { export_template_manager->install_android_template_from_file(p_file); } + void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!p_confirmed) { // FIXME: this may be a hack. current_menu_option = (MenuOptions)p_option; @@ -2821,7 +2838,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { quick_run->set_title(TTR("Quick Run Scene...")); play_custom_scene_button->set_pressed(false); } else { - String last_custom_scene = run_custom_filename; + String last_custom_scene = run_custom_filename; // This is necessary to have a copy of the string. run_play_custom(last_custom_scene); } @@ -2833,13 +2850,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { editor_run.stop(); run_custom_filename.clear(); - play_button->set_pressed(false); - play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); - play_scene_button->set_pressed(false); - play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); - play_custom_scene_button->set_pressed(false); - play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); + run_current_filename.clear(); stop_button->set_disabled(true); + _reset_play_buttons(); if (bool(EDITOR_GET("run/output/always_close_output_on_stop"))) { for (int i = 0; i < bottom_panel_items.size(); i++) { @@ -2862,7 +2875,12 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_PLAY_SCENE: { - run_play_current(); + if (run_current_filename.is_empty() || editor_run.get_status() == EditorRun::STATUS_STOP) { + run_play_current(); + } else { + String last_current_scene = run_current_filename; // This is necessary to have a copy of the string. + run_play_custom(last_current_scene); + } } break; case RUN_SETTINGS: { @@ -5066,8 +5084,9 @@ void EditorNode::run_play_current() { } void EditorNode::run_play_custom(const String &p_custom) { + bool is_current = !run_current_filename.is_empty(); _menu_option_confirm(RUN_STOP, true); - _run(false, p_custom); + _run(is_current, p_custom); } void EditorNode::run_stop() { @@ -6295,7 +6314,7 @@ EditorNode::EditorNode() { main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 8); main_vbox->add_theme_constant_override("separation", 8 * EDSCALE); - menu_hb = memnew(HBoxContainer); + menu_hb = memnew(EditorTitleBar); main_vbox->add_child(menu_hb); left_l_hsplit = memnew(HSplitContainer); @@ -6526,6 +6545,15 @@ EditorNode::EditorNode() { scene_root_parent->add_child(main_control); bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU); + bool can_expand = bool(EDITOR_GET("interface/editor/expand_to_title")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_EXTEND_TO_TITLE); + + if (can_expand) { + // Add spacer to avoid other controls under window minimize/maximize/close buttons (left side). + Control *menu_spacer = memnew(Control); + menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + menu_spacer->set_custom_minimum_size(Size2(DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID).x, 0)); + menu_hb->add_child(menu_spacer); + } main_menu = memnew(MenuBar); menu_hb->add_child(main_menu); @@ -6695,6 +6723,11 @@ EditorNode::EditorNode() { ED_SHORTCUT_OVERRIDE("editor/quit_to_project_list", "macos", KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::Q); project_menu->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), RUN_PROJECT_MANAGER, true); + // Spacer to center 2D / 3D / Script buttons. + Control *left_spacer = memnew(Control); + left_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + menu_hb->add_child(left_spacer); + menu_hb->add_spacer(); main_editor_button_vb = memnew(HBoxContainer); @@ -6772,7 +6805,9 @@ EditorNode::EditorNode() { } help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Heart"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT); + // Spacer to center 2D / 3D / Script buttons. Control *right_spacer = memnew(Control); + right_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); menu_hb->add_child(right_spacer); HBoxContainer *play_hb = memnew(HBoxContainer); @@ -6782,10 +6817,8 @@ EditorNode::EditorNode() { play_button->set_flat(true); play_hb->add_child(play_button); play_button->set_toggle_mode(true); - play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); play_button->set_focus_mode(Control::FOCUS_NONE); play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY)); - play_button->set_tooltip(TTR("Play the project.")); ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), Key::F5); ED_SHORTCUT_OVERRIDE("editor/play", "macos", KeyModifierMask::CMD | Key::B); @@ -6826,9 +6859,7 @@ EditorNode::EditorNode() { play_hb->add_child(play_scene_button); play_scene_button->set_toggle_mode(true); play_scene_button->set_focus_mode(Control::FOCUS_NONE); - play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_SCENE)); - play_scene_button->set_tooltip(TTR("Play the edited scene.")); ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), Key::F6); ED_SHORTCUT_OVERRIDE("editor/play_scene", "macos", KeyModifierMask::CMD | Key::R); @@ -6839,9 +6870,9 @@ EditorNode::EditorNode() { play_hb->add_child(play_custom_scene_button); play_custom_scene_button->set_toggle_mode(true); play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE); - play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_CUSTOM_SCENE)); - play_custom_scene_button->set_tooltip(TTR("Play custom scene")); + + _reset_play_buttons(); ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F5); ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R); @@ -6878,6 +6909,14 @@ EditorNode::EditorNode() { right_menu_hb->add_child(rendering_driver); + if (can_expand) { + // Add spacer to avoid other controls under the window minimize/maximize/close buttons (right side). + Control *menu_spacer = memnew(Control); + menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + menu_spacer->set_custom_minimum_size(Size2(DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID).y, 0)); + menu_hb->add_child(menu_spacer); + } + // Only display the render drivers that are available for this display driver. int display_driver_idx = OS::get_singleton()->get_display_driver_id(); Vector<String> render_drivers = DisplayServer::get_create_function_rendering_drivers(display_driver_idx); @@ -7294,7 +7333,7 @@ EditorNode::EditorNode() { canvas_item_mat_convert.instantiate(); resource_conversion_plugins.push_back(canvas_item_mat_convert); - Ref<ParticlesMaterialConversionPlugin> particles_mat_convert; + Ref<ParticleProcessMaterialConversionPlugin> particles_mat_convert; particles_mat_convert.instantiate(); resource_conversion_plugins.push_back(particles_mat_convert); @@ -7434,8 +7473,16 @@ EditorNode::EditorNode() { add_child(screenshot_timer); screenshot_timer->set_owner(get_owner()); - main_menu->set_custom_minimum_size(Size2(MAX(main_menu->get_minimum_size().x, play_hb->get_minimum_size().x + right_menu_hb->get_minimum_size().x), 0)); - right_spacer->set_custom_minimum_size(Size2(MAX(0, main_menu->get_minimum_size().x - play_hb->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + // Adjust spacers to center 2D / 3D / Script buttons. + int max_w = MAX(play_hb->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu->get_minimum_size().x); + left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu->get_minimum_size().x), 0)); + right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - play_hb->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + + // Extend menu bar to window title. + if (can_expand) { + DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE, true, DisplayServer::MAIN_WINDOW_ID); + menu_hb->set_can_move_window(true); + } String exec = OS::get_singleton()->get_executable_path(); // Save editor executable path for third-party tools. diff --git a/editor/editor_node.h b/editor/editor_node.h index 91c753e480..792d2fc879 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -35,6 +35,7 @@ #include "editor/editor_folding.h" #include "editor/editor_native_shader_source_visualizer.h" #include "editor/editor_run.h" +#include "editor/editor_title_bar.h" #include "editor/export/editor_export.h" #include "editor/inspector_dock.h" @@ -322,7 +323,7 @@ private: HBoxContainer *bottom_hb = nullptr; Control *vp_base = nullptr; - HBoxContainer *menu_hb = nullptr; + EditorTitleBar *menu_hb = nullptr; Control *main_control = nullptr; MenuBar *main_menu = nullptr; PopupMenu *file_menu = nullptr; @@ -470,7 +471,9 @@ private: String _tmp_import_path; String external_file; String open_navigate; + String run_custom_filename; + String run_current_filename; DynamicFontImportSettings *fontdata_import_settings = nullptr; SceneImportSettings *scene_import_settings = nullptr; @@ -580,6 +583,7 @@ private: void _run(bool p_current = false, const String &p_custom = ""); void _run_native(const Ref<EditorExportPreset> &p_preset); + void _reset_play_buttons(); void _add_to_recent_scenes(const String &p_scene); void _update_recent_scenes(); diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index 87ebd3e1c1..adbfacd131 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -80,6 +80,11 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) { } void EditorPath::_show_popup() { + if (sub_objects_menu->is_visible()) { + sub_objects_menu->hide(); + return; + } + sub_objects_menu->clear(); Size2 size = get_size(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 84c4c9c877..c70dc6bc51 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -99,6 +99,10 @@ void EditorPropertyText::set_string_name(bool p_enabled) { string_name = p_enabled; } +void EditorPropertyText::set_secret(bool p_enabled) { + text->set_secret(p_enabled); +} + void EditorPropertyText::set_placeholder(const String &p_string) { text->set_placeholder(p_string); } @@ -1458,7 +1462,7 @@ void EditorPropertyFloat::_value_changed(double val) { } if (angle_in_radians) { - val = Math::deg2rad(val); + val = Math::deg_to_rad(val); } emit_changed(get_edited_property(), val); } @@ -1466,7 +1470,7 @@ void EditorPropertyFloat::_value_changed(double val) { void EditorPropertyFloat::update_property() { double val = get_edited_object()->get(get_edited_property()); if (angle_in_radians) { - val = Math::rad2deg(val); + val = Math::rad_to_deg(val); } setting = true; spin->set_value(val); @@ -1988,9 +1992,9 @@ void EditorPropertyVector3::_value_changed(double val, const String &p_name) { v3.y = spin[1]->get_value(); v3.z = spin[2]->get_value(); if (angle_in_radians) { - v3.x = Math::deg2rad(v3.x); - v3.y = Math::deg2rad(v3.y); - v3.z = Math::deg2rad(v3.z); + v3.x = Math::deg_to_rad(v3.x); + v3.y = Math::deg_to_rad(v3.y); + v3.z = Math::deg_to_rad(v3.z); } emit_changed(get_edited_property(), v3, p_name); } @@ -2022,9 +2026,9 @@ void EditorPropertyVector3::_update_ratio() { void EditorPropertyVector3::update_using_vector(Vector3 p_vector) { if (angle_in_radians) { - p_vector.x = Math::rad2deg(p_vector.x); - p_vector.y = Math::rad2deg(p_vector.y); - p_vector.z = Math::rad2deg(p_vector.z); + p_vector.x = Math::rad_to_deg(p_vector.x); + p_vector.y = Math::rad_to_deg(p_vector.y); + p_vector.z = Math::rad_to_deg(p_vector.z); } setting = true; spin[0]->set_value(p_vector.x); @@ -2039,9 +2043,9 @@ Vector3 EditorPropertyVector3::get_vector() { v3.y = spin[1]->get_value(); v3.z = spin[2]->get_value(); if (angle_in_radians) { - v3.x = Math::deg2rad(v3.x); - v3.y = Math::deg2rad(v3.y); - v3.z = Math::deg2rad(v3.z); + v3.x = Math::deg_to_rad(v3.x); + v3.y = Math::deg_to_rad(v3.y); + v3.z = Math::deg_to_rad(v3.z); } return v3; @@ -2643,9 +2647,9 @@ void EditorPropertyQuaternion::_custom_value_changed(double val) { edit_euler.z = euler[2]->get_value(); Vector3 v; - v.x = Math::deg2rad(edit_euler.x); - v.y = Math::deg2rad(edit_euler.y); - v.z = Math::deg2rad(edit_euler.z); + v.x = Math::deg_to_rad(edit_euler.x); + v.y = Math::deg_to_rad(edit_euler.y); + v.z = Math::deg_to_rad(edit_euler.z); Quaternion temp_q = Quaternion(v); spin[0]->set_value(temp_q.x); @@ -2685,9 +2689,9 @@ void EditorPropertyQuaternion::update_property() { spin[3]->set_value(val.w); if (!is_grabbing_euler()) { Vector3 v = val.normalized().get_euler_yxz(); - edit_euler.x = Math::rad2deg(v.x); - edit_euler.y = Math::rad2deg(v.y); - edit_euler.z = Math::rad2deg(v.z); + edit_euler.x = Math::rad_to_deg(v.x); + edit_euler.y = Math::rad_to_deg(v.y); + edit_euler.z = Math::rad_to_deg(v.z); euler[0]->set_value(edit_euler.x); euler[1]->set_value(edit_euler.y); euler[2]->set_value(edit_euler.z); @@ -4408,6 +4412,9 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyText *editor = memnew(EditorPropertyText); if (p_hint == PROPERTY_HINT_PLACEHOLDER_TEXT) { editor->set_placeholder(p_hint_text); + } else if (p_hint == PROPERTY_HINT_PASSWORD) { + editor->set_secret(true); + editor->set_placeholder(p_hint_text); } return editor; } @@ -4532,6 +4539,9 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyText *editor = memnew(EditorPropertyText); if (p_hint == PROPERTY_HINT_PLACEHOLDER_TEXT) { editor->set_placeholder(p_hint_text); + } else if (p_hint == PROPERTY_HINT_PASSWORD) { + editor->set_secret(true); + editor->set_placeholder(p_hint_text); } editor->set_string_name(true); return editor; diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 6ac3973303..d6c9510634 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -67,6 +67,7 @@ public: void set_string_name(bool p_enabled); virtual void update_property() override; void set_placeholder(const String &p_string); + void set_secret(bool p_enabled); EditorPropertyText(); }; diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp index 6c713de94a..a2dfa4f80e 100644 --- a/editor/editor_property_name_processor.cpp +++ b/editor/editor_property_name_processor.cpp @@ -106,6 +106,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["aabb"] = "AABB"; capitalize_string_remaps["adb"] = "ADB"; capitalize_string_remaps["ao"] = "AO"; + capitalize_string_remaps["api"] = "API"; capitalize_string_remaps["apk"] = "APK"; capitalize_string_remaps["arm64-v8a"] = "arm64-v8a"; capitalize_string_remaps["armeabi-v7a"] = "armeabi-v7a"; @@ -172,6 +173,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["k1"] = "K1"; capitalize_string_remaps["k2"] = "K2"; capitalize_string_remaps["kb"] = "(KB)"; // Unit. + capitalize_string_remaps["lcd"] = "LCD"; capitalize_string_remaps["ldr"] = "LDR"; capitalize_string_remaps["lod"] = "LOD"; capitalize_string_remaps["lowpass"] = "Low-pass"; @@ -190,11 +192,14 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["opengl"] = "OpenGL"; capitalize_string_remaps["opentype"] = "OpenType"; capitalize_string_remaps["openxr"] = "OpenXR"; + capitalize_string_remaps["osslsigncode"] = "osslsigncode"; capitalize_string_remaps["pck"] = "PCK"; capitalize_string_remaps["png"] = "PNG"; capitalize_string_remaps["po2"] = "(Power of 2)"; // Unit. capitalize_string_remaps["pvrtc"] = "PVRTC"; capitalize_string_remaps["pvs"] = "PVS"; + capitalize_string_remaps["rcedit"] = "rcedit"; + capitalize_string_remaps["rcodesign"] = "rcodesign"; capitalize_string_remaps["rgb"] = "RGB"; capitalize_string_remaps["rid"] = "RID"; capitalize_string_remaps["rmb"] = "RMB"; @@ -204,6 +209,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["sdfgi"] = "SDFGI"; capitalize_string_remaps["sdk"] = "SDK"; capitalize_string_remaps["sec"] = "(sec)"; // Unit. + capitalize_string_remaps["signtool"] = "signtool"; capitalize_string_remaps["sms"] = "SMS"; capitalize_string_remaps["srgb"] = "sRGB"; capitalize_string_remaps["ssao"] = "SSAO"; @@ -236,6 +242,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["webp"] = "WebP"; capitalize_string_remaps["webrtc"] = "WebRTC"; capitalize_string_remaps["websocket"] = "WebSocket"; + capitalize_string_remaps["wine"] = "wine"; capitalize_string_remaps["wifi"] = "Wi-Fi"; capitalize_string_remaps["x86"] = "x86"; capitalize_string_remaps["xr"] = "XR"; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 4437b1b166..dd4adbb28f 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -407,6 +407,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { set_restart_if_changed("interface/editor/debug/enable_pseudolocalization", true); // Use pseudolocalization in editor. EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/use_embedded_menu", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) + EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/expand_to_title", true, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/custom_display_scale", 1.0, "0.5,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/main_font_size", 14, "8,48,1") @@ -414,7 +415,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 0, "Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set") _initial_set("interface/editor/code_font_custom_opentype_features", ""); _initial_set("interface/editor/code_font_custom_variations", ""); - _initial_set("interface/editor/font_antialiased", true); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_antialiasing", 1, "None,Grayscale,LCD sub-pixel") #ifdef MACOS_ENABLED EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (None),None,Light,Normal") #else diff --git a/editor/editor_title_bar.cpp b/editor/editor_title_bar.cpp new file mode 100644 index 0000000000..06dcea1f8a --- /dev/null +++ b/editor/editor_title_bar.cpp @@ -0,0 +1,86 @@ +/*************************************************************************/ +/* editor_title_bar.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 "editor/editor_title_bar.h" + +void EditorTitleBar::input(const Ref<InputEvent> &p_event) { + if (!can_move) { + return; + } + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && moving) { + if ((mm->get_button_mask() & MouseButton::LEFT) == MouseButton::LEFT) { + Window *w = Object::cast_to<Window>(get_viewport()); + if (w) { + Point2 mouse = DisplayServer::get_singleton()->mouse_get_position(); + w->set_position(mouse - click_pos); + } + } else { + moving = false; + } + } + + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && has_point(mb->get_position())) { + Window *w = Object::cast_to<Window>(get_viewport()); + if (w) { + if (mb->get_button_index() == MouseButton::LEFT) { + if (mb->is_pressed()) { + click_pos = DisplayServer::get_singleton()->mouse_get_position() - w->get_position(); + moving = true; + } else { + moving = false; + } + } + if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click() && mb->is_pressed()) { + if (DisplayServer::get_singleton()->window_maximize_on_title_dbl_click()) { + if (w->get_mode() == Window::MODE_WINDOWED) { + w->set_mode(Window::MODE_MAXIMIZED); + } else if (w->get_mode() == Window::MODE_MAXIMIZED) { + w->set_mode(Window::MODE_WINDOWED); + } + } else if (DisplayServer::get_singleton()->window_minimize_on_title_dbl_click()) { + w->set_mode(Window::MODE_MINIMIZED); + } + moving = false; + } + } + } +} + +void EditorTitleBar::set_can_move_window(bool p_enabled) { + can_move = p_enabled; + set_process_input(can_move); +} + +bool EditorTitleBar::get_can_move_window() const { + return can_move; +} diff --git a/editor/editor_title_bar.h b/editor/editor_title_bar.h new file mode 100644 index 0000000000..ad6ec37ac9 --- /dev/null +++ b/editor/editor_title_bar.h @@ -0,0 +1,53 @@ +/*************************************************************************/ +/* editor_title_bar.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 EDITOR_TITLE_BAR_H +#define EDITOR_TITLE_BAR_H + +#include "scene/gui/box_container.h" +#include "scene/main/window.h" + +class EditorTitleBar : public HBoxContainer { + GDCLASS(EditorTitleBar, HBoxContainer); + + Point2i click_pos; + bool moving = false; + bool can_move = false; + +protected: + virtual void input(const Ref<InputEvent> &p_event) override; + static void _bind_methods(){}; + +public: + void set_can_move_window(bool p_enabled); + bool get_can_move_window() const; +}; + +#endif // EDITOR_TITLE_BAR_H diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp index 31f408eedb..d291040bd2 100644 --- a/editor/export/editor_export.cpp +++ b/editor/export/editor_export.cpp @@ -312,12 +312,14 @@ void EditorExport::update_export_presets() { // Clear the preset properties and values prior to reloading preset->properties.clear(); preset->values.clear(); + preset->update_visibility.clear(); for (const EditorExportPlatform::ExportOption &E : options) { preset->properties.push_back(E.option); StringName option_name = E.option.name; preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value; + preset->update_visibility[option_name] = E.update_visibility; } } } diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index ab1586cb77..8283c24e61 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -323,6 +323,7 @@ Ref<EditorExportPreset> EditorExportPlatform::create_preset() { for (const ExportOption &E : options) { preset->properties.push_back(E.option); preset->values[E.option.name] = E.default_value; + preset->update_visibility[E.option.name] = E.update_visibility; } return preset; diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h index c870ee66aa..bbdb47e041 100644 --- a/editor/export/editor_export_platform.h +++ b/editor/export/editor_export_platform.h @@ -117,10 +117,12 @@ public: struct ExportOption { PropertyInfo option; Variant default_value; + bool update_visibility = false; - ExportOption(const PropertyInfo &p_info, const Variant &p_default) : + ExportOption(const PropertyInfo &p_info, const Variant &p_default, bool p_update_visibility = false) : option(p_info), - default_value(p_default) { + default_value(p_default), + update_visibility(p_update_visibility) { } ExportOption() {} }; @@ -136,13 +138,13 @@ public: messages.push_back(msg); switch (p_type) { case EXPORT_MESSAGE_INFO: { - print_line(vformat("%s: %s\n", msg.category, msg.text)); + print_line(vformat("%s: %s", msg.category, msg.text)); } break; case EXPORT_MESSAGE_WARNING: { - WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text)); + WARN_PRINT(vformat("%s: %s", msg.category, msg.text)); } break; case EXPORT_MESSAGE_ERROR: { - ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text)); + ERR_PRINT(vformat("%s: %s", msg.category, msg.text)); } break; default: break; @@ -170,7 +172,7 @@ public: virtual void get_export_options(List<ExportOption> *r_options) = 0; virtual bool should_update_export_options() { return false; } - virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } + virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } virtual String get_os_name() const = 0; virtual String get_name() const = 0; diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp index cdf69e727d..4411ad11bc 100644 --- a/editor/export/editor_export_preset.cpp +++ b/editor/export/editor_export_preset.cpp @@ -34,6 +34,9 @@ bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) if (values.has(p_name)) { values[p_name] = p_value; EditorExport::singleton->save_presets(); + if (update_visibility[p_name]) { + notify_property_list_changed(); + } return true; } @@ -51,7 +54,7 @@ bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const { void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const { for (const PropertyInfo &E : properties) { - if (platform->get_export_option_visibility(E.name, values)) { + if (platform->get_export_option_visibility(this, E.name, values)) { p_list->push_back(E); } } diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h index 00109396b0..0c780c45cd 100644 --- a/editor/export/editor_export_preset.h +++ b/editor/export/editor_export_preset.h @@ -67,6 +67,7 @@ private: List<PropertyInfo> properties; HashMap<StringName, Variant> values; + HashMap<StringName, bool> update_visibility; String name; diff --git a/editor/icons/InterpCubicAngle.svg b/editor/icons/InterpCubicAngle.svg new file mode 100644 index 0000000000..e302d556dc --- /dev/null +++ b/editor/icons/InterpCubicAngle.svg @@ -0,0 +1 @@ +<svg enable-background="new 0 0 16 8" height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#5fff95" stroke-linecap="round"><path d="m2 6c5 0 3-4 6-4s1 4 6 4" stroke-width="2"/><circle cx="14" cy="2" r="1.5" stroke-linejoin="round"/></g></svg> diff --git a/editor/icons/InterpCubicInTime.svg b/editor/icons/InterpCubicInTime.svg deleted file mode 100644 index 81027f798a..0000000000 --- a/editor/icons/InterpCubicInTime.svg +++ /dev/null @@ -1 +0,0 @@ -<svg enable-background="new -595.5 420.5 16 8" height="8" viewBox="-595.5 420.5 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m-593.5 426.5c1-4 3.5-5.5 6-2s5 2 6-2" fill="none" stroke="#ff92cb" stroke-linecap="round" stroke-width="2"/></svg> diff --git a/editor/icons/InterpLinearAngle.svg b/editor/icons/InterpLinearAngle.svg new file mode 100644 index 0000000000..af4e87a6cb --- /dev/null +++ b/editor/icons/InterpLinearAngle.svg @@ -0,0 +1 @@ +<svg enable-background="new 0 0 16 8" height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fd995f" stroke-linecap="round" stroke-linejoin="round"><path d="m2 6 6-4 6 4" stroke-width="2"/><circle cx="14" cy="2" r="1.5"/></g></svg> diff --git a/editor/icons/ParticlesMaterial.svg b/editor/icons/ParticleProcessMaterial.svg index 33598980a5..33598980a5 100644 --- a/editor/icons/ParticlesMaterial.svg +++ b/editor/icons/ParticleProcessMaterial.svg diff --git a/editor/icons/RigidDynamicBody2D.svg b/editor/icons/RigidBody2D.svg index 5d08e991ae..5d08e991ae 100644 --- a/editor/icons/RigidDynamicBody2D.svg +++ b/editor/icons/RigidBody2D.svg diff --git a/editor/icons/RigidDynamicBody3D.svg b/editor/icons/RigidBody3D.svg index 7f5db4ce88..7f5db4ce88 100644 --- a/editor/icons/RigidDynamicBody3D.svg +++ b/editor/icons/RigidBody3D.svg diff --git a/editor/icons/SoftDynamicBody3D.svg b/editor/icons/SoftBody3D.svg index 7bc9a22c22..7bc9a22c22 100644 --- a/editor/icons/SoftDynamicBody3D.svg +++ b/editor/icons/SoftBody3D.svg diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp index f4d19fe8b6..5b9ed2c1d2 100644 --- a/editor/import/collada.cpp +++ b/editor/import/collada.cpp @@ -131,7 +131,7 @@ Transform3D Collada::Node::compute_transform(const Collada &state) const { switch (xf.op) { case XForm::OP_ROTATE: { if (xf.data.size() >= 4) { - xform_step.rotate(Vector3(xf.data[0], xf.data[1], xf.data[2]), Math::deg2rad(xf.data[3])); + xform_step.rotate(Vector3(xf.data[0], xf.data[1], xf.data[2]), Math::deg_to_rad(xf.data[3])); } } break; case XForm::OP_SCALE: { diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 043681aa87..b9be8fb792 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -449,8 +449,8 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper // Update font preview. if (font_preview.is_valid()) { - if (p_edited_property == "antialiased") { - font_preview->set_antialiased(import_settings_data->get("antialiased")); + if (p_edited_property == "antialiasing") { + font_preview->set_antialiasing((TextServer::FontAntialiasing)import_settings_data->get("antialiasing").operator int()); } else if (p_edited_property == "generate_mipmaps") { font_preview->set_generate_mipmaps(import_settings_data->get("generate_mipmaps")); } else if (p_edited_property == "multichannel_signed_distance_field") { @@ -574,6 +574,12 @@ void DynamicFontImportSettings::_variations_validate() { } } } + if ((TextServer::FontAntialiasing)(int)import_settings_data->get("antialiasing") == TextServer::FONT_ANTIALIASING_LCD) { + warn += "\n" + TTR("Note: LCD sub-pixel anti-aliasing is selected, each of the glyphs will be pre-rendered for all supported sub-pixel layouts (5x)."); + } + if ((TextServer::SubpixelPositioning)(int)import_settings_data->get("subpixel_positioning") != TextServer::SUBPIXEL_POSITIONING_DISABLED) { + warn += "\n" + TTR("Note: Sub-pixel positioning is selected, each of the glyphs might be pre-rendered for multiple sub-pixel offsets (up to 4x)."); + } if (warn.is_empty()) { label_warn->set_text(""); label_warn->hide(); @@ -881,7 +887,7 @@ void DynamicFontImportSettings::_re_import() { HashMap<StringName, Variant> main_settings; main_settings["face_index"] = import_settings_data->get("face_index"); - main_settings["antialiased"] = import_settings_data->get("antialiased"); + main_settings["antialiasing"] = import_settings_data->get("antialiasing"); main_settings["generate_mipmaps"] = import_settings_data->get("generate_mipmaps"); main_settings["multichannel_signed_distance_field"] = import_settings_data->get("multichannel_signed_distance_field"); main_settings["msdf_pixel_range"] = import_settings_data->get("msdf_pixel_range"); @@ -1079,7 +1085,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { import_settings_data->notify_property_list_changed(); if (font_preview.is_valid()) { - font_preview->set_antialiased(import_settings_data->get("antialiased")); + font_preview->set_antialiasing((TextServer::FontAntialiasing)import_settings_data->get("antialiasing").operator int()); font_preview->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field")); font_preview->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range")); font_preview->set_msdf_size(import_settings_data->get("msdf_size")); @@ -1108,7 +1114,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); - options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); + options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel"), 1)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp index 685cb16eb1..6f775c7ea8 100644 --- a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp +++ b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp @@ -324,7 +324,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory Vector3 src_dir = src_tail - src_head; // Rotate rest. - if (Math::abs(Math::rad2deg(src_dir.angle_to(prof_dir))) > float(p_options["retarget/rest_fixer/fix_silhouette/threshold"])) { + if (Math::abs(Math::rad_to_deg(src_dir.angle_to(prof_dir))) > float(p_options["retarget/rest_fixer/fix_silhouette/threshold"])) { // Get rotation difference. Vector3 up_vec; // Need to rotate other than roll axis. switch (Vector3(abs(src_dir.x), abs(src_dir.y), abs(src_dir.z)).min_axis_index()) { diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index 32fd94b093..c822cd0fec 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -105,7 +105,7 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List< r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), (msdf) ? true : false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); @@ -139,7 +139,7 @@ void ResourceImporterDynamicFont::show_advanced_options(const String &p_path) { Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing dynamic font from: " + p_source_file); - bool antialiased = p_options["antialiased"]; + int antialiasing = p_options["antialiasing"]; bool generate_mipmaps = p_options["generate_mipmaps"]; bool msdf = p_options["multichannel_signed_distance_field"]; int px_range = p_options["msdf_pixel_range"]; @@ -159,7 +159,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str Ref<FontFile> font; font.instantiate(); font->set_data(data); - font->set_antialiased(antialiased); + font->set_antialiasing((TextServer::FontAntialiasing)antialiasing); font->set_generate_mipmaps(generate_mipmaps); font->set_multichannel_signed_distance_field(msdf); font->set_msdf_pixel_range(px_range); diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index 374cbe7ce2..58c2061051 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -99,7 +99,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin Ref<FontFile> font; font.instantiate(); - font->set_antialiased(false); + font->set_antialiasing(TextServer::FONT_ANTIALIASING_NONE); font->set_generate_mipmaps(false); font->set_multichannel_signed_distance_field(false); font->set_fixed_size(base_size); diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index b301bbf0f9..ed83535421 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -327,7 +327,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const Ref<Image> image; image.instantiate(); - Error err = ImageLoader::load_image(p_source_file, image, nullptr, false, 1.0); + Error err = ImageLoader::load_image(p_source_file, image); if (err != OK) { return err; } diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 85dda24f8e..62cb6e4167 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -565,7 +565,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, HashMap<R _pre_gen_shape_list(mesh, shapes, true); } - RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); + RigidBody3D *rigid_body = memnew(RigidBody3D); rigid_body->set_name(_fixstr(name, "rigid_body")); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); @@ -1060,7 +1060,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< base = col; } break; case MESH_PHYSICS_RIGID_BODY_AND_MESH: { - RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); + RigidBody3D *rigid_body = memnew(RigidBody3D); rigid_body->set_name(p_node->get_name()); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 0eed6184c0..17b94ec706 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -409,11 +409,26 @@ void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String } Error ResourceImporterTexture::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { + // Parse import options. + int32_t loader_flags = ImageFormatLoader::FLAG_NONE; + + // Compression. CompressMode compress_mode = CompressMode(int(p_options["compress/mode"])); const float lossy = p_options["compress/lossy_quality"]; const int pack_channels = p_options["compress/channel_pack"]; + const int normal = p_options["compress/normal_map"]; + const int hdr_compression = p_options["compress/hdr_compression"]; + const int bptc_ldr = p_options["compress/bptc_ldr"]; + + // Mipmaps. const bool mipmaps = p_options["mipmaps/generate"]; const uint32_t mipmap_limit = mipmaps ? uint32_t(p_options["mipmaps/limit"]) : uint32_t(-1); + + // Roughness. + const int roughness = p_options["roughness/mode"]; + const String normal_map = p_options["roughness/src_normal"]; + + // Processing. const bool fix_alpha_border = p_options["process/fix_alpha_border"]; const bool premult_alpha = p_options["process/premult_alpha"]; const bool normal_map_invert_y = p_options["process/normal_map_invert_y"]; @@ -421,29 +436,29 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String const bool stream = false; const int size_limit = p_options["process/size_limit"]; const bool hdr_as_srgb = p_options["process/hdr_as_srgb"]; + if (hdr_as_srgb) { + loader_flags |= ImageFormatLoader::FLAG_FORCE_LINEAR; + } const bool hdr_clamp_exposure = p_options["process/hdr_clamp_exposure"]; - const int normal = p_options["compress/normal_map"]; - const int hdr_compression = p_options["compress/hdr_compression"]; - const int bptc_ldr = p_options["compress/bptc_ldr"]; - const int roughness = p_options["roughness/mode"]; - const String normal_map = p_options["roughness/src_normal"]; + float scale = 1.0; + // SVG-specific options. if (p_options.has("svg/scale")) { scale = p_options["svg/scale"]; } Ref<Image> normal_image; Image::RoughnessChannel roughness_channel = Image::ROUGHNESS_CHANNEL_R; - if (mipmaps && roughness > 1 && FileAccess::exists(normal_map)) { normal_image.instantiate(); if (ImageLoader::load_image(normal_map, normal_image) == OK) { roughness_channel = Image::RoughnessChannel(roughness - 2); } } + Ref<Image> image; image.instantiate(); - Error err = ImageLoader::load_image(p_source_file, image, nullptr, hdr_as_srgb, scale); + Error err = ImageLoader::load_image(p_source_file, image, nullptr, loader_flags, scale); if (err != OK) { return err; } diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index a1e00f7d30..1dcae2841b 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -390,7 +390,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s int first = 0; int last = (frames / format_channels) - 1; bool found = false; - float limit = Math::db2linear(TRIM_DB_LIMIT); + float limit = Math::db_to_linear(TRIM_DB_LIMIT); for (int i = 0; i < data.size() / format_channels; i++) { float ampChannelSum = 0; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 2e83e2041f..3505d7fedf 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -223,8 +223,8 @@ public: grid_step_x->set_value(p_grid_step.x); grid_step_y->set_value(p_grid_step.y); primary_grid_steps->set_value(p_primary_grid_steps); - rotation_offset->set_value(Math::rad2deg(p_rotation_offset)); - rotation_step->set_value(Math::rad2deg(p_rotation_step)); + rotation_offset->set_value(Math::rad_to_deg(p_rotation_offset)); + rotation_step->set_value(Math::rad_to_deg(p_rotation_step)); scale_step->set_value(p_scale_step); } @@ -232,8 +232,8 @@ public: p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value()); p_grid_step = Point2(grid_step_x->get_value(), grid_step_y->get_value()); p_primary_grid_steps = int(primary_grid_steps->get_value()); - p_rotation_offset = Math::deg2rad(rotation_offset->get_value()); - p_rotation_step = Math::deg2rad(rotation_step->get_value()); + p_rotation_offset = Math::deg_to_rad(rotation_offset->get_value()); + p_rotation_step = Math::deg_to_rad(rotation_step->get_value()); p_scale_step = scale_step->get_value(); } }; @@ -1447,7 +1447,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { drag_selection, vformat(TTR("Rotate CanvasItem \"%s\" to %d degrees"), drag_selection[0]->get_name(), - Math::rad2deg(drag_selection[0]->_edit_get_rotation())), + Math::rad_to_deg(drag_selection[0]->_edit_get_rotation())), true); } @@ -3676,7 +3676,7 @@ void CanvasItemEditor::_draw_transform_message() { } break; case DRAG_ROTATE: { - real_t delta = Math::rad2deg(current_transform.get_rotation() - original_transform.get_rotation()); + real_t delta = Math::rad_to_deg(current_transform.get_rotation() - original_transform.get_rotation()); transform_message = TTR("Rotating:") + " " + FORMAT(delta) + String::utf8(" °"); } break; @@ -5563,19 +5563,7 @@ bool CanvasItemEditorViewport::_cyclical_dependency_exists(const String &p_targe void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point) { // Adjust casing according to project setting. The file name is expected to be in snake_case, but will work for others. String name = path.get_file().get_basename(); - switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_casing").operator int()) { - case NAME_CASING_PASCAL_CASE: - name = name.capitalize().replace(" ", ""); - break; - case NAME_CASING_CAMEL_CASE: - name = name.capitalize().replace(" ", ""); - name[0] = name.to_lower()[0]; - break; - case NAME_CASING_SNAKE_CASE: - name = name.capitalize().replace(" ", "_").to_lower(); - break; - } - child->set_name(name); + child->set_name(Node::adjust_name_casing(name)); Ref<Texture2D> texture = ResourceCache::get_ref(path); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 2ca495e5d6..0a840d6fd6 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -215,7 +215,7 @@ private: int primary_grid_steps = 8; int grid_step_multiplier = 0; - real_t snap_rotation_step = Math::deg2rad(15.0); + real_t snap_rotation_step = Math::deg_to_rad(15.0); real_t snap_rotation_offset = 0.0; real_t snap_scale_step = 0.1f; bool smart_snap_active = false; diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp index e20d298195..e56fd5dfe3 100644 --- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp @@ -37,7 +37,7 @@ #include "editor/editor_undo_redo_manager.h" #include "scene/2d/cpu_particles_2d.h" #include "scene/gui/separator.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" void CPUParticles2DEditorPlugin::edit(Object *p_object) { particles = Object::cast_to<CPUParticles2D>(p_object); diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp index 1487f8b7bc..e2d19c34e6 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp @@ -38,7 +38,7 @@ #include "editor/scene_tree_dock.h" #include "scene/2d/cpu_particles_2d.h" #include "scene/gui/separator.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" void GPUParticles2DEditorPlugin::edit(Object *p_object) { particles = Object::cast_to<GPUParticles2D>(p_object); @@ -167,9 +167,9 @@ void GPUParticles2DEditorPlugin::_generate_visibility_rect() { } void GPUParticles2DEditorPlugin::_generate_emission_mask() { - Ref<ParticlesMaterial> pm = particles->get_process_material(); + Ref<ParticleProcessMaterial> pm = particles->get_process_material(); if (!pm.is_valid()) { - EditorNode::get_singleton()->show_warning(TTR("Can only set point into a ParticlesMaterial process material")); + EditorNode::get_singleton()->show_warning(TTR("Can only set point into a ParticleProcessMaterial process material")); return; } @@ -320,7 +320,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { } if (valid_normals.size()) { - pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS); + pm->set_emission_shape(ParticleProcessMaterial::EMISSION_SHAPE_DIRECTED_POINTS); Vector<uint8_t> normdata; normdata.resize(w * h * 2 * sizeof(float)); //use RG texture @@ -339,7 +339,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { pm->set_emission_normal_texture(ImageTexture::create_from_image(img)); } else { - pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS); + pm->set_emission_shape(ParticleProcessMaterial::EMISSION_SHAPE_POINTS); } } diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp index 335efd6949..ebc92bf531 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp @@ -36,7 +36,7 @@ #include "editor/plugins/node_3d_editor_plugin.h" #include "editor/scene_tree_dock.h" #include "scene/3d/cpu_particles_3d.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" bool GPUParticles3DEditorBase::_generate(Vector<Vector3> &points, Vector<Vector3> &normals) { bool use_normals = emission_fill->get_selected() == 1; @@ -255,9 +255,9 @@ void GPUParticles3DEditor::_menu_option(int p_option) { } } break; case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: { - Ref<ParticlesMaterial> material = node->get_process_material(); + Ref<ParticleProcessMaterial> material = node->get_process_material(); if (material.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticlesMaterial' is required.")); + EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticleProcessMaterial' is required.")); return; } @@ -366,11 +366,11 @@ void GPUParticles3DEditor::_generate_emission_points() { Ref<Image> image = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img)); Ref<ImageTexture> tex = ImageTexture::create_from_image(image); - Ref<ParticlesMaterial> material = node->get_process_material(); + Ref<ParticleProcessMaterial> material = node->get_process_material(); ERR_FAIL_COND(material.is_null()); if (normals.size() > 0) { - material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS); + material->set_emission_shape(ParticleProcessMaterial::EMISSION_SHAPE_DIRECTED_POINTS); material->set_emission_point_count(point_count); material->set_emission_point_texture(tex); @@ -392,7 +392,7 @@ void GPUParticles3DEditor::_generate_emission_points() { Ref<Image> image2 = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img2)); material->set_emission_normal_texture(ImageTexture::create_from_image(image2)); } else { - material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS); + material->set_emission_shape(ParticleProcessMaterial::EMISSION_SHAPE_POINTS); material->set_emission_point_count(point_count); material->set_emission_point_texture(tex); } diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 5d59f62f05..74a6e90a6d 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -36,7 +36,7 @@ #include "editor/editor_undo_redo_manager.h" #include "scene/gui/subviewport_container.h" #include "scene/resources/fog_material.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" #include "scene/resources/sky_material.h" void MaterialEditor::_notification(int p_what) { @@ -179,8 +179,8 @@ MaterialEditor::MaterialEditor() { viewport->add_child(box_instance); Transform3D box_xform; - box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg2rad(25.0)); - box_xform.basis = box_xform.basis * Basis().rotated(Vector3(0, 1, 0), Math::deg2rad(-25.0)); + box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg_to_rad(25.0)); + box_xform.basis = box_xform.basis * Basis().rotated(Vector3(0, 1, 0), Math::deg_to_rad(-25.0)); box_xform.basis.scale(Vector3(0.7, 0.7, 0.7)); box_xform.origin.y = 0.05; box_instance->set_transform(box_xform); @@ -405,17 +405,17 @@ Ref<Resource> ORMMaterial3DConversionPlugin::convert(const Ref<Resource> &p_reso return smat; } -String ParticlesMaterialConversionPlugin::converts_to() const { +String ParticleProcessMaterialConversionPlugin::converts_to() const { return "ShaderMaterial"; } -bool ParticlesMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const { - Ref<ParticlesMaterial> mat = p_resource; +bool ParticleProcessMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const { + Ref<ParticleProcessMaterial> mat = p_resource; return mat.is_valid(); } -Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const { - Ref<ParticlesMaterial> mat = p_resource; +Ref<Resource> ParticleProcessMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const { + Ref<ParticleProcessMaterial> mat = p_resource; ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>()); Ref<ShaderMaterial> smat; diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index fc3da5fd9f..06ae43e6d7 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -122,8 +122,8 @@ public: virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const override; }; -class ParticlesMaterialConversionPlugin : public EditorResourceConversionPlugin { - GDCLASS(ParticlesMaterialConversionPlugin, EditorResourceConversionPlugin); +class ParticleProcessMaterialConversionPlugin : public EditorResourceConversionPlugin { + GDCLASS(ParticleProcessMaterialConversionPlugin, EditorResourceConversionPlugin); public: virtual String converts_to() const override; diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 31c9f1e387..980d2974a0 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -77,8 +77,8 @@ void MeshEditor::edit(Ref<Mesh> p_mesh) { mesh = p_mesh; mesh_instance->set_mesh(mesh); - rot_x = Math::deg2rad(-15.0); - rot_y = Math::deg2rad(30.0); + rot_x = Math::deg_to_rad(-15.0); + rot_y = Math::deg_to_rad(30.0); _update_rotation(); AABB aabb = mesh->get_aabb(); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 043848080f..878f8c9a95 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -59,7 +59,7 @@ #include "scene/3d/ray_cast_3d.h" #include "scene/3d/reflection_probe.h" #include "scene/3d/shape_cast_3d.h" -#include "scene/3d/soft_dynamic_body_3d.h" +#include "scene/3d/soft_body_3d.h" #include "scene/3d/spring_arm_3d.h" #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body_3d.h" @@ -1295,7 +1295,7 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec //min_p = p_arc_xform.affine_inverse().xform(min_p); float a = (Math_PI * 0.5) - Vector2(min_p.x, -min_p.z).angle(); - return Math::rad2deg(a); + return Math::rad_to_deg(a); } void Light3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { @@ -1421,8 +1421,8 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int i = 0; i < 120; i++) { // Create a circle - const float ra = Math::deg2rad((float)(i * 3)); - const float rb = Math::deg2rad((float)((i + 1) * 3)); + const float ra = Math::deg_to_rad((float)(i * 3)); + const float rb = Math::deg_to_rad((float)((i + 1) * 3)); const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -1458,13 +1458,13 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { SpotLight3D *sl = Object::cast_to<SpotLight3D>(light); float r = sl->get_param(Light3D::PARAM_RANGE); - float w = r * Math::sin(Math::deg2rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); - float d = r * Math::cos(Math::deg2rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); + float w = r * Math::sin(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); + float d = r * Math::cos(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); for (int i = 0; i < 120; i++) { // Draw a circle - const float ra = Math::deg2rad((float)(i * 3)); - const float rb = Math::deg2rad((float)((i + 1) * 3)); + const float ra = Math::deg_to_rad((float)(i * 3)); + const float rb = Math::deg_to_rad((float)((i + 1) * 3)); const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w; const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w; @@ -1545,8 +1545,8 @@ void AudioStreamPlayer3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo float closest_angle = 1e20; for (int i = 0; i < 180; i++) { - float a = Math::deg2rad((float)i); - float an = Math::deg2rad((float)(i + 1)); + float a = Math::deg_to_rad((float)i); + float an = Math::deg_to_rad((float)(i + 1)); Vector3 from(Math::sin(a), 0, -Math::cos(a)); Vector3 to(Math::sin(an), 0, -Math::cos(an)); @@ -1628,8 +1628,8 @@ void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int i = 0; i < 120; i++) { // Create a circle. - const float ra = Math::deg2rad((float)(i * 3)); - const float rb = Math::deg2rad((float)((i + 1) * 3)); + const float ra = Math::deg_to_rad((float)(i * 3)); + const float rb = Math::deg_to_rad((float)((i + 1) * 3)); const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -1671,8 +1671,8 @@ void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (player->is_emission_angle_enabled()) { const float pc = player->get_emission_angle(); - const float ofs = -Math::cos(Math::deg2rad(pc)); - const float radius = Math::sin(Math::deg2rad(pc)); + const float ofs = -Math::cos(Math::deg_to_rad(pc)); + const float radius = Math::sin(Math::deg_to_rad(pc)); Vector<Vector3> points_primary; points_primary.resize(200); @@ -1707,7 +1707,7 @@ void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_lines(points_secondary, material_secondary); Vector<Vector3> handles; - const float ha = Math::deg2rad(player->get_emission_angle()); + const float ha = Math::deg_to_rad(player->get_emission_angle()); handles.push_back(Vector3(Math::sin(ha), 0, -Math::cos(ha))); p_gizmo->add_handles(handles, get_material("handles")); } @@ -1872,7 +1872,7 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { // The real FOV is halved for accurate representation float fov = camera->get_fov() / 2.0; - Vector3 side = Vector3(Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov))); + Vector3 side = Vector3(Math::sin(Math::deg_to_rad(fov)), 0, -Math::cos(Math::deg_to_rad(fov))); Vector3 nside = side; nside.x = -nside.x; Vector3 up = Vector3(0, side.x, 0); @@ -1944,7 +1944,7 @@ MeshInstance3DGizmoPlugin::MeshInstance3DGizmoPlugin() { } bool MeshInstance3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { - return Object::cast_to<MeshInstance3D>(p_spatial) != nullptr && Object::cast_to<SoftDynamicBody3D>(p_spatial) == nullptr; + return Object::cast_to<MeshInstance3D>(p_spatial) != nullptr && Object::cast_to<SoftBody3D>(p_spatial) == nullptr; } String MeshInstance3DGizmoPlugin::get_gizmo_name() const { @@ -2643,8 +2643,8 @@ void VehicleWheel3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { float r = car_wheel->get_radius(); const int skip = 10; for (int i = 0; i <= 360; i += skip) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + skip); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + skip); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -2687,30 +2687,30 @@ void VehicleWheel3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { /////////// -SoftDynamicBody3DGizmoPlugin::SoftDynamicBody3DGizmoPlugin() { +SoftBody3DGizmoPlugin::SoftBody3DGizmoPlugin() { Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); create_material("shape_material", gizmo_color); create_handle_material("handles"); } -bool SoftDynamicBody3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { - return Object::cast_to<SoftDynamicBody3D>(p_spatial) != nullptr; +bool SoftBody3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<SoftBody3D>(p_spatial) != nullptr; } -String SoftDynamicBody3DGizmoPlugin::get_gizmo_name() const { - return "SoftDynamicBody3D"; +String SoftBody3DGizmoPlugin::get_gizmo_name() const { + return "SoftBody3D"; } -int SoftDynamicBody3DGizmoPlugin::get_priority() const { +int SoftBody3DGizmoPlugin::get_priority() const { return -1; } -bool SoftDynamicBody3DGizmoPlugin::is_selectable_when_hidden() const { +bool SoftBody3DGizmoPlugin::is_selectable_when_hidden() const { return true; } -void SoftDynamicBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); +void SoftBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -2746,22 +2746,22 @@ void SoftDynamicBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_collision_triangles(tm); } -String SoftDynamicBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - return "SoftDynamicBody3D pin point"; +String SoftBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { + return "SoftBody3D pin point"; } -Variant SoftDynamicBody3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); +Variant SoftBody3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { + SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); return Variant(soft_body->is_point_pinned(p_id)); } -void SoftDynamicBody3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { - SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); +void SoftBody3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { + SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); soft_body->pin_point_toggle(p_id); } -bool SoftDynamicBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); +bool SoftBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { + SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); return soft_body->is_point_pinned(p_id); } @@ -3272,8 +3272,8 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> points; for (int i = 0; i <= 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -4517,8 +4517,8 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> points; for (int i = 0; i <= 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -4589,8 +4589,8 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector3 d(0, height * 0.5 - radius, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; @@ -4660,8 +4660,8 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector3 d(0, height * 0.5, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; @@ -5203,8 +5203,8 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba //swing for (int i = 0; i < 360; i += 10) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 10); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 10); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w; @@ -5221,12 +5221,12 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(1, 0, 0))).origin); /// Twist - float ts = Math::rad2deg(p_twist); + float ts = Math::rad_to_deg(p_twist); ts = MIN(ts, 720); for (int i = 0; i < int(ts); i += 5) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 5); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 5); float c = i / 720.0; float cn = (i + 5) / 720.0; Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w * c; diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h index 7dac1bd360..1b6485ac4e 100644 --- a/editor/plugins/node_3d_editor_gizmos.h +++ b/editor/plugins/node_3d_editor_gizmos.h @@ -409,8 +409,8 @@ public: VehicleWheel3DGizmoPlugin(); }; -class SoftDynamicBody3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(SoftDynamicBody3DGizmoPlugin, EditorNode3DGizmoPlugin); +class SoftBody3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(SoftBody3DGizmoPlugin, EditorNode3DGizmoPlugin); public: bool has_gizmo(Node3D *p_spatial) override; @@ -424,7 +424,7 @@ public: void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; - SoftDynamicBody3DGizmoPlugin(); + SoftBody3DGizmoPlugin(); }; class VisibleOnScreenNotifier3DGizmoPlugin : public EditorNode3DGizmoPlugin { diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 6add9e2e1e..0fdb62c56c 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -342,7 +342,7 @@ void Node3DEditorViewport::_update_camera(real_t p_interp_delta) { camera->set_global_transform(to_camera_transform(camera_cursor)); if (orthogonal) { - float half_fov = Math::deg2rad(get_fov()) / 2.0; + float half_fov = Math::deg_to_rad(get_fov()) / 2.0; float height = 2.0 * cursor.distance * Math::tan(half_fov); camera->set_orthogonal(height, get_znear(), get_zfar()); } else { @@ -2144,7 +2144,7 @@ void Node3DEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, cons } const real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); - const real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + const real_t radians_per_pixel = Math::deg_to_rad(degrees_per_pixel); const bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis"); const bool invert_x_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_x_axis"); @@ -2177,7 +2177,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const // Scale mouse sensitivity with camera FOV scale when zoomed in to make it easier to point at things. const real_t degrees_per_pixel = real_t(EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_sensitivity")) * MIN(1.0, cursor.fov_scale); - const real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + const real_t radians_per_pixel = Math::deg_to_rad(degrees_per_pixel); const bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis"); // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag". @@ -3981,19 +3981,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po // Adjust casing according to project setting. The file name is expected to be in snake_case, but will work for others. String name = path.get_file().get_basename(); - switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_casing").operator int()) { - case NAME_CASING_PASCAL_CASE: - name = name.capitalize().replace(" ", ""); - break; - case NAME_CASING_CAMEL_CASE: - name = name.capitalize().replace(" ", ""); - name[0] = name.to_lower()[0]; - break; - case NAME_CASING_SNAKE_CASE: - name = name.capitalize().replace(" ", "_").to_lower(); - break; - } - mesh_instance->set_name(name); + mesh_instance->set_name(Node::adjust_name_casing(name)); instantiated_scene = mesh_instance; } else { @@ -4546,7 +4534,7 @@ void Node3DEditorViewport::update_transform(Point2 p_mousepos, bool p_shift) { break; } - static const float orthogonal_threshold = Math::cos(Math::deg2rad(87.0f)); + static const float orthogonal_threshold = Math::cos(Math::deg_to_rad(87.0f)); bool axis_is_orthogonal = ABS(plane.normal.dot(global_axis)) < orthogonal_threshold; double angle = 0.0f; @@ -4566,10 +4554,10 @@ void Node3DEditorViewport::update_transform(Point2 p_mousepos, bool p_shift) { if (_edit.snap || spatial_editor->is_snap_enabled()) { snap = spatial_editor->get_rotate_snap(); } - angle = Math::rad2deg(angle) + snap * 0.5; //else it won't reach +180 + angle = Math::rad_to_deg(angle) + snap * 0.5; //else it won't reach +180 angle -= Math::fmod(angle, snap); set_message(vformat(TTR("Rotating %s degrees."), String::num(angle, snap_step_decimals))); - angle = Math::deg2rad(angle); + angle = Math::deg_to_rad(angle); bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW @@ -5737,7 +5725,7 @@ void Node3DEditor::_xform_dialog_action() { for (int i = 0; i < 3; i++) { translate[i] = xform_translate[i]->get_text().to_float(); - rotate[i] = Math::deg2rad(xform_rotate[i]->get_text().to_float()); + rotate[i] = Math::deg_to_rad(xform_rotate[i]->get_text().to_float()); scale[i] = xform_scale[i]->get_text().to_float(); } @@ -7512,7 +7500,7 @@ void Node3DEditor::_register_all_gizmos() { add_gizmo_plugin(Ref<AudioListener3DGizmoPlugin>(memnew(AudioListener3DGizmoPlugin))); add_gizmo_plugin(Ref<MeshInstance3DGizmoPlugin>(memnew(MeshInstance3DGizmoPlugin))); add_gizmo_plugin(Ref<OccluderInstance3DGizmoPlugin>(memnew(OccluderInstance3DGizmoPlugin))); - add_gizmo_plugin(Ref<SoftDynamicBody3DGizmoPlugin>(memnew(SoftDynamicBody3DGizmoPlugin))); + add_gizmo_plugin(Ref<SoftBody3DGizmoPlugin>(memnew(SoftBody3DGizmoPlugin))); add_gizmo_plugin(Ref<Sprite3DGizmoPlugin>(memnew(Sprite3DGizmoPlugin))); add_gizmo_plugin(Ref<Label3DGizmoPlugin>(memnew(Label3DGizmoPlugin))); add_gizmo_plugin(Ref<Marker3DGizmoPlugin>(memnew(Marker3DGizmoPlugin))); @@ -7623,10 +7611,10 @@ void Node3DEditor::_load_default_preview_settings() { // On any not-tidally-locked planet, a sun would have an angular altitude // of 60 degrees as the average of all points on the sphere at noon. // The azimuth choice is arbitrary, but ideally shouldn't be on an axis. - sun_rotation = Vector2(-Math::deg2rad(60.0), Math::deg2rad(150.0)); + sun_rotation = Vector2(-Math::deg_to_rad(60.0), Math::deg_to_rad(150.0)); - sun_angle_altitude->set_value(-Math::rad2deg(sun_rotation.x)); - sun_angle_azimuth->set_value(180.0 - Math::rad2deg(sun_rotation.y)); + sun_angle_altitude->set_value(-Math::rad_to_deg(sun_rotation.x)); + sun_angle_azimuth->set_value(180.0 - Math::rad_to_deg(sun_rotation.y)); sun_direction->update(); environ_sky_color->set_pick_color(Color(0.385, 0.454, 0.55)); environ_ground_color->set_pick_color(Color(0.2, 0.169, 0.133)); @@ -7669,8 +7657,8 @@ void Node3DEditor::_update_preview_environment() { } } - sun_angle_altitude->set_value(-Math::rad2deg(sun_rotation.x)); - sun_angle_azimuth->set_value(180.0 - Math::rad2deg(sun_rotation.y)); + sun_angle_altitude->set_value(-Math::rad_to_deg(sun_rotation.x)); + sun_angle_azimuth->set_value(180.0 - Math::rad_to_deg(sun_rotation.y)); bool disable_env = world_env_count > 0 || environ_button->is_pressed(); @@ -7703,15 +7691,15 @@ void Node3DEditor::_sun_direction_input(const Ref<InputEvent> &p_event) { sun_rotation.x += mm->get_relative().y * (0.02 * EDSCALE); sun_rotation.y -= mm->get_relative().x * (0.02 * EDSCALE); sun_rotation.x = CLAMP(sun_rotation.x, -Math_TAU / 4, Math_TAU / 4); - sun_angle_altitude->set_value(-Math::rad2deg(sun_rotation.x)); - sun_angle_azimuth->set_value(180.0 - Math::rad2deg(sun_rotation.y)); + sun_angle_altitude->set_value(-Math::rad_to_deg(sun_rotation.x)); + sun_angle_azimuth->set_value(180.0 - Math::rad_to_deg(sun_rotation.y)); _preview_settings_changed(); } } void Node3DEditor::_sun_direction_angle_set() { - sun_rotation.x = Math::deg2rad(-sun_angle_altitude->get_value()); - sun_rotation.y = Math::deg2rad(180.0 - sun_angle_azimuth->get_value()); + sun_rotation.x = Math::deg_to_rad(-sun_angle_altitude->get_value()); + sun_rotation.y = Math::deg_to_rad(180.0 - sun_angle_azimuth->get_value()); _preview_settings_changed(); } diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 4641df3dca..53bc6fbdf4 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -1257,6 +1257,17 @@ void ShaderEditorPlugin::_update_shader_list_status() { } } +void ShaderEditorPlugin::_move_shader_tab(int p_from, int p_to) { + if (p_from == p_to) { + return; + } + EditedShader es = edited_shaders[p_from]; + edited_shaders.remove_at(p_from); + edited_shaders.insert(p_to, es); + shader_tabs->move_child(shader_tabs->get_tab_control(p_from), p_to); + _update_shader_list(); +} + void ShaderEditorPlugin::edit(Object *p_object) { EditedShader es; @@ -1451,6 +1462,109 @@ void ShaderEditorPlugin::_shader_include_created(Ref<ShaderInclude> p_shader_inc EditorNode::get_singleton()->push_item(p_shader_inc.ptr()); } +Variant ShaderEditorPlugin::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + if (shader_list->get_item_count() == 0) { + return Variant(); + } + + int idx = shader_list->get_item_at_position(p_point); + if (idx < 0) { + return Variant(); + } + + HBoxContainer *drag_preview = memnew(HBoxContainer); + String preview_name = shader_list->get_item_text(idx); + Ref<Texture2D> preview_icon = shader_list->get_item_icon(idx); + + if (!preview_icon.is_null()) { + TextureRect *tf = memnew(TextureRect); + tf->set_texture(preview_icon); + tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + drag_preview->add_child(tf); + } + Label *label = memnew(Label(preview_name)); + drag_preview->add_child(label); + main_split->set_drag_preview(drag_preview); + + Dictionary drag_data; + drag_data["type"] = "shader_list_element"; + drag_data["shader_list_element"] = idx; + + return drag_data; +} + +bool ShaderEditorPlugin::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + Dictionary d = p_data; + if (!d.has("type")) { + return false; + } + + if (String(d["type"]) == "shader_list_element") { + return true; + } + + if (String(d["type"]) == "files") { + Vector<String> files = d["files"]; + + if (files.size() == 0) { + return false; + } + + for (int i = 0; i < files.size(); i++) { + String file = files[i]; + if (ResourceLoader::exists(file, "Shader")) { + Ref<Shader> shader = ResourceLoader::load(file); + if (shader.is_valid()) { + return true; + } + } + } + return false; + } + + return false; +} + +void ShaderEditorPlugin::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + if (!can_drop_data_fw(p_point, p_data, p_from)) { + return; + } + + Dictionary d = p_data; + if (!d.has("type")) { + return; + } + + if (String(d["type"]) == "shader_list_element") { + int idx = d["shader_list_element"]; + int new_idx = shader_list->get_item_at_position(p_point); + _move_shader_tab(idx, new_idx); + return; + } + + if (String(d["type"]) == "files") { + Vector<String> files = d["files"]; + + for (int i = 0; i < files.size(); i++) { + String file = files[i]; + if (!ResourceLoader::exists(file, "Shader")) { + continue; + } + + Ref<Resource> res = ResourceLoader::load(file); + if (res.is_valid()) { + edit(res.ptr()); + } + } + } +} + +void ShaderEditorPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("_get_drag_data_fw", "point", "from"), &ShaderEditorPlugin::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("_can_drop_data_fw", "point", "data", "from"), &ShaderEditorPlugin::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("_drop_data_fw", "point", "data", "from"), &ShaderEditorPlugin::drop_data_fw); +} + ShaderEditorPlugin::ShaderEditorPlugin() { main_split = memnew(HSplitContainer); @@ -1483,6 +1597,7 @@ ShaderEditorPlugin::ShaderEditorPlugin() { vb->add_child(shader_list); shader_list->connect("item_selected", callable_mp(this, &ShaderEditorPlugin::_shader_selected)); shader_list->connect("item_clicked", callable_mp(this, &ShaderEditorPlugin::_shader_list_clicked)); + shader_list->set_drag_forwarding(this); main_split->add_child(vb); vb->set_custom_minimum_size(Size2(200, 300) * EDSCALE); diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 0980cc4db2..afd38ef71a 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -250,6 +250,14 @@ class ShaderEditorPlugin : public EditorPlugin { void _shader_created(Ref<Shader> p_shader); void _shader_include_created(Ref<ShaderInclude> p_shader_inc); void _update_shader_list_status(); + void _move_shader_tab(int p_from, int p_to); + + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + +protected: + static void _bind_methods(); public: virtual void edit(Object *p_object) override; diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index f119ada810..54ba28833c 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -127,8 +127,8 @@ void TileAtlasView::_update_zoom_and_panning(bool p_zoom_on_mouse_pos) { } // Update the backgrounds. - background_left->update(); - background_right->update(); + background_left->set_size(base_tiles_root_control->get_custom_minimum_size()); + background_right->set_size(alternative_tiles_root_control->get_custom_minimum_size()); // Zoom on the position. if (p_zoom_on_mouse_pos) { @@ -374,13 +374,11 @@ void TileAtlasView::_draw_alternatives() { void TileAtlasView::_draw_background_left() { Ref<Texture2D> texture = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")); - background_left->set_size(base_tiles_root_control->get_custom_minimum_size()); background_left->draw_texture_rect(texture, Rect2(Vector2(), background_left->get_size()), true); } void TileAtlasView::_draw_background_right() { Ref<Texture2D> texture = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")); - background_right->set_size(alternative_tiles_root_control->get_custom_minimum_size()); background_right->draw_texture_rect(texture, Rect2(Vector2(), background_right->get_size()), true); } @@ -405,23 +403,6 @@ void TileAtlasView::set_atlas_source(TileSet *p_tile_set, TileSetAtlasSource *p_ // Update everything. _update_zoom_and_panning(); - // Change children control size. - Size2i base_tiles_control_size = _compute_base_tiles_control_size(); - for (int i = 0; i < base_tiles_drawing_root->get_child_count(); i++) { - Control *control = Object::cast_to<Control>(base_tiles_drawing_root->get_child(i)); - if (control) { - control->set_size(base_tiles_control_size); - } - } - - Size2i alternative_control_size = _compute_alternative_tiles_control_size(); - for (int i = 0; i < alternative_tiles_drawing_root->get_child_count(); i++) { - Control *control = Object::cast_to<Control>(alternative_tiles_drawing_root->get_child(i)); - if (control) { - control->set_size(alternative_control_size); - } - } - // Update. base_tiles_draw->update(); base_tiles_texture_grid->update(); @@ -613,7 +594,7 @@ TileAtlasView::TileAtlasView() { background_left = memnew(Control); background_left->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - background_left->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); + background_left->set_anchors_and_offsets_preset(Control::PRESET_TOP_LEFT); background_left->set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED); background_left->connect("draw", callable_mp(this, &TileAtlasView::_draw_background_left)); base_tiles_root_control->add_child(background_left); @@ -651,23 +632,26 @@ TileAtlasView::TileAtlasView() { alternative_tiles_root_control = memnew(Control); alternative_tiles_root_control->set_mouse_filter(Control::MOUSE_FILTER_PASS); + alternative_tiles_root_control->set_v_size_flags(Control::SIZE_EXPAND_FILL); alternative_tiles_root_control->connect("gui_input", callable_mp(this, &TileAtlasView::_alternative_tiles_root_control_gui_input)); right_vbox->add_child(alternative_tiles_root_control); background_right = memnew(Control); background_right->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); + background_right->set_anchors_and_offsets_preset(Control::PRESET_TOP_LEFT); background_right->set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED); background_right->connect("draw", callable_mp(this, &TileAtlasView::_draw_background_right)); - alternative_tiles_root_control->add_child(background_right); alternative_tiles_drawing_root = memnew(Control); alternative_tiles_drawing_root->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); + alternative_tiles_drawing_root->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); alternative_tiles_drawing_root->set_texture_filter(TEXTURE_FILTER_NEAREST); alternative_tiles_root_control->add_child(alternative_tiles_drawing_root); alternatives_draw = memnew(Control); alternatives_draw->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); + alternatives_draw->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); alternatives_draw->connect("draw", callable_mp(this, &TileAtlasView::_draw_alternatives)); alternative_tiles_drawing_root->add_child(alternatives_draw); } diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h index 196a642283..1c0b622bb1 100644 --- a/editor/plugins/tiles/tile_atlas_view.h +++ b/editor/plugins/tiles/tile_atlas_view.h @@ -136,6 +136,7 @@ public: } else { base_tiles_root_control->add_child(p_control); } + p_control->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); p_control->set_mouse_filter(Control::MOUSE_FILTER_PASS); }; @@ -149,6 +150,7 @@ public: } else { alternative_tiles_root_control->add_child(p_control); } + p_control->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); p_control->set_mouse_filter(Control::MOUSE_FILTER_PASS); }; diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 09722d3d65..6bdf279537 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -1888,7 +1888,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In alternative_tiles_control_unscaled->update(); if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) { - if (Vector2(drag_start_mouse_pos).distance_to(tile_atlas_control->get_local_mouse_position()) > 5.0 * EDSCALE) { + if (Vector2(drag_start_mouse_pos).distance_to(alternative_tiles_control->get_local_mouse_position()) > 5.0 * EDSCALE) { drag_type = DRAG_TYPE_NONE; } } @@ -1896,8 +1896,6 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - drag_type = DRAG_TYPE_NONE; - Vector2 mouse_local_pos = alternative_tiles_control->get_local_mouse_position(); if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { @@ -1919,25 +1917,29 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In if (mb->is_pressed()) { drag_type = DRAG_TYPE_MAY_POPUP_MENU; drag_start_mouse_pos = alternative_tiles_control->get_local_mouse_position(); - } else if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) { - // Right click released and wasn't dragged too far - Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos); + } else { + if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) { + // Right click released and wasn't dragged too far + Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos); - selection.clear(); - TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) }; - if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) { - selection.insert(selected); - } + selection.clear(); + TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) }; + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) { + selection.insert(selected); + } - _update_tile_inspector(); - _update_tile_id_label(); + _update_tile_inspector(); + _update_tile_id_label(); - if (selection.size() == 1) { - selected = selection.front()->get(); - menu_option_coords = selected.tile; - menu_option_alternative = selected.alternative; - alternative_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i())); + if (selection.size() == 1) { + selected = selection.front()->get(); + menu_option_coords = selected.tile; + menu_option_alternative = selected.alternative; + alternative_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i())); + } } + + drag_type = DRAG_TYPE_NONE; } } tile_atlas_control->update(); @@ -2524,7 +2526,6 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control); tile_atlas_control_unscaled = memnew(Control); - tile_atlas_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); tile_atlas_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw)); tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control_unscaled, false); tile_atlas_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); @@ -2541,7 +2542,6 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control); alternative_tiles_control_unscaled = memnew(Control); - alternative_tiles_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); alternative_tiles_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw)); tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control_unscaled, false); alternative_tiles_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 961f092650..e048ee2698 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4312,6 +4312,9 @@ void VisualShaderEditor::_update_varying_tree() { case VisualShader::VARYING_TYPE_FLOAT: item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons"))); break; + case VisualShader::VARYING_TYPE_INT: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("int"), SNAME("EditorIcons"))); + break; case VisualShader::VARYING_TYPE_VECTOR_2D: item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons"))); break; @@ -4321,8 +4324,8 @@ void VisualShaderEditor::_update_varying_tree() { case VisualShader::VARYING_TYPE_VECTOR_4D: item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons"))); break; - case VisualShader::VARYING_TYPE_COLOR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Color"), SNAME("EditorIcons"))); + case VisualShader::VARYING_TYPE_BOOLEAN: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("bool"), SNAME("EditorIcons"))); break; case VisualShader::VARYING_TYPE_TRANSFORM: item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons"))); @@ -4963,10 +4966,11 @@ VisualShaderEditor::VisualShaderEditor() { varying_type = memnew(OptionButton); hb->add_child(varying_type); varying_type->add_item("Float"); + varying_type->add_item("Int"); varying_type->add_item("Vector2"); varying_type->add_item("Vector3"); varying_type->add_item("Vector4"); - varying_type->add_item("Color"); + varying_type->add_item("Boolean"); varying_type->add_item("Transform"); varying_name = memnew(LineEdit); @@ -5759,10 +5763,11 @@ public: Ref<Texture2D> type_icon[] = { EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("int"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons")), - EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")), }; diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index e07a445ce3..04c73e16ab 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -76,8 +76,7 @@ static const char *enum_renames[][2] = { { "ARVR_STEREO", "XR_STEREO" }, // XRInterface { "ARVR_UNKNOWN_TRACKING", "XR_UNKNOWN_TRACKING" }, // XRInterface { "BAKE_ERROR_INVALID_MESH", "BAKE_ERROR_MESHES_INVALID" }, // LightmapGI - { "BODY_MODE_CHARACTER", "BODY_MODE_DYNAMIC" }, // PhysicsServer2D - { "BODY_MODE_DYNAMIC_LOCKED", "BODY_MODE_DYNAMIC_LINEAR" }, // PhysicsServer3D + { "BODY_MODE_CHARACTER", "BODY_MODE_RIGID_LINEAR" }, // PhysicsServer { "BUTTON_LEFT", "MOUSE_BUTTON_LEFT" }, // Globals { "BUTTON_MASK_LEFT", "MOUSE_BUTTON_MASK_LEFT" }, // Globals { "BUTTON_MASK_MIDDLE", "MOUSE_BUTTON_MASK_MIDDLE" }, // Globals @@ -125,15 +124,13 @@ static const char *enum_renames[][2] = { { "MATH_RAND", "MATH_RANDF_RANGE" }, // VisualScriptBuiltinFunc { "MATH_RANDOM", "MATH_RANDI_RANGE" }, // VisualScriptBuiltinFunc { "MATH_STEPIFY", "MATH_STEP_DECIMALS" }, // VisualScriptBuiltinFunc - { "MODE_CHARACTER", "MODE_DYNAMIC_LOCKED" }, // RigidBody2D, RigidBody3D - { "MODE_KINEMATIC", "FREEZE_MODE_KINEMATIC" }, // RigidDynamicBody + { "MODE_KINEMATIC", "FREEZE_MODE_KINEMATIC" }, // RigidBody { "MODE_OPEN_ANY", "FILE_MODE_OPEN_ANY" }, // FileDialog { "MODE_OPEN_DIR", "FILE_MODE_OPEN_DIR" }, // FileDialog { "MODE_OPEN_FILE", "FILE_MODE_OPEN_FILE" }, // FileDialog { "MODE_OPEN_FILES", "FILE_MODE_OPEN_FILES" }, // FileDialog - { "MODE_RIGID", "MODE_DYNAMIC" }, // RigidBody2D, RigidBody3D { "MODE_SAVE_FILE", "FILE_MODE_SAVE_FILE" }, // FileDialog - { "MODE_STATIC", "FREEZE_MODE_STATIC" }, // RigidDynamicBody + { "MODE_STATIC", "FREEZE_MODE_STATIC" }, // RigidBody { "NOTIFICATION_APP_PAUSED", "NOTIFICATION_APPLICATION_PAUSED" }, // MainLoop { "NOTIFICATION_APP_RESUMED", "NOTIFICATION_APPLICATION_RESUMED" }, // MainLoop { "NOTIFICATION_PATH_CHANGED", "NOTIFICATION_PATH_RENAMED" }, //Node @@ -201,11 +198,12 @@ static const char *gdscript_function_renames[][2] = { // { "set_color", "surface_set_color"}, // ImmediateMesh broke Light2D, Theme, SurfaceTool // { "set_event", "set_shortcut" }, // BaseButton - Cyclic Rename // { "set_extents", "set_size"}, // BoxShape, RectangleShape broke ReflectionProbe - // { "set_flag", "set_particle_flag"}, // ParticlesMaterial broke Window, HingeJoint3D + // { "set_flag", "set_particle_flag"}, // ParticleProcessMaterial broke Window, HingeJoint3D // { "set_h_offset", "set_drag_horizontal_offset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D // { "set_margin", "set_offset" }, // Control broke Shape3D, AtlasTexture // { "set_mode", "set_mode_file_mode" }, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap // { "set_normal", "surface_set_normal"}, // ImmediateGeometry broke SurfaceTool, WorldMarginShape2D + // { "set_offset", "set_progress" }, // PathFollow2D, PathFollow3D - Too common // { "set_process_mode", "set_process_callback" }, // AnimationTree broke Node, Tween, Sky // { "set_refuse_new_network_connections", "set_refuse_new_connections"}, // MultiplayerAPI broke SceneTree // { "set_uv", "surface_set_uv" }, // ImmediateMesh broke Polygon2D @@ -220,16 +218,16 @@ static const char *gdscript_function_renames[][2] = { { "_update_wrap_at", "_update_wrap_at_column" }, // TextEdit { "add_animation", "add_animation_library" }, // AnimationPlayer { "add_cancel", "add_cancel_button" }, // AcceptDialog - { "add_central_force", "apply_central_force" }, //RigidDynamicBody2D + { "add_central_force", "apply_central_force" }, //RigidBody2D { "add_child_below_node", "add_sibling" }, // Node { "add_color_override", "add_theme_color_override" }, // Control { "add_constant_override", "add_theme_constant_override" }, // Control { "add_font_override", "add_theme_font_override" }, // Control - { "add_force", "apply_force" }, //RigidDynamicBody2D + { "add_force", "apply_force" }, //RigidBody2D { "add_icon_override", "add_theme_icon_override" }, // Control { "add_scene_import_plugin", "add_scene_format_importer_plugin" }, //EditorPlugin { "add_stylebox_override", "add_theme_stylebox_override" }, // Control - { "add_torque", "apply_torque" }, //RigidDynamicBody2D + { "add_torque", "apply_torque" }, //RigidBody2D { "apply_changes", "_apply_changes" }, // EditorPlugin { "bind_child_node_to_bone", "set_bone_children" }, // Skeleton3D { "body_add_force", "body_apply_force" }, // PhysicsServer2D @@ -275,8 +273,8 @@ static const char *gdscript_function_renames[][2] = { { "get_action_list", "action_get_events" }, // InputMap { "get_alt", "is_alt_pressed" }, // InputEventWithModifiers { "get_animation_process_mode", "get_process_callback" }, // AnimationPlayer - { "get_applied_force", "get_constant_force" }, //RigidDynamicBody2D - { "get_applied_torque", "get_constant_torque" }, //RigidDynamicBody2D + { "get_applied_force", "get_constant_force" }, //RigidBody2D + { "get_applied_torque", "get_constant_torque" }, //RigidBody2D { "get_audio_bus", "get_audio_bus_name" }, // Area3D { "get_bound_child_nodes_to_bone", "get_bone_children" }, // Skeleton3D { "get_camera", "get_camera_3d" }, // Viewport -> this is also convertable to get_camera_2d, broke GLTFNode @@ -371,6 +369,7 @@ static const char *gdscript_function_renames[][2] = { { "get_theme_item_types", "get_theme_item_type_list" }, // Theme { "get_timer_process_mode", "get_timer_process_callback" }, // Timer { "get_translation", "get_position" }, // Node3D broke GLTFNode which is used rarely + { "get_unit_offset", "get_progress_ratio" }, // PathFollow2D, PathFollow3D { "get_use_in_baked_light", "is_baking_navigation" }, // GridMap { "get_used_cells_by_id", "get_used_cells" }, // TileMap { "get_v_scrollbar", "get_v_scroll_bar" }, //ScrollContainer @@ -532,6 +531,7 @@ static const char *gdscript_function_renames[][2] = { { "set_timer_process_mode", "set_timer_process_callback" }, // Timer { "set_tonemap_auto_exposure", "set_tonemap_auto_exposure_enabled" }, // Environment { "set_translation", "set_position" }, // Node3D - this broke GLTFNode which is used rarely + { "set_unit_offset", "set_progress_ratio" }, // PathFollow2D, PathFollow3D { "set_uv2", "surface_set_uv2" }, // ImmediateMesh broke Surffacetool { "set_v_drag_enabled", "set_drag_vertical_enabled" }, // Camera2D { "set_valign", "set_vertical_alignment" }, // Label @@ -566,9 +566,23 @@ static const char *gdscript_function_renames[][2] = { { "to_utf8", "to_utf8_buffer" }, // String { "to_wchar", "to_utf32_buffer" }, // String // TODO - utf32 or utf16? - // Globals + // @GlobalScope + { "bytes2var", "bytes_to_var" }, + { "bytes2var_with_objects", "bytes_to_var_with_objects" }, + { "db2linear", "db_to_linear" }, + { "deg2rad", "deg_to_rad" }, + { "linear2db", "linear_to_db" }, + { "rad2deg", "rad_to_deg" }, { "rand_range", "randf_range" }, { "stepify", "snapped" }, + { "str2var", "str_to_var" }, + { "var2str", "var_to_str" }, + { "var2bytes", "var_to_bytes" }, + { "var2bytes_with_objects", "var_to_bytes_with_objects" }, + + // @GDScript + { "dict2inst", "dict_to_inst" }, + { "inst2dict", "inst_to_dict" }, { nullptr, nullptr }, }; @@ -607,11 +621,12 @@ static const char *csharp_function_renames[][2] = { // { "SetColor", "SurfaceSetColor"}, // ImmediateMesh broke Light2D, Theme, SurfaceTool // { "SetEvent", "SetShortcut" }, // BaseButton - Cyclic Rename // { "SetExtents", "SetSize"}, // BoxShape, RectangleShape broke ReflectionProbe - // { "SetFlag", "SetParticleFlag"}, // ParticlesMaterial broke Window, HingeJoint3D + // { "SetFlag", "SetParticleFlag"}, // ParticleProcessMaterial broke Window, HingeJoint3D // { "SetHOffset", "SetDragHorizontalOffset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D // { "SetMargin", "SetOffset" }, // Control broke Shape3D, AtlasTexture // { "SetMode", "SetModeFileMode" }, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap // { "SetNormal", "SurfaceSetNormal"}, // ImmediateGeometry broke SurfaceTool, WorldMarginShape2D + // { "SetOffset", "SetProgress" }, // PathFollow2D, PathFollow3D - Too common // { "SetProcessMode", "SetProcessCallback" }, // AnimationTree broke Node, Tween, Sky // { "SetRefuseNewNetworkConnections", "SetRefuseNewConnections"}, // MultiplayerAPI broke SceneTree // { "SetUv", "SurfaceSetUv" }, // ImmediateMesh broke Polygon2D @@ -627,16 +642,16 @@ static const char *csharp_function_renames[][2] = { { "_UpdateWrapAt", "_UpdateWrapAtColumn" }, // TextEdit { "AddAnimation", "AddAnimationLibrary" }, // AnimationPlayer { "AddCancel", "AddCancelButton" }, // AcceptDialog - { "AddCentralForce", "AddConstantCentralForce" }, //RigidDynamicBody2D + { "AddCentralForce", "AddConstantCentralForce" }, //RigidBody2D { "AddChildBelowNode", "AddSibling" }, // Node { "AddColorOverride", "AddThemeColorOverride" }, // Control { "AddConstantOverride", "AddThemeConstantOverride" }, // Control { "AddFontOverride", "AddThemeFontOverride" }, // Control - { "AddForce", "AddConstantForce" }, //RigidDynamicBody2D + { "AddForce", "AddConstantForce" }, //RigidBody2D { "AddIconOverride", "AddThemeIconOverride" }, // Control { "AddSceneImportPlugin", "AddSceneFormatImporterPlugin" }, //EditorPlugin { "AddStyleboxOverride", "AddThemeStyleboxOverride" }, // Control - { "AddTorque", "AddConstantTorque" }, //RigidDynamicBody2D + { "AddTorque", "AddConstantTorque" }, //RigidBody2D { "BindChildNodeToBone", "SetBoneChildren" }, // Skeleton3D { "BumpmapToNormalmap", "BumpMapToNormalMap" }, // Image { "CanBeHidden", "_CanBeHidden" }, // EditorNode3DGizmoPlugin @@ -675,8 +690,8 @@ static const char *csharp_function_renames[][2] = { { "GetActionList", "ActionGetEvents" }, // InputMap { "GetAlt", "IsAltPressed" }, // InputEventWithModifiers { "GetAnimationProcessMode", "GetProcessCallback" }, // AnimationPlayer - { "GetAppliedForce", "GetConstantForce" }, //RigidDynamicBody2D - { "GetAppliedTorque", "GetConstantTorque" }, //RigidDynamicBody2D + { "GetAppliedForce", "GetConstantForce" }, //RigidBody2D + { "GetAppliedTorque", "GetConstantTorque" }, //RigidBody2D { "GetAudioBus", "GetAudioBusName" }, // Area3D { "GetBoundChildNodesToBone", "GetBoneChildren" }, // Skeleton3D { "GetCamera", "GetCamera3d" }, // Viewport -> this is also convertable to getCamera2d, broke GLTFNode @@ -767,6 +782,7 @@ static const char *csharp_function_renames[][2] = { { "GetThemeItemTypes", "GetThemeItemTypeList" }, // Theme { "GetTimerProcessMode", "GetTimerProcessCallback" }, // Timer { "GetTranslation", "GetPosition" }, // Node3D broke GLTFNode which is used rarely + { "GetUnitOffset", "GetProgressRatio" }, // PathFollow2D, PathFollow3D { "GetUseInBakedLight", "IsBakingNavigation" }, // GridMap { "GetUsedCellsById", "GetUsedCells" }, // TileMap { "GetVScrollbar", "GetVScrollBar" }, //ScrollContainer @@ -918,6 +934,7 @@ static const char *csharp_function_renames[][2] = { { "SetTimerProcessMode", "SetTimerProcessCallback" }, // Timer { "SetTonemapAutoExposure", "SetTonemapAutoExposureEnabled" }, // Environment { "SetTranslation", "SetPosition" }, // Node3D - this broke GLTFNode which is used rarely + { "SetUnitOffset", "SetProgressRatio" }, // PathFollow2D, PathFollow3D { "SetUv2", "SurfaceSetUv2" }, // ImmediateMesh broke Surffacetool { "SetVDragEnabled", "SetDragVerticalEnabled" }, // Camera2D { "SetValign", "SetVerticalAlignment" }, // Label @@ -952,9 +969,23 @@ static const char *csharp_function_renames[][2] = { { "ToUtf8", "ToUtf8Buffer" }, // String { "ToWchar", "ToUtf32Buffer" }, // String // TODO - utf32 or utf16? - // Globals + // @GlobalScope + { "Bytes2Var", "BytesToVar" }, + { "Bytes2VarWithObjects", "BytesToVarWithObjects" }, + { "Db2Linear", "DbToLinear" }, + { "Deg2Rad", "DegToRad" }, + { "Linear2Db", "LinearToDb" }, + { "Rad2Deg", "RadToDeg" }, { "RandRange", "RandfRange" }, { "Stepify", "Snapped" }, + { "Str2Var", "StrToVar" }, + { "Var2Str", "VarToStr" }, + { "Var2Bytes", "VarToBytes" }, + { "Var2BytesWithObjects", "VarToBytesWithObjects" }, + + // @GDScript + { "Dict2Inst", "DictToInst" }, + { "Inst2Dict", "InstToDict" }, { nullptr, nullptr }, }; @@ -969,6 +1000,7 @@ static const char *gdscript_properties_renames[][2] = { // // {"meta","meta_pressed"},// This may broke a lot of comments and user variables // // {"pause_mode","process_mode"}, // Node - Cyclic rename, look for others // // {"rotate","rotates"}, // PathFollow2D - probably function exists with same name + // // {"offset","progress"}, // PathFollow2D, PathFollow3D - Name is way too vague // // {"shift","shift_pressed"},// This may broke a lot of comments and user variables // { "autowrap", "autowrap_mode" }, // Label // { "cast_to", "target_position" }, // RayCast2D, RayCast3D @@ -990,6 +1022,7 @@ static const char *gdscript_properties_renames[][2] = { { "close_h_ofs", "close_h_offset" }, // Theme { "close_v_ofs", "close_v_offset" }, // Theme { "commentfocus", "comment_focus" }, // Theme + { "contacts_reported", "max_contacts_reported" }, // RigidBody { "drag_margin_bottom", "drag_bottom_margin" }, // Camera2D { "drag_margin_h_enabled", "drag_horizontal_enabled" }, // Camera2D { "drag_margin_left", "drag_left_margin" }, // Camera2D @@ -1008,6 +1041,7 @@ static const char *gdscript_properties_renames[][2] = { { "gravity_vec", "gravity_direction" }, // Area2D { "hseparation", "h_separation" }, // Theme { "iterations_per_second", "physics_ticks_per_second" }, // Engine + { "invert_enable", "invert_enabled" }, // Polygon2D { "margin_bottom", "offset_bottom" }, // Control broke NinePatchRect, StyleBox { "margin_left", "offset_left" }, // Control broke NinePatchRect, StyleBox { "margin_right", "offset_right" }, // Control broke NinePatchRect, StyleBox @@ -1036,6 +1070,7 @@ static const char *gdscript_properties_renames[][2] = { { "table_hseparation", "table_h_separation" }, // Theme { "table_vseparation", "table_v_separation" }, // Theme { "translation", "position" }, // Node3D - broke GLTFNode + { "unit_offset", "progress_ratio" }, // PathFollow2D, PathFollow3D { "vseparation", "v_separation" }, // Theme { nullptr, nullptr }, @@ -1051,6 +1086,7 @@ static const char *csharp_properties_renames[][2] = { // // {"Meta","MetaPressed"},// This may broke a lot of comments and user variables // // {"PauseMode","ProcessMode"}, // Node - Cyclic rename, look for others // // {"Rotate","Rotates"}, // PathFollow2D - probably function exists with same name + // // {"Offset","Progress"}, // PathFollow2D, PathFollow3D - Name is way too vague // // {"Shift","ShiftPressed"},// This may broke a lot of comments and user variables // { "Autowrap", "AutowrapMode" }, // Label // { "CastTo", "TargetPosition" }, // RayCast2D, RayCast3D @@ -1089,6 +1125,7 @@ static const char *csharp_properties_renames[][2] = { { "GravityVec", "GravityDirection" }, // Area2D { "Hseparation", "HSeparation" }, // Theme { "IterationsPerSecond", "PhysicsTicksPerSecond" }, // Engine + { "InvertEnable", "InvertEnabled" }, // Polygon2D { "MarginBottom", "OffsetBottom" }, // Control broke NinePatchRect, StyleBox { "MarginLeft", "OffsetLeft" }, // Control broke NinePatchRect, StyleBox { "MarginRight", "OffsetRight" }, // Control broke NinePatchRect, StyleBox @@ -1117,6 +1154,7 @@ static const char *csharp_properties_renames[][2] = { { "TableHseparation", "TableHSeparation" }, // Theme { "TableVseparation", "TableVSeparation" }, // Theme { "Translation", "Position" }, // Node3D - broke GLTFNode + { "UnitOffset", "ProgressRatio" }, // PathFollow2D, PathFollow3D { "Vseparation", "VSeparation" }, // Theme { nullptr, nullptr }, @@ -1344,6 +1382,7 @@ static const char *class_renames[][2] = { { "PanoramaSky", "Sky" }, { "Particles", "GPUParticles3D" }, // Be careful, this will be used everywhere { "Particles2D", "GPUParticles2D" }, + { "ParticlesMaterial", "ParticleProcessMaterial" }, { "Path", "Path3D" }, // Be careful, this will be used everywhere { "PathFollow", "PathFollow3D" }, { "PhysicalBone", "PhysicalBone3D" }, @@ -1371,15 +1410,14 @@ static const char *class_renames[][2] = { { "Reference", "RefCounted" }, // Be careful, this will be used everywhere { "RemoteTransform", "RemoteTransform3D" }, { "ResourceInteractiveLoader", "ResourceLoader" }, - { "RigidBody", "RigidDynamicBody3D" }, - { "RigidBody2D", "RigidDynamicBody2D" }, + { "RigidBody", "RigidBody3D" }, { "SceneTreeTween", "Tween" }, { "Shape", "Shape3D" }, // Be careful, this will be used everywhere { "ShortCut", "Shortcut" }, { "Skeleton", "Skeleton3D" }, { "SkeletonIK", "SkeletonIK3D" }, { "SliderJoint", "SliderJoint3D" }, - { "SoftBody", "SoftDynamicBody3D" }, + { "SoftBody", "SoftBody3D" }, { "Spatial", "Node3D" }, { "SpatialGizmo", "Node3DGizmo" }, { "SpatialMaterial", "StandardMaterial3D" }, diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 77e0321f83..15e992ce18 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -166,6 +166,7 @@ void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_ class_name->deselect(); parent_name->set_text(p_base_name); parent_name->deselect(); + internal_name->set_text(""); if (!p_base_path.is_empty()) { initial_bp = p_base_path.get_basename(); diff --git a/main/main.cpp b/main/main.cpp index 8a25827e02..126ac59070 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -725,11 +725,16 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->get()); forwardable_cli_arguments[CLI_SCOPE_PROJECT].push_back(I->get()); } - if (I->get() == "--single-window" || - I->get() == "--audio-driver" || + if (I->get() == "--single-window") { + forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->get()); + } + if (I->get() == "--audio-driver" || I->get() == "--display-driver" || I->get() == "--rendering-driver") { - forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->get()); + if (I->next()) { + forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->get()); + forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->next()->get()); + } } #endif diff --git a/methods.py b/methods.py index c02517d137..9b60d4251f 100644 --- a/methods.py +++ b/methods.py @@ -540,7 +540,7 @@ def detect_visual_c_compiler_version(tools_env): # and not scons setup environment (env)... so make sure you call the right environment on it or it will fail to detect # the proper vc version that will be called - # There is no flag to give to visual c compilers to set the architecture, i.e. scons bits argument (32,64,ARM etc) + # There is no flag to give to visual c compilers to set the architecture, i.e. scons arch argument (x86_32, x86_64, arm64, etc.). # There are many different cl.exe files that are run, and each one compiles & links to a different architecture # As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program() # is to check the PATH variable and figure out which one will be called first. Code below does that and returns: diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp index 8813c3827a..ae03abca50 100644 --- a/modules/bmp/image_loader_bmp.cpp +++ b/modules/bmp/image_loader_bmp.cpp @@ -200,7 +200,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, return err; } -Error ImageLoaderBMP::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) { +Error ImageLoaderBMP::load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale) { bmp_header_s bmp_header; Error err = ERR_INVALID_DATA; diff --git a/modules/bmp/image_loader_bmp.h b/modules/bmp/image_loader_bmp.h index 63dee0a969..cf8346ecad 100644 --- a/modules/bmp/image_loader_bmp.h +++ b/modules/bmp/image_loader_bmp.h @@ -83,7 +83,7 @@ protected: const bmp_header_s &p_header); public: - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale); + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderBMP(); }; diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 243c23342e..6294790132 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1838,7 +1838,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { u_step *= curve_length / path_u_distance; } double v_step = 1.0 / shape_sides; - double spin_step = Math::deg2rad(spin_degrees / spin_sides); + double spin_step = Math::deg_to_rad(spin_degrees / spin_sides); double extrusion_step = 1.0 / extrusions; if (mode == MODE_PATH) { if (path_joined) { @@ -1902,7 +1902,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } } - real_t angle_simplify_dot = Math::cos(Math::deg2rad(path_simplify_angle)); + real_t angle_simplify_dot = Math::cos(Math::deg_to_rad(path_simplify_angle)); Vector3 previous_simplify_dir = Vector3(0, 0, 0); int faces_combined = 0; diff --git a/modules/denoise/config.py b/modules/denoise/config.py index 521115dae5..350839651a 100644 --- a/modules/denoise/config.py +++ b/modules/denoise/config.py @@ -5,14 +5,7 @@ def can_build(env, platform): # as doing lightmap generation and denoising on Android or HTML5 # would be a bit far-fetched. desktop_platforms = ["linuxbsd", "macos", "windows"] - supported_arch = env["bits"] == "64" - if env["arch"] == "arm64": - supported_arch = False - if env["arch"].startswith("ppc"): - supported_arch = False - if env["arch"].startswith("rv"): - supported_arch = False - return env["tools"] and platform in desktop_platforms and supported_arch + return env["tools"] and platform in desktop_platforms and env["arch"] == "x86_64" def configure(env): diff --git a/modules/enet/doc_classes/ENetPacketPeer.xml b/modules/enet/doc_classes/ENetPacketPeer.xml index 46008317a2..67760ba5e8 100644 --- a/modules/enet/doc_classes/ENetPacketPeer.xml +++ b/modules/enet/doc_classes/ENetPacketPeer.xml @@ -18,6 +18,18 @@ Returns the number of channels allocated for communication with peer. </description> </method> + <method name="get_remote_address" qualifiers="const"> + <return type="String" /> + <description> + Returns the IP address of this peer. + </description> + </method> + <method name="get_remote_port" qualifiers="const"> + <return type="int" /> + <description> + Returns the remote port of this peer. + </description> + </method> <method name="get_state" qualifiers="const"> <return type="int" enum="ENetPacketPeer.PeerState" /> <description> diff --git a/modules/enet/enet_packet_peer.cpp b/modules/enet/enet_packet_peer.cpp index 62c0550edb..5a96f75c4f 100644 --- a/modules/enet/enet_packet_peer.cpp +++ b/modules/enet/enet_packet_peer.cpp @@ -206,6 +206,8 @@ void ENetPacketPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("send", "channel", "packet", "flags"), &ENetPacketPeer::_send); ClassDB::bind_method(D_METHOD("throttle_configure", "interval", "acceleration", "deceleration"), &ENetPacketPeer::throttle_configure); ClassDB::bind_method(D_METHOD("set_timeout", "timeout", "timeout_min", "timeout_max"), &ENetPacketPeer::set_timeout); + ClassDB::bind_method(D_METHOD("get_remote_address"), &ENetPacketPeer::get_remote_address); + ClassDB::bind_method(D_METHOD("get_remote_port"), &ENetPacketPeer::get_remote_port); ClassDB::bind_method(D_METHOD("get_statistic", "statistic"), &ENetPacketPeer::get_statistic); ClassDB::bind_method(D_METHOD("get_state"), &ENetPacketPeer::get_state); ClassDB::bind_method(D_METHOD("get_channels"), &ENetPacketPeer::get_channels); diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index a44be04b2d..c2301c3e27 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -74,11 +74,11 @@ [/codeblock] </description> </method> - <method name="dict2inst"> + <method name="dict_to_inst"> <return type="Object" /> <param index="0" name="dictionary" type="Dictionary" /> <description> - Converts a dictionary (previously created with [method inst2dict]) back to an instance. Useful for deserializing. + Converts a [param dictionary] (previously created with [method inst_to_dict]) back to an Object instance. Useful for deserializing. </description> </method> <method name="get_stack"> @@ -102,15 +102,15 @@ [b]Note:[/b] Not supported for calling from threads. Instead, this will return an empty array. </description> </method> - <method name="inst2dict"> + <method name="inst_to_dict"> <return type="Dictionary" /> <param index="0" name="instance" type="Object" /> <description> - Returns the passed instance converted to a dictionary (useful for serializing). + Returns the passed [param instance] converted to a Dictionary (useful for serializing). [codeblock] var foo = "bar" func _ready(): - var d = inst2dict(self) + var d = inst_to_dict(self) print(d.keys()) print(d.values()) [/codeblock] diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 681aa45c8f..b9560ea69b 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -646,13 +646,13 @@ void GDScriptSyntaxHighlighter::_update_cache() { node_path_color = Color(0.72, 0.77, 0.49); node_ref_color = Color(0.39, 0.76, 0.35); annotation_color = Color(1.0, 0.7, 0.45); - string_name_color = Color(1.0, 0.66, 0.72); + string_name_color = Color(1.0, 0.76, 0.65); } else { function_definition_color = Color(0, 0.6, 0.6); node_path_color = Color(0.18, 0.55, 0); node_ref_color = Color(0.0, 0.5, 0); annotation_color = Color(0.8, 0.37, 0); - string_name_color = Color(0.8, 0.46, 0.52); + string_name_color = Color(0.8, 0.56, 0.45); } EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color); diff --git a/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd b/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd index a379d915a9..b8fc8c75dc 100644 --- a/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd +++ b/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd @@ -6,7 +6,7 @@ extends _BASE_ const SPEED = 300.0 const JUMP_VELOCITY = -400.0 -# Get the gravity from the project settings to be synced with RigidDynamicBody nodes. +# Get the gravity from the project settings to be synced with RigidBody nodes. var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity") diff --git a/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd b/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd index 360b199e56..53bc606c9a 100644 --- a/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd +++ b/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd @@ -6,7 +6,7 @@ extends _BASE_ const SPEED = 5.0 const JUMP_VELOCITY = 4.5 -# Get the gravity from the project settings to be synced with RigidDynamicBody nodes. +# Get the gravity from the project settings to be synced with RigidBody nodes. var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index 38893a422d..bcbe8b8d2b 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -262,7 +262,7 @@ struct GDScriptUtilityFunctionsDefinitions { } } - static inline void inst2dict(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + static inline void inst_to_dict(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() == Variant::NIL) { @@ -329,7 +329,7 @@ struct GDScriptUtilityFunctionsDefinitions { } } - static inline void dict2inst(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + static inline void dict_to_inst(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() != Variant::DICTIONARY) { @@ -653,8 +653,8 @@ void GDScriptUtilityFunctions::register_functions() { REGISTER_VARARG_FUNC(str, true, Variant::STRING); REGISTER_VARARG_FUNC(range, false, Variant::ARRAY); REGISTER_CLASS_FUNC(load, false, "Resource", ARG("path", Variant::STRING)); - REGISTER_FUNC(inst2dict, false, Variant::DICTIONARY, ARG("instance", Variant::OBJECT)); - REGISTER_FUNC(dict2inst, false, Variant::OBJECT, ARG("dictionary", Variant::DICTIONARY)); + REGISTER_FUNC(inst_to_dict, false, Variant::DICTIONARY, ARG("instance", Variant::OBJECT)); + REGISTER_FUNC(dict_to_inst, false, Variant::OBJECT, ARG("dictionary", Variant::DICTIONARY)); REGISTER_FUNC_DEF(Color8, true, 255, Variant::COLOR, ARG("r8", Variant::INT), ARG("g8", Variant::INT), ARG("b8", Variant::INT), ARG("a8", Variant::INT)); REGISTER_VARARG_FUNC(print_debug, false, Variant::NIL); REGISTER_FUNC_NO_ARGS(print_stack, false, Variant::NIL); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index b913a771e1..87ba1d9869 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -5176,7 +5176,7 @@ Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex SpotLight3D *light = memnew(SpotLight3D); light->set_param(SpotLight3D::PARAM_ENERGY, intensity); light->set_param(SpotLight3D::PARAM_RANGE, range); - light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad2deg(l->outer_cone_angle)); + light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad_to_deg(l->outer_cone_angle)); light->set_color(l->color); // Line of best fit derived from guessing, see https://www.desmos.com/calculator/biiflubp8b @@ -5200,7 +5200,7 @@ Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> state, const GLTFNodeInd Ref<GLTFCamera> c = state->cameras[gltf_node->camera]; camera->set_projection(c->get_perspective() ? Camera3D::PROJECTION_PERSPECTIVE : Camera3D::PROJECTION_ORTHOGONAL); // GLTF spec (yfov) is in radians, Godot's camera (fov) is in degrees. - camera->set_fov(Math::rad2deg(c->get_fov())); + camera->set_fov(Math::rad_to_deg(c->get_fov())); // GLTF spec (xmag and ymag) is a radius in meters, Godot's camera (size) is a diameter in meters. camera->set_size(c->get_size_mag() * 2.0f); camera->set_near(c->get_depth_near()); @@ -5215,7 +5215,7 @@ GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera3D *p_ c.instantiate(); c->set_perspective(p_camera->get_projection() == Camera3D::ProjectionType::PROJECTION_PERSPECTIVE); // GLTF spec (yfov) is in radians, Godot's camera (fov) is in degrees. - c->set_fov(Math::deg2rad(p_camera->get_fov())); + c->set_fov(Math::deg_to_rad(p_camera->get_fov())); // GLTF spec (xmag and ymag) is a radius in meters, Godot's camera (size) is a diameter in meters. c->set_size_mag(p_camera->get_size() * 0.5f); c->set_depth_far(p_camera->get_far()); @@ -5246,7 +5246,7 @@ GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> state, Light3D *p_lig SpotLight3D *light = cast_to<SpotLight3D>(p_light); l->range = light->get_param(SpotLight3D::PARAM_RANGE); l->intensity = light->get_param(SpotLight3D::PARAM_ENERGY); - l->outer_cone_angle = Math::deg2rad(light->get_param(SpotLight3D::PARAM_SPOT_ANGLE)); + l->outer_cone_angle = Math::deg_to_rad(light->get_param(SpotLight3D::PARAM_SPOT_ANGLE)); // This equation is the inverse of the import equation (which has a desmos link). float angle_ratio = 1 - (0.2 / (0.1 + light->get_param(SpotLight3D::PARAM_SPOT_ATTENUATION))); diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index cc1ca9131d..dbbccc9bcc 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -73,8 +73,8 @@ static void _editor_init() { Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (blender3_path.is_empty()) { WARN_PRINT("Blend file import is enabled in the project settings, but no Blender path is configured in the editor settings. Blend files will not be imported."); - } else if (!da->file_exists(blender3_path)) { - WARN_PRINT("Blend file import is enabled, but the Blender path doesn't point to an accessible file. Blend files will not be imported."); + } else if (!da->dir_exists(blender3_path)) { + WARN_PRINT("Blend file import is enabled, but the Blender path doesn't point to an accessible directory. Blend files will not be imported."); } else { Ref<EditorSceneFormatImporterBlend> importer; importer.instantiate(); diff --git a/modules/gltf/structures/gltf_camera.h b/modules/gltf/structures/gltf_camera.h index 714ec21693..8e528c063f 100644 --- a/modules/gltf/structures/gltf_camera.h +++ b/modules/gltf/structures/gltf_camera.h @@ -44,7 +44,7 @@ private: // GLTF has no default camera values, they should always be specified in // the GLTF file. Here we default to Godot's default camera settings. bool perspective = true; - real_t fov = Math::deg2rad(75.0); + real_t fov = Math::deg_to_rad(75.0); real_t size_mag = 0.5; real_t depth_far = 4000.0; real_t depth_near = 0.05; diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp index eca689e87a..e7c6fe592d 100644 --- a/modules/hdr/image_loader_hdr.cpp +++ b/modules/hdr/image_loader_hdr.cpp @@ -33,7 +33,7 @@ #include "core/os/os.h" #include "core/string/print_string.h" -Error ImageLoaderHDR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) { +Error ImageLoaderHDR::load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale) { String header = f->get_token(); ERR_FAIL_COND_V_MSG(header != "#?RADIANCE" && header != "#?RGBE", ERR_FILE_UNRECOGNIZED, "Unsupported header information in HDR: " + header + "."); @@ -131,7 +131,7 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_f ptr[1] * exp / 255.0, ptr[2] * exp / 255.0); - if (p_force_linear) { + if (p_flags & FLAG_FORCE_LINEAR) { c = c.srgb_to_linear(); } diff --git a/modules/hdr/image_loader_hdr.h b/modules/hdr/image_loader_hdr.h index 16c0816562..1bff05129b 100644 --- a/modules/hdr/image_loader_hdr.h +++ b/modules/hdr/image_loader_hdr.h @@ -35,7 +35,7 @@ class ImageLoaderHDR : public ImageFormatLoader { public: - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale); + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderHDR(); }; diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp index 0e03fa65c8..3e138bf633 100644 --- a/modules/jpg/image_loader_jpegd.cpp +++ b/modules/jpg/image_loader_jpegd.cpp @@ -104,7 +104,7 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p return OK; } -Error ImageLoaderJPG::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) { +Error ImageLoaderJPG::load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale) { Vector<uint8_t> src_image; uint64_t src_image_len = f->get_length(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); diff --git a/modules/jpg/image_loader_jpegd.h b/modules/jpg/image_loader_jpegd.h index 6d631446e7..caa0461d05 100644 --- a/modules/jpg/image_loader_jpegd.h +++ b/modules/jpg/image_loader_jpegd.h @@ -35,7 +35,7 @@ class ImageLoaderJPG : public ImageFormatLoader { public: - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale); + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderJPG(); }; diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 83ac478a97..2dcf644a06 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -62,7 +62,7 @@ void LightmapperRD::add_directional_light(bool p_static, const Vector3 &p_direct l.color[2] = p_color.b; l.energy = p_energy; l.static_bake = p_static; - l.size = Math::tan(Math::deg2rad(p_angular_distance)); + l.size = Math::tan(Math::deg_to_rad(p_angular_distance)); l.shadow_blur = p_shadow_blur; lights.push_back(l); } @@ -96,7 +96,7 @@ void LightmapperRD::add_spot_light(bool p_static, const Vector3 &p_position, con l.direction[2] = p_direction.z; l.range = p_range; l.attenuation = p_attenuation; - l.cos_spot_angle = Math::cos(Math::deg2rad(p_spot_angle)); + l.cos_spot_angle = Math::cos(Math::deg_to_rad(p_spot_angle)); l.inv_spot_attenuation = 1.0f / p_spot_attenuation; l.color[0] = p_color.r; l.color[1] = p_color.g; diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index c7f9b39b48..3277f9beeb 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -3,11 +3,11 @@ import os.path def is_desktop(platform): - return platform in ["windows", "macos", "linuxbsd", "server", "uwp", "haiku"] + return platform in ["windows", "macos", "linuxbsd", "uwp", "haiku"] def is_unix_like(platform): - return platform in ["macos", "linuxbsd", "server", "android", "haiku", "ios"] + return platform in ["macos", "linuxbsd", "android", "haiku", "ios"] def module_supports_tools_on(platform): @@ -18,7 +18,7 @@ def configure(env, env_mono): # is_android = env["platform"] == "android" # is_javascript = env["platform"] == "javascript" # is_ios = env["platform"] == "ios" - # is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"] + # is_ios_sim = is_ios and env["arch"] in ["x86_32", "x86_64"] tools_enabled = env["tools"] @@ -82,7 +82,7 @@ def find_dotnet_app_host_dir(env): dotnet_root = env["dotnet_root"] if not dotnet_root: - dotnet_cmd = find_executable("dotnet") + dotnet_cmd = find_dotnet_executable(env["arch"]) if dotnet_cmd: sdk_path = find_dotnet_sdk(dotnet_cmd, dotnet_version) if sdk_path: @@ -128,27 +128,22 @@ def find_dotnet_app_host_dir(env): def determine_runtime_identifier(env): + # The keys are Godot's names, the values are the Microsoft's names. + # List: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog names_map = { "windows": "win", "macos": "osx", "linuxbsd": "linux", - "server": "linux", # FIXME: Is server linux only, or also macos? } - - # .NET RID architectures: x86, x64, arm, or arm64 - + arch_map = { + "x86_64": "x64", + "x86_32": "x86", + "arm64": "arm64", + "arm32": "arm", + } platform = env["platform"] - if is_desktop(platform): - if env["arch"] in ["arm", "arm32"]: - rid = "arm" - elif env["arch"] == "arm64": - rid = "arm64" - else: - bits = env["bits"] - bit_arch_map = {"64": "x64", "32": "x86"} - rid = bit_arch_map[bits] - return "%s-%s" % (names_map[platform], rid) + return "%s-%s" % (names_map[platform], arch_map[env["arch"]]) else: raise NotImplementedError() @@ -186,6 +181,35 @@ def find_app_host_version(dotnet_cmd, search_version_str): return "" +def find_dotnet_arch(dotnet_cmd): + import subprocess + + try: + env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US") + lines = subprocess.check_output([dotnet_cmd, "--info"], env=env).splitlines() + + for line_bytes in lines: + line = line_bytes.decode("utf-8") + + parts = line.split(":", 1) + if len(parts) < 2: + continue + + arch_str = parts[0].strip() + if arch_str != "Architecture": + continue + + arch_value = parts[1].strip() + arch_map = {"x64": "x86_64", "x86": "x86_32", "arm64": "arm64", "arm32": "arm32"} + return arch_map[arch_value] + except (subprocess.CalledProcessError, OSError) as e: + import sys + + print(e, file=sys.stderr) + + return "" + + def find_dotnet_sdk(dotnet_cmd, search_version_str): import subprocess from distutils.version import LooseVersion @@ -248,24 +272,44 @@ def find_dotnet_cli_rid(dotnet_cmd): ENV_PATH_SEP = ";" if os.name == "nt" else ":" -def find_executable(name): +def find_dotnet_executable(arch): is_windows = os.name == "nt" windows_exts = os.environ["PATHEXT"].split(ENV_PATH_SEP) if is_windows else None path_dirs = os.environ["PATH"].split(ENV_PATH_SEP) search_dirs = path_dirs + [os.getcwd()] # cwd is last in the list + for dir in path_dirs: + search_dirs += [ + os.path.join(dir, "x64"), + os.path.join(dir, "x86"), + os.path.join(dir, "arm64"), + os.path.join(dir, "arm32"), + ] # search subfolders for cross compiling + + # `dotnet --info` may not specify architecture. In such cases, + # we fallback to the first one we find without architecture. + sdk_path_unknown_arch = "" + for dir in search_dirs: - path = os.path.join(dir, name) + path = os.path.join(dir, "dotnet") if is_windows: for extension in windows_exts: path_with_ext = path + extension if os.path.isfile(path_with_ext) and os.access(path_with_ext, os.X_OK): - return path_with_ext + sdk_arch = find_dotnet_arch(path_with_ext) + if sdk_arch == arch or arch == "": + return path_with_ext + elif sdk_arch == "": + sdk_path_unknown_arch = path_with_ext else: if os.path.isfile(path) and os.access(path, os.X_OK): - return path + sdk_arch = find_dotnet_arch(path) + if sdk_arch == arch or arch == "": + return path + elif sdk_arch == "": + sdk_path_unknown_arch = path - return "" + return sdk_path_unknown_arch diff --git a/modules/mono/config.py b/modules/mono/config.py index d156877929..b599414a2c 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -1,6 +1,6 @@ -# Prior to .NET Core, we supported these: ["windows", "macos", "linuxbsd", "server", "android", "haiku", "javascript", "ios"] +# Prior to .NET Core, we supported these: ["windows", "macos", "linuxbsd", "android", "haiku", "javascript", "ios"] # Eventually support for each them should be added back (except Haiku if not supported by .NET Core) -supported_platforms = ["windows", "macos", "linuxbsd", "server"] +supported_platforms = ["windows", "macos", "linuxbsd"] def can_build(env, platform): diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props index 652b9e8e43..ad41ab04d5 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props @@ -77,7 +77,6 @@ <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'windows' ">GODOT_WINDOWS;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'linuxbsd' ">GODOT_LINUXBSD;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'macos' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants> - <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'server' ">GODOT_SERVER;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'uwp' ">GODOT_UWP;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'haiku' ">GODOT_HAIKU;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'android' ">GODOT_ANDROID;GODOT_MOBILE</GodotPlatformConstants> diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs index 0f8b128da8..3dfa8000ba 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs @@ -1,6 +1,7 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; namespace Godot.SourceGenerators { @@ -19,7 +20,7 @@ namespace Godot.SourceGenerators "must be declared with the partial modifier."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0001", + new DiagnosticDescriptor(id: "GD0001", title: message, messageFormat: message, category: "Usage", @@ -51,7 +52,7 @@ namespace Godot.SourceGenerators "containing types must be declared with the partial modifier."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0002", + new DiagnosticDescriptor(id: "GD0002", title: message, messageFormat: message, category: "Usage", @@ -78,7 +79,7 @@ namespace Godot.SourceGenerators " Remove the 'static' modifier or the '[Export]' attribute."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0101", + new DiagnosticDescriptor(id: "GD0101", title: message, messageFormat: message, category: "Usage", @@ -104,7 +105,7 @@ namespace Godot.SourceGenerators string description = $"{message}. Use a supported type or remove the '[Export]' attribute."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0102", + new DiagnosticDescriptor(id: "GD0102", title: message, messageFormat: message, category: "Usage", @@ -132,7 +133,7 @@ namespace Godot.SourceGenerators $"{message}. Exported properties must be writable."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0103", + new DiagnosticDescriptor(id: "GD0103", title: message, messageFormat: message, category: "Usage", @@ -156,7 +157,7 @@ namespace Godot.SourceGenerators string description = $"{message}. Exported properties must be readable."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0104", + new DiagnosticDescriptor(id: "GD0104", title: message, messageFormat: message, category: "Usage", @@ -181,7 +182,7 @@ namespace Godot.SourceGenerators string description = $"{message}. Rename the delegate accordingly or remove the '[Signal]' attribute."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0201", + new DiagnosticDescriptor(id: "GD0201", title: message, messageFormat: message, category: "Usage", @@ -205,7 +206,7 @@ namespace Godot.SourceGenerators string description = $"{message}. Use supported types only or remove the '[Signal]' attribute."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0202", + new DiagnosticDescriptor(id: "GD0202", title: message, messageFormat: message, category: "Usage", @@ -229,7 +230,7 @@ namespace Godot.SourceGenerators string description = $"{message}. Return void or remove the '[Signal]' attribute."; context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id: "GODOT-G0203", + new DiagnosticDescriptor(id: "GD0203", title: message, messageFormat: message, category: "Usage", @@ -239,5 +240,97 @@ namespace Godot.SourceGenerators location, location?.SourceTree?.FilePath)); } + + public static readonly DiagnosticDescriptor GenericTypeArgumentMustBeVariantRule = + new DiagnosticDescriptor(id: "GD0301", + title: "The generic type argument must be a Variant compatible type", + messageFormat: "The generic type argument must be a Variant compatible type: {0}", + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + "The generic type argument must be a Variant compatible type. Use a Variant compatible type as the generic type argument."); + + public static void ReportGenericTypeArgumentMustBeVariant( + SyntaxNodeAnalysisContext context, + SyntaxNode typeArgumentSyntax, + ISymbol typeArgumentSymbol) + { + string message = "The generic type argument " + + $"must be a Variant compatible type: '{typeArgumentSymbol.ToDisplayString()}'"; + + string description = $"{message}. Use a Variant compatible type as the generic type argument."; + + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor(id: "GD0301", + title: message, + messageFormat: message, + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description), + typeArgumentSyntax.GetLocation(), + typeArgumentSyntax.SyntaxTree.FilePath)); + } + + public static readonly DiagnosticDescriptor GenericTypeParameterMustBeVariantAnnotatedRule = + new DiagnosticDescriptor(id: "GD0302", + title: "The generic type parameter must be annotated with the MustBeVariant attribute", + messageFormat: "The generic type argument must be a Variant type: {0}", + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + "The generic type argument must be a Variant type. Use a Variant type as the generic type argument."); + + public static void ReportGenericTypeParameterMustBeVariantAnnotated( + SyntaxNodeAnalysisContext context, + SyntaxNode typeArgumentSyntax, + ISymbol typeArgumentSymbol) + { + string message = "The generic type parameter must be annotated with the MustBeVariant attribute"; + + string description = $"{message}. Add the MustBeVariant attribute to the generic type parameter."; + + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor(id: "GD0302", + title: message, + messageFormat: message, + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description), + typeArgumentSyntax.GetLocation(), + typeArgumentSyntax.SyntaxTree.FilePath)); + } + + public static readonly DiagnosticDescriptor TypeArgumentParentSymbolUnhandledRule = + new DiagnosticDescriptor(id: "GD0303", + title: "The generic type parameter must be annotated with the MustBeVariant attribute", + messageFormat: "The generic type argument must be a Variant type: {0}", + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + "The generic type argument must be a Variant type. Use a Variant type as the generic type argument."); + + public static void ReportTypeArgumentParentSymbolUnhandled( + SyntaxNodeAnalysisContext context, + SyntaxNode typeArgumentSyntax, + ISymbol parentSymbol) + { + string message = $"Symbol '{parentSymbol.ToDisplayString()}' parent of a type argument " + + "that must be Variant compatible was not handled."; + + string description = $"{message}. Handle type arguments that are children of the unhandled symbol type."; + + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor(id: "GD0303", + title: message, + messageFormat: message, + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description), + typeArgumentSyntax.GetLocation(), + typeArgumentSyntax.SyntaxTree.FilePath)); + } } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs index bac4708165..de3b6c862a 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs @@ -177,6 +177,9 @@ namespace Godot.SourceGenerators public static bool IsGodotSignalAttribute(this INamedTypeSymbol symbol) => symbol.ToString() == GodotClasses.SignalAttr; + public static bool IsGodotMustBeVariantAttribute(this INamedTypeSymbol symbol) + => symbol.ToString() == GodotClasses.MustBeVariantAttr; + public static bool IsGodotClassNameAttribute(this INamedTypeSymbol symbol) => symbol.ToString() == GodotClasses.GodotClassNameAttr; @@ -272,5 +275,13 @@ namespace Godot.SourceGenerators yield return new GodotFieldData(field, marshalType.Value); } } + + public static string Path(this Location location) + => location.SourceTree?.GetLineSpan(location.SourceSpan).Path + ?? location.GetLineSpan().Path; + + public static int StartLine(this Location location) + => location.SourceTree?.GetLineSpan(location.SourceSpan).StartLinePosition.Line + ?? location.GetLineSpan().StartLinePosition.Line; } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs index e899440e10..1d8ddbabf2 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs @@ -9,6 +9,7 @@ namespace Godot.SourceGenerators public const string ExportGroupAttr = "Godot.ExportGroupAttribute"; public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute"; public const string SignalAttr = "Godot.SignalAttribute"; + public const string MustBeVariantAttr = "Godot.MustBeVariantAttribute"; public const string GodotClassNameAttr = "Godot.GodotClassName"; public const string SystemFlagsAttr = "System.FlagsAttribute"; } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs index a3ad8cbabd..db395e21cb 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs @@ -59,4 +59,26 @@ namespace Godot.SourceGenerators public IFieldSymbol FieldSymbol { get; } public MarshalType Type { get; } } + + public struct GodotPropertyOrFieldData + { + public GodotPropertyOrFieldData(ISymbol symbol, MarshalType type) + { + Symbol = symbol; + Type = type; + } + + public GodotPropertyOrFieldData(GodotPropertyData propertyData) + : this(propertyData.PropertySymbol, propertyData.Type) + { + } + + public GodotPropertyOrFieldData(GodotFieldData fieldData) + : this(fieldData.FieldSymbol, fieldData.Type) + { + } + + public ISymbol Symbol { get; } + public MarshalType Type { get; } + } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs index ca84518c0c..831ac3bdeb 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs @@ -11,11 +11,11 @@ namespace Godot.SourceGenerators { public INamedTypeSymbol GodotObjectType { get; } - public TypeCache(GeneratorExecutionContext context) + public TypeCache(Compilation compilation) { INamedTypeSymbol GetTypeByMetadataNameOrThrow(string fullyQualifiedMetadataName) { - return context.Compilation.GetTypeByMetadataName(fullyQualifiedMetadataName) ?? + return compilation.GetTypeByMetadataName(fullyQualifiedMetadataName) ?? throw new InvalidOperationException("Type not found: " + fullyQualifiedMetadataName); } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs new file mode 100644 index 0000000000..7aaadb27be --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs @@ -0,0 +1,100 @@ +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Godot.SourceGenerators +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class MustBeVariantAnalyzer : DiagnosticAnalyzer + { + public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics + => ImmutableArray.Create( + Common.GenericTypeArgumentMustBeVariantRule, + Common.GenericTypeParameterMustBeVariantAnnotatedRule, + Common.TypeArgumentParentSymbolUnhandledRule); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.TypeArgumentList); + } + + private void AnalyzeNode(SyntaxNodeAnalysisContext context) + { + var typeArgListSyntax = (TypeArgumentListSyntax)context.Node; + + // Method invocation or variable declaration that contained the type arguments + var parentSyntax = context.Node.Parent; + Debug.Assert(parentSyntax != null); + + var sm = context.SemanticModel; + + var typeCache = new MarshalUtils.TypeCache(context.Compilation); + + for (int i = 0; i < typeArgListSyntax.Arguments.Count; i++) + { + var typeSyntax = typeArgListSyntax.Arguments[i]; + var typeSymbol = sm.GetSymbolInfo(typeSyntax).Symbol as ITypeSymbol; + Debug.Assert(typeSymbol != null); + + var parentSymbol = sm.GetSymbolInfo(parentSyntax).Symbol; + + if (!ShouldCheckTypeArgument(context, parentSyntax, parentSymbol, typeSyntax, typeSymbol, i)) + { + return; + } + + if (typeSymbol is ITypeParameterSymbol typeParamSymbol) + { + if (!typeParamSymbol.GetAttributes().Any(a => a.AttributeClass?.IsGodotMustBeVariantAttribute() ?? false)) + { + Common.ReportGenericTypeParameterMustBeVariantAnnotated(context, typeSyntax, typeSymbol); + } + continue; + } + + var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(typeSymbol, typeCache); + + if (marshalType == null) + { + Common.ReportGenericTypeArgumentMustBeVariant(context, typeSyntax, typeSymbol); + continue; + } + } + } + + /// <summary> + /// Check if the given type argument is being used in a type parameter that contains + /// the <c>MustBeVariantAttribute</c>; otherwise, we ignore the attribute. + /// </summary> + /// <param name="context">Context for a syntax node action.</param> + /// <param name="parentSyntax">The parent node syntax that contains the type node syntax.</param> + /// <param name="parentSymbol">The symbol retrieved for the parent node syntax.</param> + /// <param name="typeArgumentSyntax">The type node syntax of the argument type to check.</param> + /// <param name="typeArgumentSymbol">The symbol retrieved for the type node syntax.</param> + /// <returns><see langword="true"/> if the type must be variant and must be analyzed.</returns> + private bool ShouldCheckTypeArgument(SyntaxNodeAnalysisContext context, SyntaxNode parentSyntax, ISymbol parentSymbol, TypeSyntax typeArgumentSyntax, ITypeSymbol typeArgumentSymbol, int typeArgumentIndex) + { + var typeParamSymbol = parentSymbol switch + { + IMethodSymbol methodSymbol => methodSymbol.TypeParameters[typeArgumentIndex], + INamedTypeSymbol typeSymbol => typeSymbol.TypeParameters[typeArgumentIndex], + _ => null, + }; + + if (typeParamSymbol == null) + { + Common.ReportTypeArgumentParentSymbolUnhandled(context, typeArgumentSyntax, parentSymbol); + return false; + } + + return typeParamSymbol.GetAttributes() + .Any(a => a.AttributeClass?.IsGodotMustBeVariantAttribute() ?? false); + } + } +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs index 1fdc04a262..5ac4f4a47e 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs @@ -49,7 +49,7 @@ namespace Godot.SourceGenerators if (godotClasses.Length > 0) { - var typeCache = new MarshalUtils.TypeCache(context); + var typeCache = new MarshalUtils.TypeCache(context.Compilation); foreach (var godotClass in godotClasses) { diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs index b4db3fda62..7629595b3a 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs @@ -49,7 +49,7 @@ namespace Godot.SourceGenerators if (godotClasses.Length > 0) { - var typeCache = new MarshalUtils.TypeCache(context); + var typeCache = new MarshalUtils.TypeCache(context.Compilation); foreach (var godotClass in godotClasses) { @@ -225,28 +225,21 @@ namespace Godot.SourceGenerators .Append(dictionaryType) .Append("();\n"); - foreach (var property in godotClassProperties) - { - foreach (var groupingInfo in DetermineGroupingPropertyInfo(property.PropertySymbol)) - AppendGroupingPropertyInfo(source, groupingInfo); + // To retain the definition order (and display categories correctly), we want to + // iterate over fields and properties at the same time, sorted by line number. + var godotClassPropertiesAndFields = Enumerable.Empty<GodotPropertyOrFieldData>() + .Concat(godotClassProperties.Select(propertyData => new GodotPropertyOrFieldData(propertyData))) + .Concat(godotClassFields.Select(fieldData => new GodotPropertyOrFieldData(fieldData))) + .OrderBy(data => data.Symbol.Locations[0].Path()) + .ThenBy(data => data.Symbol.Locations[0].StartLine()); - var propertyInfo = DeterminePropertyInfo(context, typeCache, - property.PropertySymbol, property.Type); - - if (propertyInfo == null) - continue; - - AppendPropertyInfo(source, propertyInfo.Value); - } - - foreach (var field in godotClassFields) + foreach (var member in godotClassPropertiesAndFields) { - - foreach (var groupingInfo in DetermineGroupingPropertyInfo(field.FieldSymbol)) + foreach (var groupingInfo in DetermineGroupingPropertyInfo(member.Symbol)) AppendGroupingPropertyInfo(source, groupingInfo); var propertyInfo = DeterminePropertyInfo(context, typeCache, - field.FieldSymbol, field.Type); + member.Symbol, member.Type); if (propertyInfo == null) continue; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs index 3b8ba21107..85fadaa52e 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs @@ -49,7 +49,7 @@ namespace Godot.SourceGenerators if (godotClasses.Length > 0) { - var typeCache = new MarshalUtils.TypeCache(context); + var typeCache = new MarshalUtils.TypeCache(context.Compilation); foreach (var godotClass in godotClasses) { diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs index 1b87c6e760..5a84122c4c 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs @@ -49,7 +49,7 @@ namespace Godot.SourceGenerators if (godotClasses.Length > 0) { - var typeCache = new MarshalUtils.TypeCache(context); + var typeCache = new MarshalUtils.TypeCache(context.Compilation); foreach (var godotClass in godotClasses) { diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs index f1c7706f9c..6b06f10db1 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs @@ -56,7 +56,7 @@ namespace Godot.SourceGenerators if (godotClasses.Length > 0) { - var typeCache = new MarshalUtils.TypeCache(context); + var typeCache = new MarshalUtils.TypeCache(context.Compilation); foreach (var godotClass in godotClasses) { @@ -117,10 +117,6 @@ namespace Godot.SourceGenerators source.Append(symbol.NameWithTypeParameters()); source.Append("\n{\n"); - // TODO: - // The delegate name already needs to end with 'Signal' to avoid collision with the event name. - // Requiring SignalAttribute is redundant. Should we remove it to make declaration shorter? - var members = symbol.GetMembers(); var signalDelegateSymbols = members diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs index 686202e81e..2448a2953b 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs @@ -25,10 +25,7 @@ namespace GodotTools.IdeMessaging public override bool Equals(object obj) { - if (obj is GodotIdeMetadata metadata) - return metadata == this; - - return false; + return obj is GodotIdeMetadata metadata && metadata == this; } public bool Equals(GodotIdeMetadata other) diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs index 3c5b897719..edbf53a389 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs @@ -27,15 +27,13 @@ namespace GodotTools.Build public override bool Equals(object? obj) { - if (obj is BuildInfo other) - return other.Solution == Solution && - other.Configuration == Configuration && other.RuntimeIdentifier == RuntimeIdentifier && - other.PublishOutputDir == PublishOutputDir && other.Restore == Restore && - other.Rebuild == Rebuild && other.OnlyClean == OnlyClean && - other.CustomProperties == CustomProperties && - other.LogsDirPath == LogsDirPath; - - return false; + return obj is BuildInfo other && + other.Solution == Solution && + other.Configuration == Configuration && other.RuntimeIdentifier == RuntimeIdentifier && + other.PublishOutputDir == PublishOutputDir && other.Restore == Restore && + other.Rebuild == Rebuild && other.OnlyClean == OnlyClean && + other.CustomProperties == CustomProperties && + other.LogsDirPath == LogsDirPath; } public override int GetHashCode() diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs index 87549f61fe..fc325fc25b 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -75,8 +75,17 @@ namespace GodotTools.Export } else { - string bits = features.Contains("64") ? "64" : features.Contains("32") ? "32" : null; - CompileAssembliesForDesktop(exporter, platform, isDebug, bits, aotOpts, aotTempDir, outputDataDir, assembliesPrepared, bclDir); + string arch = ""; + if (features.Contains("x86_64")) { + arch = "x86_64"; + } else if (features.Contains("x86_32")) { + arch = "x86_32"; + } else if (features.Contains("arm64")) { + arch = "arm64"; + } else if (features.Contains("arm32")) { + arch = "arm32"; + } + CompileAssembliesForDesktop(exporter, platform, isDebug, arch, aotOpts, aotTempDir, outputDataDir, assembliesPrepared, bclDir); } } @@ -112,7 +121,7 @@ namespace GodotTools.Export } } - public static void CompileAssembliesForDesktop(ExportPlugin exporter, string platform, bool isDebug, string bits, AotOptions aotOpts, string aotTempDir, string outputDataDir, IDictionary<string, string> assemblies, string bclDir) + public static void CompileAssembliesForDesktop(ExportPlugin exporter, string platform, bool isDebug, string arch, AotOptions aotOpts, string aotTempDir, string outputDataDir, IDictionary<string, string> assemblies, string bclDir) { foreach (var assembly in assemblies) { @@ -126,9 +135,9 @@ namespace GodotTools.Export string outputFileName = assemblyName + ".dll" + outputFileExtension; string tempOutputFilePath = Path.Combine(aotTempDir, outputFileName); - var compilerArgs = GetAotCompilerArgs(platform, isDebug, bits, aotOpts, assemblyPath, tempOutputFilePath); + var compilerArgs = GetAotCompilerArgs(platform, isDebug, arch, aotOpts, assemblyPath, tempOutputFilePath); - string compilerDirPath = GetMonoCrossDesktopDirName(platform, bits); + string compilerDirPath = GetMonoCrossDesktopDirName(platform, arch); ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir); @@ -432,9 +441,9 @@ MONO_AOT_MODE_LAST = 1000, var androidToolPrefixes = new Dictionary<string, string> { - ["armeabi-v7a"] = "arm-linux-androideabi-", - ["arm64-v8a"] = "aarch64-linux-android-", - ["x86"] = "i686-linux-android-", + ["arm32"] = "arm-linux-androideabi-", + ["arm64"] = "aarch64-linux-android-", + ["x86_32"] = "i686-linux-android-", ["x86_64"] = "x86_64-linux-android-" }; @@ -547,9 +556,9 @@ MONO_AOT_MODE_LAST = 1000, { var androidAbis = new[] { - "armeabi-v7a", - "arm64-v8a", - "x86", + "arm32", + "arm64", + "x86_32", "x86_64" }; @@ -560,9 +569,9 @@ MONO_AOT_MODE_LAST = 1000, { var abiArchs = new Dictionary<string, string> { - ["armeabi-v7a"] = "armv7", - ["arm64-v8a"] = "aarch64-v8a", - ["x86"] = "i686", + ["arm32"] = "armv7", + ["arm64"] = "aarch64-v8a", + ["x86_32"] = "i686", ["x86_64"] = "x86_64" }; @@ -571,31 +580,25 @@ MONO_AOT_MODE_LAST = 1000, return $"{arch}-linux-android"; } - private static string GetMonoCrossDesktopDirName(string platform, string bits) + private static string GetMonoCrossDesktopDirName(string platform, string arch) { switch (platform) { case OS.Platforms.Windows: case OS.Platforms.UWP: { - string arch = bits == "64" ? "x86_64" : "i686"; return $"windows-{arch}"; } case OS.Platforms.MacOS: { - Debug.Assert(bits == null || bits == "64"); - string arch = "x86_64"; return $"{platform}-{arch}"; } case OS.Platforms.LinuxBSD: - case OS.Platforms.Server: { - string arch = bits == "64" ? "x86_64" : "i686"; return $"linux-{arch}"; } case OS.Platforms.Haiku: { - string arch = bits == "64" ? "x86_64" : "i686"; return $"{platform}-{arch}"; } default: diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index ecf363c106..e1b5530b93 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -100,7 +100,7 @@ namespace GodotTools.Export if (!DeterminePlatformFromFeatures(features, out string platform)) throw new NotSupportedException("Target platform not supported"); - if (!new[] { OS.Platforms.Windows, OS.Platforms.LinuxBSD, OS.Platforms.MacOS, OS.Platforms.Server } + if (!new[] { OS.Platforms.Windows, OS.Platforms.LinuxBSD, OS.Platforms.MacOS } .Contains(platform)) { throw new NotImplementedException("Target platform not yet implemented"); diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 62140d41bc..651922d019 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -15,6 +15,9 @@ namespace GodotTools.Utils [SuppressMessage("ReSharper", "InconsistentNaming")] public static class OS { + /// <summary> + /// Display names for the OS platforms. + /// </summary> private static class Names { public const string Windows = "Windows"; @@ -23,7 +26,6 @@ namespace GodotTools.Utils public const string FreeBSD = "FreeBSD"; public const string NetBSD = "NetBSD"; public const string BSD = "BSD"; - public const string Server = "Server"; public const string UWP = "UWP"; public const string Haiku = "Haiku"; public const string Android = "Android"; @@ -31,12 +33,14 @@ namespace GodotTools.Utils public const string HTML5 = "HTML5"; } + /// <summary> + /// Godot platform identifiers. + /// </summary> public static class Platforms { public const string Windows = "windows"; public const string MacOS = "macos"; public const string LinuxBSD = "linuxbsd"; - public const string Server = "server"; public const string UWP = "uwp"; public const string Haiku = "haiku"; public const string Android = "android"; @@ -44,6 +48,10 @@ namespace GodotTools.Utils public const string HTML5 = "javascript"; } + /// <summary> + /// OS name part of the .NET runtime identifier (RID). + /// See https://docs.microsoft.com/en-us/dotnet/core/rid-catalog. + /// </summary> public static class DotNetOS { public const string Win = "win"; @@ -65,7 +73,6 @@ namespace GodotTools.Utils ["LinuxBSD"] = Platforms.LinuxBSD, // "X11" for compatibility, temporarily, while we are on an outdated branch ["X11"] = Platforms.LinuxBSD, - ["Server"] = Platforms.Server, ["UWP"] = Platforms.UWP, ["Haiku"] = Platforms.Haiku, ["Android"] = Platforms.Android, @@ -81,7 +88,6 @@ namespace GodotTools.Utils [Names.FreeBSD] = Platforms.LinuxBSD, [Names.NetBSD] = Platforms.LinuxBSD, [Names.BSD] = Platforms.LinuxBSD, - [Names.Server] = Platforms.Server, [Names.UWP] = Platforms.UWP, [Names.Haiku] = Platforms.Haiku, [Names.Android] = Platforms.Android, @@ -98,7 +104,6 @@ namespace GodotTools.Utils // instead of `linux` in the runtime identifier. This would be a problem as // Godot has a single export profile for both, named LinuxBSD. [Platforms.LinuxBSD] = DotNetOS.Linux, - [Platforms.Server] = DotNetOS.Linux, [Platforms.UWP] = DotNetOS.Win10, [Platforms.Android] = DotNetOS.Android, [Platforms.iOS] = DotNetOS.iOS, @@ -129,13 +134,12 @@ namespace GodotTools.Utils new[] { Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD }; private static readonly IEnumerable<string> UnixLikePlatforms = - new[] { Names.MacOS, Names.Server, Names.Haiku, Names.Android, Names.iOS } + new[] { Names.MacOS, Names.Haiku, Names.Android, Names.iOS } .Concat(LinuxBSDPlatforms).ToArray(); private static readonly Lazy<bool> _isWindows = new(() => IsOS(Names.Windows)); private static readonly Lazy<bool> _isMacOS = new(() => IsOS(Names.MacOS)); private static readonly Lazy<bool> _isLinuxBSD = new(() => IsAnyOS(LinuxBSDPlatforms)); - private static readonly Lazy<bool> _isServer = new(() => IsOS(Names.Server)); private static readonly Lazy<bool> _isUWP = new(() => IsOS(Names.UWP)); private static readonly Lazy<bool> _isHaiku = new(() => IsOS(Names.Haiku)); private static readonly Lazy<bool> _isAndroid = new(() => IsOS(Names.Android)); @@ -149,8 +153,6 @@ namespace GodotTools.Utils [SupportedOSPlatformGuard("linux")] public static bool IsLinuxBSD => _isLinuxBSD.Value; - [SupportedOSPlatformGuard("linux")] public static bool IsServer => _isServer.Value; - [SupportedOSPlatformGuard("windows")] public static bool IsUWP => _isUWP.Value; public static bool IsHaiku => _isHaiku.Value; diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 73d8f23081..d70a1e6c88 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -87,9 +87,7 @@ StringBuilder &operator<<(StringBuilder &r_sb, const char *p_cstring) { #define CS_STATIC_FIELD_NATIVE_CTOR "NativeCtor" #define CS_STATIC_FIELD_METHOD_BIND_PREFIX "MethodBind" -#define CS_STATIC_FIELD_METHOD_NAME_PREFIX "MethodName_" #define CS_STATIC_FIELD_METHOD_PROXY_NAME_PREFIX "MethodProxyName_" -#define CS_STATIC_FIELD_SIGNAL_NAME_PREFIX "SignalName_" #define ICALL_PREFIX "godot_icall_" #define ICALL_CLASSDB_GET_METHOD "ClassDB_get_method" @@ -1606,12 +1604,6 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output << MEMBER_BEGIN "// ReSharper disable once InconsistentNaming\n" << INDENT1 "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n" << INDENT1 "private static readonly StringName " - << CS_STATIC_FIELD_METHOD_NAME_PREFIX << imethod.name - << " = \"" << imethod.name << "\";\n"; - - output << MEMBER_BEGIN "// ReSharper disable once InconsistentNaming\n" - << INDENT1 "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n" - << INDENT1 "private static readonly StringName " << CS_STATIC_FIELD_METHOD_PROXY_NAME_PREFIX << imethod.name << " = \"" << imethod.proxy_name << "\";\n"; } @@ -1637,7 +1629,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // We check both native names (snake_case) and proxy names (PascalCase) output << INDENT2 "if ((method == " << CS_STATIC_FIELD_METHOD_PROXY_NAME_PREFIX << imethod.name - << " || method == " << CS_STATIC_FIELD_METHOD_NAME_PREFIX << imethod.name + << " || method == MethodName." << imethod.proxy_name << ") && argCount == " << itos(imethod.arguments.size()) << " && " << CS_METHOD_HAS_GODOT_CLASS_METHOD << "((godot_string_name)" << CS_STATIC_FIELD_METHOD_PROXY_NAME_PREFIX << imethod.name << ".NativeValue))\n" @@ -1713,7 +1705,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // again, but this time with the respective proxy name (PascalCase). It's the job of // user derived classes to override the method and check for those. Our C# source // generators take care of generating those override methods. - output << INDENT2 "if (method == " << CS_STATIC_FIELD_METHOD_NAME_PREFIX << imethod.name + output << INDENT2 "if (method == MethodName." << imethod.proxy_name << ")\n" INDENT2 "{\n" << INDENT3 "if (" CS_METHOD_HAS_GODOT_CLASS_METHOD "(" << CS_STATIC_FIELD_METHOD_PROXY_NAME_PREFIX << imethod.name @@ -1731,6 +1723,45 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output << INDENT1 "}\n"; } + //Generate StringName for all class members + bool is_inherit = !itype.is_singleton && obj_types.has(itype.base_name); + //PropertyName + if (is_inherit) { + output << MEMBER_BEGIN "public new class PropertyName : " << obj_types[itype.base_name].proxy_name << ".PropertyName"; + } else { + output << MEMBER_BEGIN "public class PropertyName"; + } + output << "\n" + << INDENT1 "{\n"; + for (const PropertyInterface &iprop : itype.properties) { + output << INDENT2 "public static readonly StringName " << iprop.proxy_name << " = \"" << iprop.cname << "\";\n"; + } + output << INDENT1 "}\n"; + //MethodName + if (is_inherit) { + output << MEMBER_BEGIN "public new class MethodName : " << obj_types[itype.base_name].proxy_name << ".MethodName"; + } else { + output << MEMBER_BEGIN "public class MethodName"; + } + output << "\n" + << INDENT1 "{\n"; + for (const MethodInterface &imethod : itype.methods) { + output << INDENT2 "public static readonly StringName " << imethod.proxy_name << " = \"" << imethod.cname << "\";\n"; + } + output << INDENT1 "}\n"; + //SignalName + if (is_inherit) { + output << MEMBER_BEGIN "public new class SignalName : " << obj_types[itype.base_name].proxy_name << ".SignalName"; + } else { + output << MEMBER_BEGIN "public class SignalName"; + } + output << "\n" + << INDENT1 "{\n"; + for (const SignalInterface &isignal : itype.signals_) { + output << INDENT2 "public static readonly StringName " << isignal.proxy_name << " = \"" << isignal.cname << "\";\n"; + } + output << INDENT1 "}\n"; + output.append(CLOSE_BLOCK /* class */); output.append("\n" @@ -2052,9 +2083,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf p_output << "Object."; } - p_output << ICALL_CLASSDB_GET_METHOD "(" BINDINGS_NATIVE_NAME_FIELD ", \"" - << p_imethod.name - << "\");\n"; + p_output << ICALL_CLASSDB_GET_METHOD "(" BINDINGS_NATIVE_NAME_FIELD ", MethodName." + << p_imethod.proxy_name + << ");\n"; } if (p_imethod.method_doc && p_imethod.method_doc->description.size()) { @@ -2226,7 +2257,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf } String delegate_name = p_isignal.proxy_name; - delegate_name += "Handler"; // Delegate name is [SignalName]Handler + delegate_name += "EventHandler"; // Delegate name is [SignalName]EventHandler // Generate delegate p_output.append(MEMBER_BEGIN "public delegate void "); @@ -2239,17 +2270,8 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf // Could we assume the StringName instance of signal name will never be freed (it's stored in ClassDB) before the managed world is unloaded? // If so, we could store the pointer we get from `data_unique_pointer()` instead of allocating StringName here. - // Cached signal name (StringName) - p_output.append(MEMBER_BEGIN "// ReSharper disable once InconsistentNaming\n"); - p_output.append(INDENT1 "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN - "private static readonly StringName " CS_STATIC_FIELD_SIGNAL_NAME_PREFIX); - p_output.append(p_isignal.name); - p_output.append(" = \""); - p_output.append(p_isignal.name); - p_output.append("\";\n"); - // Generate event - p_output.append(MEMBER_BEGIN "[Signal]" MEMBER_BEGIN "public "); + p_output.append(MEMBER_BEGIN "public "); if (p_itype.is_singleton) { p_output.append("static "); @@ -2262,21 +2284,21 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf p_output.append("\n" OPEN_BLOCK_L1 INDENT2); if (p_itype.is_singleton) { - p_output.append("add => " CS_PROPERTY_SINGLETON ".Connect(" CS_STATIC_FIELD_SIGNAL_NAME_PREFIX); + p_output.append("add => " CS_PROPERTY_SINGLETON ".Connect(SignalName."); } else { - p_output.append("add => Connect(" CS_STATIC_FIELD_SIGNAL_NAME_PREFIX); + p_output.append("add => Connect(SignalName."); } - p_output.append(p_isignal.name); + p_output.append(p_isignal.proxy_name); p_output.append(", new Callable(value));\n"); if (p_itype.is_singleton) { - p_output.append(INDENT2 "remove => " CS_PROPERTY_SINGLETON ".Disconnect(" CS_STATIC_FIELD_SIGNAL_NAME_PREFIX); + p_output.append(INDENT2 "remove => " CS_PROPERTY_SINGLETON ".Disconnect(SignalName."); } else { - p_output.append(INDENT2 "remove => Disconnect(" CS_STATIC_FIELD_SIGNAL_NAME_PREFIX); + p_output.append(INDENT2 "remove => Disconnect(SignalName."); } - p_output.append(p_isignal.name); + p_output.append(p_isignal.proxy_name); p_output.append(", new Callable(value));\n"); p_output.append(CLOSE_BLOCK_L1); } diff --git a/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs index c34f1a17f3..1f5ea7532d 100644 --- a/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs +++ b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs @@ -8,7 +8,7 @@ public partial class _CLASS_ : _BASE_ public const float Speed = 300.0f; public const float JumpVelocity = -400.0f; - // Get the gravity from the project settings to be synced with RigidDynamicBody nodes. + // Get the gravity from the project settings to be synced with RigidBody nodes. public float gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle(); public override void _PhysicsProcess(float delta) diff --git a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs index 069908c426..4e978b7549 100644 --- a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs +++ b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs @@ -8,7 +8,7 @@ public partial class _CLASS_ : _BASE_ public const float Speed = 5.0f; public const float JumpVelocity = 4.5f; - // Get the gravity from the project settings to be synced with RigidDynamicBody nodes. + // Get the gravity from the project settings to be synced with RigidBody nodes. public float gravity = ProjectSettings.GetSetting("physics/3d/default_gravity").AsSingle(); public override void _PhysicsProcess(float delta) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs index f87f37bc43..b3a36e8ac8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs @@ -697,12 +697,7 @@ namespace Godot /// <returns>Whether or not the AABB and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is AABB) - { - return Equals((AABB)obj); - } - - return false; + return obj is AABB other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs index 81991c6626..f2984bd1fb 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs @@ -483,7 +483,7 @@ namespace Godot.Collections /// <typeparam name="T">The type of the array.</typeparam> [SuppressMessage("ReSharper", "RedundantExtendsListEntry")] [SuppressMessage("Naming", "CA1710", MessageId = "Identifiers should have correct suffix")] - public sealed class Array<T> : + public sealed class Array<[MustBeVariant] T> : IList<T>, IReadOnlyList<T>, ICollection<T>, diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/MustBeVariantAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/MustBeVariantAttribute.cs new file mode 100644 index 0000000000..23088378d1 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/MustBeVariantAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace Godot +{ + /// <summary> + /// Attribute that restricts generic type parameters to be only types + /// that can be marshaled from/to a <see cref="Variant"/>. + /// </summary> + [AttributeUsage(AttributeTargets.GenericParameter)] + public class MustBeVariantAttribute : Attribute { } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs index 07a214f543..38e68a89d5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs @@ -2,6 +2,6 @@ using System; namespace Godot { - [AttributeUsage(AttributeTargets.Delegate | AttributeTargets.Event)] + [AttributeUsage(AttributeTargets.Delegate)] public class SignalAttribute : Attribute { } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 4cb9bf5758..87adf9efe5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -892,12 +892,7 @@ namespace Godot /// <returns>Whether or not the basis matrix and the object are exactly equal.</returns> public override bool Equals(object obj) { - if (obj is Basis) - { - return Equals((Basis)obj); - } - - return false; + return obj is Basis other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index ed0e1efd35..0cbaef3dad 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -1151,12 +1151,7 @@ namespace Godot /// <returns>Whether or not the color and the other object are equal.</returns> public override bool Equals(object obj) { - if (obj is Color) - { - return Equals((Color)obj); - } - - return false; + return obj is Color other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs index bacf7c89e6..5bce66ea87 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs @@ -10,136 +10,136 @@ namespace Godot { // Color names and values are derived from core/math/color_names.inc internal static readonly Dictionary<string, Color> namedColors = new Dictionary<string, Color> { - { "ALICE_BLUE", new Color(0xF0F8FFFF) }, - { "ANTIQUE_WHITE", new Color(0xFAEBD7FF) }, + { "ALICEBLUE", new Color(0xF0F8FFFF) }, + { "ANTIQUEWHITE", new Color(0xFAEBD7FF) }, { "AQUA", new Color(0x00FFFFFF) }, { "AQUAMARINE", new Color(0x7FFFD4FF) }, { "AZURE", new Color(0xF0FFFFFF) }, { "BEIGE", new Color(0xF5F5DCFF) }, { "BISQUE", new Color(0xFFE4C4FF) }, { "BLACK", new Color(0x000000FF) }, - { "BLANCHED_ALMOND", new Color(0xFFEBCDFF) }, + { "BLANCHEDALMOND", new Color(0xFFEBCDFF) }, { "BLUE", new Color(0x0000FFFF) }, - { "BLUE_VIOLET", new Color(0x8A2BE2FF) }, + { "BLUEVIOLET", new Color(0x8A2BE2FF) }, { "BROWN", new Color(0xA52A2AFF) }, { "BURLYWOOD", new Color(0xDEB887FF) }, - { "CADET_BLUE", new Color(0x5F9EA0FF) }, + { "CADETBLUE", new Color(0x5F9EA0FF) }, { "CHARTREUSE", new Color(0x7FFF00FF) }, { "CHOCOLATE", new Color(0xD2691EFF) }, { "CORAL", new Color(0xFF7F50FF) }, - { "CORNFLOWER_BLUE", new Color(0x6495EDFF) }, + { "CORNFLOWERBLUE", new Color(0x6495EDFF) }, { "CORNSILK", new Color(0xFFF8DCFF) }, { "CRIMSON", new Color(0xDC143CFF) }, { "CYAN", new Color(0x00FFFFFF) }, - { "DARK_BLUE", new Color(0x00008BFF) }, - { "DARK_CYAN", new Color(0x008B8BFF) }, - { "DARK_GOLDENROD", new Color(0xB8860BFF) }, - { "DARK_GRAY", new Color(0xA9A9A9FF) }, - { "DARK_GREEN", new Color(0x006400FF) }, - { "DARK_KHAKI", new Color(0xBDB76BFF) }, - { "DARK_MAGENTA", new Color(0x8B008BFF) }, - { "DARK_OLIVE_GREEN", new Color(0x556B2FFF) }, - { "DARK_ORANGE", new Color(0xFF8C00FF) }, - { "DARK_ORCHID", new Color(0x9932CCFF) }, - { "DARK_RED", new Color(0x8B0000FF) }, - { "DARK_SALMON", new Color(0xE9967AFF) }, - { "DARK_SEA_GREEN", new Color(0x8FBC8FFF) }, - { "DARK_SLATE_BLUE", new Color(0x483D8BFF) }, - { "DARK_SLATE_GRAY", new Color(0x2F4F4FFF) }, - { "DARK_TURQUOISE", new Color(0x00CED1FF) }, - { "DARK_VIOLET", new Color(0x9400D3FF) }, - { "DEEP_PINK", new Color(0xFF1493FF) }, - { "DEEP_SKY_BLUE", new Color(0x00BFFFFF) }, - { "DIM_GRAY", new Color(0x696969FF) }, - { "DODGER_BLUE", new Color(0x1E90FFFF) }, + { "DARKBLUE", new Color(0x00008BFF) }, + { "DARKCYAN", new Color(0x008B8BFF) }, + { "DARKGOLDENROD", new Color(0xB8860BFF) }, + { "DARKGRAY", new Color(0xA9A9A9FF) }, + { "DARKGREEN", new Color(0x006400FF) }, + { "DARKKHAKI", new Color(0xBDB76BFF) }, + { "DARKMAGENTA", new Color(0x8B008BFF) }, + { "DARKOLIVEGREEN", new Color(0x556B2FFF) }, + { "DARKORANGE", new Color(0xFF8C00FF) }, + { "DARKORCHID", new Color(0x9932CCFF) }, + { "DARKRED", new Color(0x8B0000FF) }, + { "DARKSALMON", new Color(0xE9967AFF) }, + { "DARKSEAGREEN", new Color(0x8FBC8FFF) }, + { "DARKSLATEBLUE", new Color(0x483D8BFF) }, + { "DARKSLATEGRAY", new Color(0x2F4F4FFF) }, + { "DARKTURQUOISE", new Color(0x00CED1FF) }, + { "DARKVIOLET", new Color(0x9400D3FF) }, + { "DEEPPINK", new Color(0xFF1493FF) }, + { "DEEPSKYBLUE", new Color(0x00BFFFFF) }, + { "DIMGRAY", new Color(0x696969FF) }, + { "DODGERBLUE", new Color(0x1E90FFFF) }, { "FIREBRICK", new Color(0xB22222FF) }, - { "FLORAL_WHITE", new Color(0xFFFAF0FF) }, - { "FOREST_GREEN", new Color(0x228B22FF) }, + { "FLORALWHITE", new Color(0xFFFAF0FF) }, + { "FORESTGREEN", new Color(0x228B22FF) }, { "FUCHSIA", new Color(0xFF00FFFF) }, { "GAINSBORO", new Color(0xDCDCDCFF) }, - { "GHOST_WHITE", new Color(0xF8F8FFFF) }, + { "GHOSTWHITE", new Color(0xF8F8FFFF) }, { "GOLD", new Color(0xFFD700FF) }, { "GOLDENROD", new Color(0xDAA520FF) }, { "GRAY", new Color(0xBEBEBEFF) }, { "GREEN", new Color(0x00FF00FF) }, - { "GREEN_YELLOW", new Color(0xADFF2FFF) }, + { "GREENYELLOW", new Color(0xADFF2FFF) }, { "HONEYDEW", new Color(0xF0FFF0FF) }, - { "HOT_PINK", new Color(0xFF69B4FF) }, - { "INDIAN_RED", new Color(0xCD5C5CFF) }, + { "HOTPINK", new Color(0xFF69B4FF) }, + { "INDIANRED", new Color(0xCD5C5CFF) }, { "INDIGO", new Color(0x4B0082FF) }, { "IVORY", new Color(0xFFFFF0FF) }, { "KHAKI", new Color(0xF0E68CFF) }, { "LAVENDER", new Color(0xE6E6FAFF) }, - { "LAVENDER_BLUSH", new Color(0xFFF0F5FF) }, - { "LAWN_GREEN", new Color(0x7CFC00FF) }, - { "LEMON_CHIFFON", new Color(0xFFFACDFF) }, - { "LIGHT_BLUE", new Color(0xADD8E6FF) }, - { "LIGHT_CORAL", new Color(0xF08080FF) }, - { "LIGHT_CYAN", new Color(0xE0FFFFFF) }, - { "LIGHT_GOLDENROD", new Color(0xFAFAD2FF) }, - { "LIGHT_GRAY", new Color(0xD3D3D3FF) }, - { "LIGHT_GREEN", new Color(0x90EE90FF) }, - { "LIGHT_PINK", new Color(0xFFB6C1FF) }, - { "LIGHT_SALMON", new Color(0xFFA07AFF) }, - { "LIGHT_SEA_GREEN", new Color(0x20B2AAFF) }, - { "LIGHT_SKY_BLUE", new Color(0x87CEFAFF) }, - { "LIGHT_SLATE_GRAY", new Color(0x778899FF) }, - { "LIGHT_STEEL_BLUE", new Color(0xB0C4DEFF) }, - { "LIGHT_YELLOW", new Color(0xFFFFE0FF) }, + { "LAVENDERBLUSH", new Color(0xFFF0F5FF) }, + { "LAWNGREEN", new Color(0x7CFC00FF) }, + { "LEMONCHIFFON", new Color(0xFFFACDFF) }, + { "LIGHTBLUE", new Color(0xADD8E6FF) }, + { "LIGHTCORAL", new Color(0xF08080FF) }, + { "LIGHTCYAN", new Color(0xE0FFFFFF) }, + { "LIGHTGOLDENROD", new Color(0xFAFAD2FF) }, + { "LIGHTGRAY", new Color(0xD3D3D3FF) }, + { "LIGHTGREEN", new Color(0x90EE90FF) }, + { "LIGHTPINK", new Color(0xFFB6C1FF) }, + { "LIGHTSALMON", new Color(0xFFA07AFF) }, + { "LIGHTSEAGREEN", new Color(0x20B2AAFF) }, + { "LIGHTSKYBLUE", new Color(0x87CEFAFF) }, + { "LIGHTSLATEGRAY", new Color(0x778899FF) }, + { "LIGHTSTEELBLUE", new Color(0xB0C4DEFF) }, + { "LIGHTYELLOW", new Color(0xFFFFE0FF) }, { "LIME", new Color(0x00FF00FF) }, - { "LIME_GREEN", new Color(0x32CD32FF) }, + { "LIMEGREEN", new Color(0x32CD32FF) }, { "LINEN", new Color(0xFAF0E6FF) }, { "MAGENTA", new Color(0xFF00FFFF) }, { "MAROON", new Color(0xB03060FF) }, - { "MEDIUM_AQUAMARINE", new Color(0x66CDAAFF) }, - { "MEDIUM_BLUE", new Color(0x0000CDFF) }, - { "MEDIUM_ORCHID", new Color(0xBA55D3FF) }, - { "MEDIUM_PURPLE", new Color(0x9370DBFF) }, - { "MEDIUM_SEA_GREEN", new Color(0x3CB371FF) }, - { "MEDIUM_SLATE_BLUE", new Color(0x7B68EEFF) }, - { "MEDIUM_SPRING_GREEN", new Color(0x00FA9AFF) }, - { "MEDIUM_TURQUOISE", new Color(0x48D1CCFF) }, - { "MEDIUM_VIOLET_RED", new Color(0xC71585FF) }, - { "MIDNIGHT_BLUE", new Color(0x191970FF) }, - { "MINT_CREAM", new Color(0xF5FFFAFF) }, - { "MISTY_ROSE", new Color(0xFFE4E1FF) }, + { "MEDIUMAQUAMARINE", new Color(0x66CDAAFF) }, + { "MEDIUMBLUE", new Color(0x0000CDFF) }, + { "MEDIUMORCHID", new Color(0xBA55D3FF) }, + { "MEDIUMPURPLE", new Color(0x9370DBFF) }, + { "MEDIUMSEAGREEN", new Color(0x3CB371FF) }, + { "MEDIUMSLATEBLUE", new Color(0x7B68EEFF) }, + { "MEDIUMSPRINGGREEN", new Color(0x00FA9AFF) }, + { "MEDIUMTURQUOISE", new Color(0x48D1CCFF) }, + { "MEDIUMVIOLETRED", new Color(0xC71585FF) }, + { "MIDNIGHTBLUE", new Color(0x191970FF) }, + { "MINTCREAM", new Color(0xF5FFFAFF) }, + { "MISTYROSE", new Color(0xFFE4E1FF) }, { "MOCCASIN", new Color(0xFFE4B5FF) }, - { "NAVAJO_WHITE", new Color(0xFFDEADFF) }, - { "NAVY_BLUE", new Color(0x000080FF) }, - { "OLD_LACE", new Color(0xFDF5E6FF) }, + { "NAVAJOWHITE", new Color(0xFFDEADFF) }, + { "NAVYBLUE", new Color(0x000080FF) }, + { "OLDLACE", new Color(0xFDF5E6FF) }, { "OLIVE", new Color(0x808000FF) }, - { "OLIVE_DRAB", new Color(0x6B8E23FF) }, + { "OLIVEDRAB", new Color(0x6B8E23FF) }, { "ORANGE", new Color(0xFFA500FF) }, - { "ORANGE_RED", new Color(0xFF4500FF) }, + { "ORANGERED", new Color(0xFF4500FF) }, { "ORCHID", new Color(0xDA70D6FF) }, - { "PALE_GOLDENROD", new Color(0xEEE8AAFF) }, - { "PALE_GREEN", new Color(0x98FB98FF) }, - { "PALE_TURQUOISE", new Color(0xAFEEEEFF) }, - { "PALE_VIOLET_RED", new Color(0xDB7093FF) }, - { "PAPAYA_WHIP", new Color(0xFFEFD5FF) }, - { "PEACH_PUFF", new Color(0xFFDAB9FF) }, + { "PALEGOLDENROD", new Color(0xEEE8AAFF) }, + { "PALEGREEN", new Color(0x98FB98FF) }, + { "PALETURQUOISE", new Color(0xAFEEEEFF) }, + { "PALEVIOLETRED", new Color(0xDB7093FF) }, + { "PAPAYAWHIP", new Color(0xFFEFD5FF) }, + { "PEACHPUFF", new Color(0xFFDAB9FF) }, { "PERU", new Color(0xCD853FFF) }, { "PINK", new Color(0xFFC0CBFF) }, { "PLUM", new Color(0xDDA0DDFF) }, - { "POWDER_BLUE", new Color(0xB0E0E6FF) }, + { "POWDERBLUE", new Color(0xB0E0E6FF) }, { "PURPLE", new Color(0xA020F0FF) }, - { "REBECCA_PURPLE", new Color(0x663399FF) }, + { "REBECCAPURPLE", new Color(0x663399FF) }, { "RED", new Color(0xFF0000FF) }, - { "ROSY_BROWN", new Color(0xBC8F8FFF) }, - { "ROYAL_BLUE", new Color(0x4169E1FF) }, - { "SADDLE_BROWN", new Color(0x8B4513FF) }, + { "ROSYBROWN", new Color(0xBC8F8FFF) }, + { "ROYALBLUE", new Color(0x4169E1FF) }, + { "SADDLEBROWN", new Color(0x8B4513FF) }, { "SALMON", new Color(0xFA8072FF) }, - { "SANDY_BROWN", new Color(0xF4A460FF) }, - { "SEA_GREEN", new Color(0x2E8B57FF) }, + { "SANDYBROWN", new Color(0xF4A460FF) }, + { "SEAGREEN", new Color(0x2E8B57FF) }, { "SEASHELL", new Color(0xFFF5EEFF) }, { "SIENNA", new Color(0xA0522DFF) }, { "SILVER", new Color(0xC0C0C0FF) }, - { "SKY_BLUE", new Color(0x87CEEBFF) }, - { "SLATE_BLUE", new Color(0x6A5ACDFF) }, - { "SLATE_GRAY", new Color(0x708090FF) }, + { "SKYBLUE", new Color(0x87CEEBFF) }, + { "SLATEBLUE", new Color(0x6A5ACDFF) }, + { "SLATEGRAY", new Color(0x708090FF) }, { "SNOW", new Color(0xFFFAFAFF) }, - { "SPRING_GREEN", new Color(0x00FF7FFF) }, - { "STEEL_BLUE", new Color(0x4682B4FF) }, + { "SPRINGGREEN", new Color(0x00FF7FFF) }, + { "STEELBLUE", new Color(0x4682B4FF) }, { "TAN", new Color(0xD2B48CFF) }, { "TEAL", new Color(0x008080FF) }, { "THISTLE", new Color(0xD8BFD8FF) }, @@ -147,15 +147,15 @@ namespace Godot { "TRANSPARENT", new Color(0xFFFFFF00) }, { "TURQUOISE", new Color(0x40E0D0FF) }, { "VIOLET", new Color(0xEE82EEFF) }, - { "WEB_GRAY", new Color(0x808080FF) }, - { "WEB_GREEN", new Color(0x008000FF) }, - { "WEB_MAROON", new Color(0x800000FF) }, - { "WEB_PURPLE", new Color(0x800080FF) }, + { "WEBGRAY", new Color(0x808080FF) }, + { "WEBGREEN", new Color(0x008000FF) }, + { "WEBMAROON", new Color(0x800000FF) }, + { "WEBPURPLE", new Color(0x800080FF) }, { "WHEAT", new Color(0xF5DEB3FF) }, { "WHITE", new Color(0xFFFFFFFF) }, - { "WHITE_SMOKE", new Color(0xF5F5F5FF) }, + { "WHITESMOKE", new Color(0xF5F5F5FF) }, { "YELLOW", new Color(0xFFFF00FF) }, - { "YELLOW_GREEN", new Color(0x9ACD32FF) }, + { "YELLOWGREEN", new Color(0x9ACD32FF) }, }; #pragma warning disable CS1591 // Disable warning: "Missing XML comment for publicly visible type or member" diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs index 6fbc04702a..c4161d2ded 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs @@ -121,8 +121,8 @@ namespace Godot var sb = new StringBuilder(); - if (methodBase is MethodInfo) - sb.AppendTypeName(((MethodInfo)methodBase).ReturnType); + if (methodBase is MethodInfo methodInfo) + sb.AppendTypeName(methodInfo.ReturnType); sb.Append(methodBase.DeclaringType?.FullName ?? "<unknown>"); sb.Append('.'); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs index 266038a0af..3c75d18943 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs @@ -181,9 +181,9 @@ namespace Godot if (variantType == Variant.Type.Nil) return false; - static byte[] Var2Bytes(in godot_variant var) + static byte[] VarToBytes(in godot_variant var) { - NativeFuncs.godotsharp_var2bytes(var, false.ToGodotBool(), out var varBytes); + NativeFuncs.godotsharp_var_to_bytes(var, false.ToGodotBool(), out var varBytes); using (varBytes) return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes); } @@ -192,7 +192,7 @@ namespace Godot var fieldValue = field.GetValue(target); using var fieldValueVariant = Marshaling.ConvertManagedObjectToVariant(fieldValue); - byte[] valueBuffer = Var2Bytes(fieldValueVariant); + byte[] valueBuffer = VarToBytes(fieldValueVariant); writer.Write(valueBuffer.Length); writer.Write(valueBuffer); } @@ -448,7 +448,7 @@ namespace Godot FieldInfo? fieldInfo = targetType.GetField(name, BindingFlags.Instance | BindingFlags.Public); - fieldInfo?.SetValue(recreatedTarget, GD.Bytes2Var(valueBuffer)); + fieldInfo?.SetValue(recreatedTarget, GD.BytesToVar(valueBuffer)); } @delegate = Delegate.CreateDelegate(delegateType, recreatedTarget, methodInfo, diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs index fa8c94ed18..95ad097192 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs @@ -352,7 +352,7 @@ namespace Godot.Collections /// </summary> /// <typeparam name="TKey">The type of the dictionary's keys.</typeparam> /// <typeparam name="TValue">The type of the dictionary's values.</typeparam> - public class Dictionary<TKey, TValue> : + public class Dictionary<[MustBeVariant] TKey, [MustBeVariant] TValue> : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue> { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs index 1dc21b6303..df0e839866 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs @@ -93,8 +93,12 @@ namespace Godot /// Negative indices access the children from the last one. /// To access a child node via its name, use <see cref="GetNode"/>. /// </summary> - /// <seealso cref="GetChildOrNull{T}(int)"/> + /// <seealso cref="GetChildOrNull{T}(int, bool)"/> /// <param name="idx">Child index.</param> + /// <param name="includeInternal"> + /// If <see langword="false"/>, internal children are skipped (see <c>internal</c> + /// parameter in <see cref="AddChild(Node, bool, InternalMode)"/>). + /// </param> /// <exception cref="InvalidCastException"> /// Thrown when the given the fetched node can't be casted to the given type <typeparamref name="T"/>. /// </exception> @@ -102,9 +106,9 @@ namespace Godot /// <returns> /// The child <see cref="Node"/> at the given index <paramref name="idx"/>. /// </returns> - public T GetChild<T>(int idx) where T : class + public T GetChild<T>(int idx, bool includeInternal = false) where T : class { - return (T)(object)GetChild(idx); + return (T)(object)GetChild(idx, includeInternal); } /// <summary> @@ -113,15 +117,20 @@ namespace Godot /// Negative indices access the children from the last one. /// To access a child node via its name, use <see cref="GetNode"/>. /// </summary> - /// <seealso cref="GetChild{T}(int)"/> + /// <seealso cref="GetChild{T}(int, bool)"/> /// <param name="idx">Child index.</param> + /// <param name="includeInternal"> + /// If <see langword="false"/>, internal children are skipped (see <c>internal</c> + /// parameter in <see cref="AddChild(Node, bool, InternalMode)"/>). + /// </param> /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam> /// <returns> /// The child <see cref="Node"/> at the given index <paramref name="idx"/>, or <see langword="null"/> if not found. /// </returns> - public T GetChildOrNull<T>(int idx) where T : class + public T GetChildOrNull<T>(int idx, bool includeInternal = false) where T : class { - return GetChild(idx) as T; + int count = GetChildCount(includeInternal); + return idx >= -count && idx < count ? GetChild(idx, includeInternal) as T : null; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs index 9348cc1d00..e4b79e7ec4 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs @@ -21,10 +21,10 @@ namespace Godot /// <param name="bytes">Byte array that will be decoded to a <c>Variant</c>.</param> /// <param name="allowObjects">If objects should be decoded.</param> /// <returns>The decoded <c>Variant</c>.</returns> - public static Variant Bytes2Var(Span<byte> bytes, bool allowObjects = false) + public static Variant BytesToVar(Span<byte> bytes, bool allowObjects = false) { using var varBytes = Marshaling.ConvertSystemArrayToNativePackedByteArray(bytes); - NativeFuncs.godotsharp_bytes2var(varBytes, allowObjects.ToGodotBool(), out godot_variant ret); + NativeFuncs.godotsharp_bytes_to_var(varBytes, allowObjects.ToGodotBool(), out godot_variant ret); return Variant.CreateTakingOwnershipOfDisposableValue(ret); } @@ -52,10 +52,10 @@ namespace Godot /// <summary> /// Converts from decibels to linear energy (audio). /// </summary> - /// <seealso cref="Linear2Db(real_t)"/> + /// <seealso cref="LinearToDb(real_t)"/> /// <param name="db">Decibels to convert.</param> /// <returns>Audio volume as linear energy.</returns> - public static real_t Db2Linear(real_t db) + public static real_t DbToLinear(real_t db) { return (real_t)Math.Exp(db * 0.11512925464970228420089957273422); } @@ -115,18 +115,18 @@ namespace Godot /// Converts from linear energy to decibels (audio). /// This can be used to implement volume sliders that behave as expected (since volume isn't linear). /// </summary> - /// <seealso cref="Db2Linear(real_t)"/> + /// <seealso cref="DbToLinear(real_t)"/> /// <example> /// <code> /// // "slider" refers to a node that inherits Range such as HSlider or VSlider. /// // Its range must be configured to go from 0 to 1. /// // Change the bus name if you'd like to change the volume of a specific bus only. - /// AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("Master"), GD.Linear2Db(slider.value)); + /// AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("Master"), GD.LinearToDb(slider.value)); /// </code> /// </example> /// <param name="linear">The linear energy to convert.</param> /// <returns>Audio as decibels.</returns> - public static real_t Linear2Db(real_t linear) + public static real_t LinearToDb(real_t linear) { return (real_t)(Math.Log(linear) * 8.6858896380650365530225783783321); } @@ -189,8 +189,6 @@ namespace Godot /// Pushes an error message to Godot's built-in debugger and to the OS terminal. /// /// Note: Errors printed this way will not pause project execution. - /// To print an error message and pause project execution in debug builds, - /// use [code]assert(false, "test error")[/code] instead. /// </summary> /// <example> /// <code> @@ -520,21 +518,21 @@ namespace Godot } /// <summary> - /// Converts a formatted string that was returned by <see cref="Var2Str(Variant)"/> to the original value. + /// Converts a formatted string that was returned by <see cref="VarToStr(Variant)"/> to the original value. /// </summary> /// <example> /// <code> /// string a = "{\"a\": 1, \"b\": 2 }"; - /// var b = (Godot.Collections.Dictionary)GD.Str2Var(a); + /// var b = (Godot.Collections.Dictionary)GD.StrToVar(a); /// GD.Print(b["a"]); // Prints 1 /// </code> /// </example> /// <param name="str">String that will be converted to Variant.</param> /// <returns>The decoded <c>Variant</c>.</returns> - public static Variant Str2Var(string str) + public static Variant StrToVar(string str) { using var godotStr = Marshaling.ConvertStringToNative(str); - NativeFuncs.godotsharp_str2var(godotStr, out godot_variant ret); + NativeFuncs.godotsharp_str_to_var(godotStr, out godot_variant ret); return Variant.CreateTakingOwnershipOfDisposableValue(ret); } @@ -542,26 +540,26 @@ namespace Godot /// Encodes a <c>Variant</c> value to a byte array. /// If <paramref name="fullObjects"/> is <see langword="true"/> encoding objects is allowed /// (and can potentially include code). - /// Deserialization can be done with <see cref="Bytes2Var(Span{byte}, bool)"/>. + /// Deserialization can be done with <see cref="BytesToVar(Span{byte}, bool)"/>. /// </summary> /// <param name="var">Variant that will be encoded.</param> /// <param name="fullObjects">If objects should be serialized.</param> /// <returns>The <c>Variant</c> encoded as an array of bytes.</returns> - public static byte[] Var2Bytes(Variant var, bool fullObjects = false) + public static byte[] VarToBytes(Variant var, bool fullObjects = false) { - NativeFuncs.godotsharp_var2bytes((godot_variant)var.NativeVar, fullObjects.ToGodotBool(), out var varBytes); + NativeFuncs.godotsharp_var_to_bytes((godot_variant)var.NativeVar, fullObjects.ToGodotBool(), out var varBytes); using (varBytes) return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes); } /// <summary> /// Converts a <c>Variant</c> <paramref name="var"/> to a formatted string that - /// can later be parsed using <see cref="Str2Var(string)"/>. + /// can later be parsed using <see cref="StrToVar(string)"/>. /// </summary> /// <example> /// <code> /// var a = new Godot.Collections.Dictionary { ["a"] = 1, ["b"] = 2 }; - /// GD.Print(GD.Var2Str(a)); + /// GD.Print(GD.VarToStr(a)); /// // Prints /// // { /// // "a": 1, @@ -571,9 +569,9 @@ namespace Godot /// </example> /// <param name="var">Variant that will be converted to string.</param> /// <returns>The <c>Variant</c> encoded as a string.</returns> - public static string Var2Str(Variant var) + public static string VarToStr(Variant var) { - NativeFuncs.godotsharp_var2str((godot_variant)var.NativeVar, out godot_string ret); + NativeFuncs.godotsharp_var_to_str((godot_variant)var.NativeVar, out godot_string ret); using (ret) return Marshaling.ConvertStringToManaged(ret); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index 08beff8104..00e775e6ad 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -35,9 +35,9 @@ namespace Godot public const real_t NaN = real_t.NaN; // 0.0174532924f and 0.0174532925199433 - private const real_t _deg2RadConst = (real_t)0.0174532925199432957692369077M; + private const real_t _degToRadConst = (real_t)0.0174532925199432957692369077M; // 57.29578f and 57.2957795130823 - private const real_t _rad2DegConst = (real_t)57.295779513082320876798154814M; + private const real_t _radToDegConst = (real_t)57.295779513082320876798154814M; /// <summary> /// Returns the absolute value of <paramref name="s"/> (i.e. positive value). @@ -219,9 +219,9 @@ namespace Godot /// </summary> /// <param name="deg">An angle expressed in degrees.</param> /// <returns>The same angle expressed in radians.</returns> - public static real_t Deg2Rad(real_t deg) + public static real_t DegToRad(real_t deg) { - return deg * _deg2RadConst; + return deg * _degToRadConst; } /// <summary> @@ -531,9 +531,9 @@ namespace Godot /// </summary> /// <param name="rad">An angle expressed in radians.</param> /// <returns>The same angle expressed in degrees.</returns> - public static real_t Rad2Deg(real_t rad) + public static real_t RadToDeg(real_t rad) { - return rad * _rad2DegConst; + return rad * _radToDegConst; } /// <summary> @@ -754,9 +754,10 @@ namespace Godot } /// <summary> - /// Returns the [code]value[/code] wrapped between [code]0[/code] and the [code]length[/code]. - /// If the limit is reached, the next value the function returned is decreased to the [code]0[/code] side or increased to the [code]length[/code] side (like a triangle wave). - /// If [code]length[/code] is less than zero, it becomes positive. + /// Returns the <paramref name="value"/> wrapped between <c>0</c> and the <paramref name="length"/>. + /// If the limit is reached, the next value the function returned is decreased to the <c>0</c> side + /// or increased to the <paramref name="length"/> side (like a triangle wave). + /// If <paramref name="length"/> is less than zero, it becomes positive. /// </summary> /// <param name="value">The value to pingpong.</param> /// <param name="length">The maximum value of the function.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index 6d2534e6f7..48c1b48c59 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -461,7 +461,7 @@ namespace Godot.NativeInterop // GD, etc - internal static partial void godotsharp_bytes2var(in godot_packed_byte_array p_bytes, + internal static partial void godotsharp_bytes_to_var(in godot_packed_byte_array p_bytes, godot_bool p_allow_objects, out godot_variant r_ret); @@ -504,12 +504,12 @@ namespace Godot.NativeInterop internal static partial void godotsharp_str(in godot_array p_what, out godot_string r_ret); - internal static partial void godotsharp_str2var(in godot_string p_str, out godot_variant r_ret); + internal static partial void godotsharp_str_to_var(in godot_string p_str, out godot_variant r_ret); - internal static partial void godotsharp_var2bytes(in godot_variant p_what, godot_bool p_full_objects, + internal static partial void godotsharp_var_to_bytes(in godot_variant p_what, godot_bool p_full_objects, out godot_packed_byte_array r_bytes); - internal static partial void godotsharp_var2str(in godot_variant p_var, out godot_string r_ret); + internal static partial void godotsharp_var_to_str(in godot_variant p_var, out godot_string r_ret); internal static partial void godotsharp_pusherror(in godot_string p_str); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 50832d7679..13070c8033 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -353,12 +353,7 @@ namespace Godot /// <returns>Whether or not the plane and the other object are exactly equal.</returns> public override bool Equals(object obj) { - if (obj is Plane) - { - return Equals((Plane)obj); - } - - return false; + return obj is Plane other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs index b85a105a0b..9d08e7120a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs @@ -39,22 +39,22 @@ namespace Godot } /// <summary> - /// The projections's X column. Also accessible by using the index position <c>[0]</c>. + /// The projection's X column. Also accessible by using the index position <c>[0]</c>. /// </summary> public Vector4 x; /// <summary> - /// The projections's Y column. Also accessible by using the index position <c>[1]</c>. + /// The projection's Y column. Also accessible by using the index position <c>[1]</c>. /// </summary> public Vector4 y; /// <summary> - /// The projections's Z column. Also accessible by using the index position <c>[2]</c>. + /// The projection's Z column. Also accessible by using the index position <c>[2]</c>. /// </summary> public Vector4 z; /// <summary> - /// The projections's W column. Also accessible by using the index position <c>[3]</c>. + /// The projection's W column. Also accessible by using the index position <c>[3]</c>. /// </summary> public Vector4 w; @@ -226,7 +226,7 @@ namespace Godot { fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect); } - real_t radians = Mathf.Deg2Rad(fovyDegrees / (real_t)2.0); + real_t radians = Mathf.DegToRad(fovyDegrees / (real_t)2.0); real_t deltaZ = zFar - zNear; real_t sine = Mathf.Sin(radians); @@ -256,7 +256,7 @@ namespace Godot fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect); } - real_t ymax = zNear * Mathf.Tan(Mathf.Deg2Rad(fovyDegrees / (real_t)2.0)); + real_t ymax = zNear * Mathf.Tan(Mathf.DegToRad(fovyDegrees / (real_t)2.0)); real_t xmax = ymax * aspect; real_t frustumshift = (intraocularDist / (real_t)2.0) * zNear / convergenceDist; real_t left; @@ -313,18 +313,18 @@ namespace Godot Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized(); if (z.x == 0 && z.y == 0) { - return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))) * (real_t)2.0; + return Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))) * (real_t)2.0; } else { Plane leftPlane = new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x).Normalized(); - return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.x))) + Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))); + return Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.x))) + Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))); } } public static real_t GetFovy(real_t fovx, real_t aspect) { - return Mathf.Rad2Deg(Mathf.Atan(aspect * Mathf.Tan(Mathf.Deg2Rad(fovx) * (real_t)0.5)) * (real_t)2.0); + return Mathf.RadToDeg(Mathf.Atan(aspect * Mathf.Tan(Mathf.DegToRad(fovx) * (real_t)0.5)) * (real_t)2.0); } public real_t GetLodMultiplier() @@ -800,11 +800,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Projection) - { - return Equals((Projection)obj); - } - return false; + return obj is Projection other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs index 658a14ca1d..999500ca13 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs @@ -580,12 +580,7 @@ namespace Godot /// <returns>Whether or not the quaternion and the other object are exactly equal.</returns> public override bool Equals(object obj) { - if (obj is Quaternion) - { - return Equals((Quaternion)obj); - } - - return false; + return obj is Quaternion other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs index d2c9b0ca8b..0b475fec19 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs @@ -426,12 +426,7 @@ namespace Godot /// <returns>Whether or not the rect and the other object are exactly equal.</returns> public override bool Equals(object obj) { - if (obj is Rect2) - { - return Equals((Rect2)obj); - } - - return false; + return obj is Rect2 other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs index 5d53b8330e..8a2a98d6ee 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs @@ -426,12 +426,7 @@ namespace Godot /// <returns>Whether or not the rect and the other object are equal.</returns> public override bool Equals(object obj) { - if (obj is Rect2i) - { - return Equals((Rect2i)obj); - } - - return false; + return obj is Rect2i other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs index 10739c02a7..b9ee0bc278 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs @@ -59,9 +59,9 @@ namespace Godot } /// <summary> - /// Constructs a <see cref="StringName"/> from the given <paramref name="path"/> string. + /// Constructs a <see cref="StringName"/> from the given <paramref name="name"/> string. /// </summary> - /// <param name="path">String to construct the <see cref="StringName"/> from.</param> + /// <param name="name">String to construct the <see cref="StringName"/> from.</param> public StringName(string name) { if (!string.IsNullOrEmpty(name)) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index 70cf8bbe22..33b4f11f62 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -602,7 +602,7 @@ namespace Godot /// <returns>Whether or not the transform and the object are exactly equal.</returns> public override bool Equals(object obj) { - return obj is Transform2D transform2D && Equals(transform2D); + return obj is Transform2D other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 5481225e3f..4b739bb86b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -579,12 +579,7 @@ namespace Godot /// <returns>Whether or not the transform and the object are exactly equal.</returns> public override readonly bool Equals(object obj) { - if (obj is Transform3D) - { - return Equals((Transform3D)obj); - } - - return false; + return obj is Transform3D other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 04c2ea7eb9..03ee12884b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -925,11 +925,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector2) - { - return Equals((Vector2)obj); - } - return false; + return obj is Vector2 other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index a8f42972d7..666616edec 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -667,12 +667,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector2i) - { - return Equals((Vector2i)obj); - } - - return false; + return obj is Vector2i other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index d5941d6b60..cdba06c089 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -993,12 +993,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector3) - { - return Equals((Vector3)obj); - } - - return false; + return obj is Vector3 other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index eb46f36e7c..2947ef94a7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -676,12 +676,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector3i) - { - return Equals((Vector3i)obj); - } - - return false; + return obj is Vector3i other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs index 20a24616ce..705da04692 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs @@ -754,12 +754,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector4) - { - return Equals((Vector4)obj); - } - - return false; + return obj is Vector4 other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs index 11c2b7234b..73134b0baf 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs @@ -629,12 +629,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector4i) - { - return Equals((Vector4i)obj); - } - - return false; + return obj is Vector4i other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index f0d6748b73..aae7a5ebfa 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -56,6 +56,7 @@ <Compile Include="Core\Attributes\ExportCategoryAttribute.cs" /> <Compile Include="Core\Attributes\ExportGroupAttribute.cs" /> <Compile Include="Core\Attributes\ExportSubgroupAttribute.cs" /> + <Compile Include="Core\Attributes\MustBeVariantAttribute.cs" /> <Compile Include="Core\Attributes\RPCAttribute.cs" /> <Compile Include="Core\Attributes\ScriptPathAttribute.cs" /> <Compile Include="Core\Attributes\SignalAttribute.cs" /> diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index 13d4395a64..0d68cb54b9 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -1233,13 +1233,13 @@ void godotsharp_pushwarning(const godot_string *p_str) { WARN_PRINT(*reinterpret_cast<const String *>(p_str)); } -void godotsharp_var2str(const godot_variant *p_var, godot_string *r_ret) { +void godotsharp_var_to_str(const godot_variant *p_var, godot_string *r_ret) { const Variant &var = *reinterpret_cast<const Variant *>(p_var); String &vars = *memnew_placement(r_ret, String); VariantWriter::write_to_string(var, vars); } -void godotsharp_str2var(const godot_string *p_str, godot_variant *r_ret) { +void godotsharp_str_to_var(const godot_string *p_str, godot_variant *r_ret) { Variant ret; VariantParser::StreamString ss; @@ -1256,7 +1256,7 @@ void godotsharp_str2var(const godot_string *p_str, godot_variant *r_ret) { memnew_placement(r_ret, Variant(ret)); } -void godotsharp_var2bytes(const godot_variant *p_var, bool p_full_objects, godot_packed_array *r_bytes) { +void godotsharp_var_to_bytes(const godot_variant *p_var, bool p_full_objects, godot_packed_array *r_bytes) { const Variant &var = *reinterpret_cast<const Variant *>(p_var); PackedByteArray &bytes = *memnew_placement(r_bytes, PackedByteArray); @@ -1268,7 +1268,7 @@ void godotsharp_var2bytes(const godot_variant *p_var, bool p_full_objects, godot encode_variant(var, bytes.ptrw(), len, p_full_objects); } -void godotsharp_bytes2var(const godot_packed_array *p_bytes, bool p_allow_objects, godot_variant *r_ret) { +void godotsharp_bytes_to_var(const godot_packed_array *p_bytes, bool p_allow_objects, godot_variant *r_ret) { const PackedByteArray *bytes = reinterpret_cast<const PackedByteArray *>(p_bytes); Variant ret; Error err = decode_variant(ret, bytes->ptr(), bytes->size(), nullptr, p_allow_objects); @@ -1479,7 +1479,7 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_node_path_get_subname, (void *)godotsharp_node_path_get_subname_count, (void *)godotsharp_node_path_is_absolute, - (void *)godotsharp_bytes2var, + (void *)godotsharp_bytes_to_var, (void *)godotsharp_convert, (void *)godotsharp_hash, (void *)godotsharp_instance_from_id, @@ -1499,9 +1499,9 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_seed, (void *)godotsharp_weakref, (void *)godotsharp_str, - (void *)godotsharp_str2var, - (void *)godotsharp_var2bytes, - (void *)godotsharp_var2str, + (void *)godotsharp_str_to_var, + (void *)godotsharp_var_to_bytes, + (void *)godotsharp_var_to_str, (void *)godotsharp_pusherror, (void *)godotsharp_pushwarning, (void *)godotsharp_object_to_string, diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 6bb522cc01..4191e46f62 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -453,11 +453,11 @@ COMMAND_2(agent_set_map, RID, p_agent, RID, p_map) { } } -COMMAND_2(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist) { +COMMAND_2(agent_set_neighbor_distance, RID, p_agent, real_t, p_distance) { RvoAgent *agent = agent_owner.get_or_null(p_agent); ERR_FAIL_COND(agent == nullptr); - agent->get_agent()->neighborDist_ = p_dist; + agent->get_agent()->neighborDist_ = p_distance; } COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count) { diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index e5f4b421bc..05ba46ede1 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -135,7 +135,7 @@ public: virtual RID agent_create() const override; COMMAND_2(agent_set_map, RID, p_agent, RID, p_map); virtual RID agent_get_map(RID p_agent) const override; - COMMAND_2(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist); + COMMAND_2(agent_set_neighbor_distance, RID, p_agent, real_t, p_distance); COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count); COMMAND_2(agent_set_time_horizon, RID, p_agent, real_t, p_time); COMMAND_2(agent_set_radius, RID, p_agent, real_t, p_radius); diff --git a/modules/noise/config.py b/modules/noise/config.py index 74db20f2a4..2318d28c53 100644 --- a/modules/noise/config.py +++ b/modules/noise/config.py @@ -10,7 +10,7 @@ def get_doc_classes(): return [ "FastNoiseLite", "Noise", - "NoiseTexture", + "NoiseTexture2D", ] diff --git a/modules/noise/doc_classes/NoiseTexture.xml b/modules/noise/doc_classes/NoiseTexture2D.xml index 62a223b387..9eea2738c5 100644 --- a/modules/noise/doc_classes/NoiseTexture.xml +++ b/modules/noise/doc_classes/NoiseTexture2D.xml @@ -1,14 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NoiseTexture" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> +<class name="NoiseTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> A texture filled with noise generated by a [Noise] object. </brief_description> <description> Uses [FastNoiseLite] or other libraries to fill the texture data of your desired size. - NoiseTexture can also generate normalmap textures. + NoiseTexture2D can also generate normalmap textures. The class uses [Thread]s to generate the texture data internally, so [method Texture2D.get_image] may return [code]null[/code] if the generation process has not completed yet. In that case, you need to wait for the texture to be generated before accessing the image and the generated byte data: [codeblock] - var texture = NoiseTexture.new() + var texture = NoiseTexture2D.new() texture.noise = FastNoiseLite.new() await texture.changed var image = texture.get_image() diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp index 27a86f45b5..b6f7cbd2f8 100644 --- a/modules/noise/editor/noise_editor_plugin.cpp +++ b/modules/noise/editor/noise_editor_plugin.cpp @@ -35,7 +35,7 @@ #include "editor/editor_scale.h" #include "modules/noise/noise.h" -#include "modules/noise/noise_texture.h" +#include "modules/noise/noise_texture_2d.h" class NoisePreview : public Control { GDCLASS(NoisePreview, Control) @@ -102,7 +102,7 @@ private: void update_preview() { if (MIN(_preview_texture_size.width, _preview_texture_size.height) > 0) { - Ref<NoiseTexture> tex; + Ref<NoiseTexture2D> tex; tex.instantiate(); tex->set_width(_preview_texture_size.width); tex->set_height(_preview_texture_size.height); diff --git a/modules/noise/noise_texture.cpp b/modules/noise/noise_texture_2d.cpp index 923b420581..8d279f9dd3 100644 --- a/modules/noise/noise_texture.cpp +++ b/modules/noise/noise_texture_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* noise_texture.cpp */ +/* noise_texture_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,58 +28,58 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "noise_texture.h" +#include "noise_texture_2d.h" #include "core/core_string_names.h" #include "noise.h" -NoiseTexture::NoiseTexture() { +NoiseTexture2D::NoiseTexture2D() { noise = Ref<Noise>(); _queue_update(); } -NoiseTexture::~NoiseTexture() { +NoiseTexture2D::~NoiseTexture2D() { if (texture.is_valid()) { RS::get_singleton()->free(texture); } noise_thread.wait_to_finish(); } -void NoiseTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture); - ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture); - ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done); +void NoiseTexture2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture2D::_update_texture); + ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture2D::_generate_texture); + ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture2D::_thread_done); - ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture::set_width); - ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture::set_height); + ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture2D::set_width); + ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture2D::set_height); - ClassDB::bind_method(D_METHOD("set_invert", "invert"), &NoiseTexture::set_invert); - ClassDB::bind_method(D_METHOD("get_invert"), &NoiseTexture::get_invert); + ClassDB::bind_method(D_METHOD("set_invert", "invert"), &NoiseTexture2D::set_invert); + ClassDB::bind_method(D_METHOD("get_invert"), &NoiseTexture2D::get_invert); - ClassDB::bind_method(D_METHOD("set_in_3d_space", "enable"), &NoiseTexture::set_in_3d_space); - ClassDB::bind_method(D_METHOD("is_in_3d_space"), &NoiseTexture::is_in_3d_space); + ClassDB::bind_method(D_METHOD("set_in_3d_space", "enable"), &NoiseTexture2D::set_in_3d_space); + ClassDB::bind_method(D_METHOD("is_in_3d_space"), &NoiseTexture2D::is_in_3d_space); - ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "invert"), &NoiseTexture::set_generate_mipmaps); - ClassDB::bind_method(D_METHOD("is_generating_mipmaps"), &NoiseTexture::is_generating_mipmaps); + ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "invert"), &NoiseTexture2D::set_generate_mipmaps); + ClassDB::bind_method(D_METHOD("is_generating_mipmaps"), &NoiseTexture2D::is_generating_mipmaps); - ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless); - ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless); + ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture2D::set_seamless); + ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture2D::get_seamless); - ClassDB::bind_method(D_METHOD("set_seamless_blend_skirt", "seamless_blend_skirt"), &NoiseTexture::set_seamless_blend_skirt); - ClassDB::bind_method(D_METHOD("get_seamless_blend_skirt"), &NoiseTexture::get_seamless_blend_skirt); + ClassDB::bind_method(D_METHOD("set_seamless_blend_skirt", "seamless_blend_skirt"), &NoiseTexture2D::set_seamless_blend_skirt); + ClassDB::bind_method(D_METHOD("get_seamless_blend_skirt"), &NoiseTexture2D::get_seamless_blend_skirt); - ClassDB::bind_method(D_METHOD("set_as_normal_map", "as_normal_map"), &NoiseTexture::set_as_normal_map); - ClassDB::bind_method(D_METHOD("is_normal_map"), &NoiseTexture::is_normal_map); + ClassDB::bind_method(D_METHOD("set_as_normal_map", "as_normal_map"), &NoiseTexture2D::set_as_normal_map); + ClassDB::bind_method(D_METHOD("is_normal_map"), &NoiseTexture2D::is_normal_map); - ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture::set_bump_strength); - ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture::get_bump_strength); + ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture2D::set_bump_strength); + ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture2D::get_bump_strength); - ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &NoiseTexture::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp"), &NoiseTexture::get_color_ramp); + ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &NoiseTexture2D::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &NoiseTexture2D::get_color_ramp); - ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise); - ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise); + ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture2D::set_noise); + ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture2D::get_noise); ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater,suffix:px"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater,suffix:px"), "set_height", "get_height"); @@ -94,7 +94,7 @@ void NoiseTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "Noise"), "set_noise", "get_noise"); } -void NoiseTexture::_validate_property(PropertyInfo &p_property) const { +void NoiseTexture2D::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "bump_strength") { if (!as_normal_map) { p_property.usage = PROPERTY_USAGE_NO_EDITOR; @@ -108,7 +108,7 @@ void NoiseTexture::_validate_property(PropertyInfo &p_property) const { } } -void NoiseTexture::_set_texture_image(const Ref<Image> &p_image) { +void NoiseTexture2D::_set_texture_image(const Ref<Image> &p_image) { image = p_image; if (image.is_valid()) { if (texture.is_valid()) { @@ -121,7 +121,7 @@ void NoiseTexture::_set_texture_image(const Ref<Image> &p_image) { emit_changed(); } -void NoiseTexture::_thread_done(const Ref<Image> &p_image) { +void NoiseTexture2D::_thread_done(const Ref<Image> &p_image) { _set_texture_image(p_image); noise_thread.wait_to_finish(); if (regen_queued) { @@ -130,12 +130,12 @@ void NoiseTexture::_thread_done(const Ref<Image> &p_image) { } } -void NoiseTexture::_thread_function(void *p_ud) { - NoiseTexture *tex = static_cast<NoiseTexture *>(p_ud); +void NoiseTexture2D::_thread_function(void *p_ud) { + NoiseTexture2D *tex = static_cast<NoiseTexture2D *>(p_ud); tex->call_deferred(SNAME("_thread_done"), tex->_generate_texture()); } -void NoiseTexture::_queue_update() { +void NoiseTexture2D::_queue_update() { if (update_queued) { return; } @@ -144,7 +144,7 @@ void NoiseTexture::_queue_update() { call_deferred(SNAME("_update_texture")); } -Ref<Image> NoiseTexture::_generate_texture() { +Ref<Image> NoiseTexture2D::_generate_texture() { // Prevent memdelete due to unref() on other thread. Ref<Noise> ref_noise = noise; @@ -172,7 +172,7 @@ Ref<Image> NoiseTexture::_generate_texture() { return image; } -Ref<Image> NoiseTexture::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradient> p_gradient) { +Ref<Image> NoiseTexture2D::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradient> p_gradient) { int width = p_image->get_width(); int height = p_image->get_height(); @@ -191,7 +191,7 @@ Ref<Image> NoiseTexture::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradien return new_image; } -void NoiseTexture::_update_texture() { +void NoiseTexture2D::_update_texture() { bool use_thread = true; if (first_time) { use_thread = false; @@ -215,25 +215,25 @@ void NoiseTexture::_update_texture() { update_queued = false; } -void NoiseTexture::set_noise(Ref<Noise> p_noise) { +void NoiseTexture2D::set_noise(Ref<Noise> p_noise) { if (p_noise == noise) { return; } if (noise.is_valid()) { - noise->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + noise->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture2D::_queue_update)); } noise = p_noise; if (noise.is_valid()) { - noise->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + noise->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture2D::_queue_update)); } _queue_update(); } -Ref<Noise> NoiseTexture::get_noise() { +Ref<Noise> NoiseTexture2D::get_noise() { return noise; } -void NoiseTexture::set_width(int p_width) { +void NoiseTexture2D::set_width(int p_width) { ERR_FAIL_COND(p_width <= 0); if (p_width == size.x) { return; @@ -242,7 +242,7 @@ void NoiseTexture::set_width(int p_width) { _queue_update(); } -void NoiseTexture::set_height(int p_height) { +void NoiseTexture2D::set_height(int p_height) { ERR_FAIL_COND(p_height <= 0); if (p_height == size.y) { return; @@ -251,7 +251,7 @@ void NoiseTexture::set_height(int p_height) { _queue_update(); } -void NoiseTexture::set_invert(bool p_invert) { +void NoiseTexture2D::set_invert(bool p_invert) { if (p_invert == invert) { return; } @@ -259,22 +259,22 @@ void NoiseTexture::set_invert(bool p_invert) { _queue_update(); } -bool NoiseTexture::get_invert() const { +bool NoiseTexture2D::get_invert() const { return invert; } -void NoiseTexture::set_in_3d_space(bool p_enable) { +void NoiseTexture2D::set_in_3d_space(bool p_enable) { if (p_enable == in_3d_space) { return; } in_3d_space = p_enable; _queue_update(); } -bool NoiseTexture::is_in_3d_space() const { +bool NoiseTexture2D::is_in_3d_space() const { return in_3d_space; } -void NoiseTexture::set_generate_mipmaps(bool p_enable) { +void NoiseTexture2D::set_generate_mipmaps(bool p_enable) { if (p_enable == generate_mipmaps) { return; } @@ -282,11 +282,11 @@ void NoiseTexture::set_generate_mipmaps(bool p_enable) { _queue_update(); } -bool NoiseTexture::is_generating_mipmaps() const { +bool NoiseTexture2D::is_generating_mipmaps() const { return generate_mipmaps; } -void NoiseTexture::set_seamless(bool p_seamless) { +void NoiseTexture2D::set_seamless(bool p_seamless) { if (p_seamless == seamless) { return; } @@ -295,11 +295,11 @@ void NoiseTexture::set_seamless(bool p_seamless) { notify_property_list_changed(); } -bool NoiseTexture::get_seamless() { +bool NoiseTexture2D::get_seamless() { return seamless; } -void NoiseTexture::set_seamless_blend_skirt(real_t p_blend_skirt) { +void NoiseTexture2D::set_seamless_blend_skirt(real_t p_blend_skirt) { ERR_FAIL_COND(p_blend_skirt < 0.05 || p_blend_skirt > 1); if (p_blend_skirt == seamless_blend_skirt) { @@ -308,11 +308,11 @@ void NoiseTexture::set_seamless_blend_skirt(real_t p_blend_skirt) { seamless_blend_skirt = p_blend_skirt; _queue_update(); } -real_t NoiseTexture::get_seamless_blend_skirt() { +real_t NoiseTexture2D::get_seamless_blend_skirt() { return seamless_blend_skirt; } -void NoiseTexture::set_as_normal_map(bool p_as_normal_map) { +void NoiseTexture2D::set_as_normal_map(bool p_as_normal_map) { if (p_as_normal_map == as_normal_map) { return; } @@ -321,11 +321,11 @@ void NoiseTexture::set_as_normal_map(bool p_as_normal_map) { notify_property_list_changed(); } -bool NoiseTexture::is_normal_map() { +bool NoiseTexture2D::is_normal_map() { return as_normal_map; } -void NoiseTexture::set_bump_strength(float p_bump_strength) { +void NoiseTexture2D::set_bump_strength(float p_bump_strength) { if (p_bump_strength == bump_strength) { return; } @@ -335,37 +335,37 @@ void NoiseTexture::set_bump_strength(float p_bump_strength) { } } -float NoiseTexture::get_bump_strength() { +float NoiseTexture2D::get_bump_strength() { return bump_strength; } -void NoiseTexture::set_color_ramp(const Ref<Gradient> &p_gradient) { +void NoiseTexture2D::set_color_ramp(const Ref<Gradient> &p_gradient) { if (p_gradient == color_ramp) { return; } if (color_ramp.is_valid()) { - color_ramp->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + color_ramp->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture2D::_queue_update)); } color_ramp = p_gradient; if (color_ramp.is_valid()) { - color_ramp->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + color_ramp->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture2D::_queue_update)); } _queue_update(); } -Ref<Gradient> NoiseTexture::get_color_ramp() const { +Ref<Gradient> NoiseTexture2D::get_color_ramp() const { return color_ramp; } -int NoiseTexture::get_width() const { +int NoiseTexture2D::get_width() const { return size.x; } -int NoiseTexture::get_height() const { +int NoiseTexture2D::get_height() const { return size.y; } -RID NoiseTexture::get_rid() const { +RID NoiseTexture2D::get_rid() const { if (!texture.is_valid()) { texture = RS::get_singleton()->texture_2d_placeholder_create(); } @@ -373,6 +373,6 @@ RID NoiseTexture::get_rid() const { return texture; } -Ref<Image> NoiseTexture::get_image() const { +Ref<Image> NoiseTexture2D::get_image() const { return image; } diff --git a/modules/noise/noise_texture.h b/modules/noise/noise_texture_2d.h index 83fbcc2d10..8f8e256fb9 100644 --- a/modules/noise/noise_texture.h +++ b/modules/noise/noise_texture_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* noise_texture.h */ +/* noise_texture_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NOISE_TEXTURE_H -#define NOISE_TEXTURE_H +#ifndef NOISE_TEXTURE_2D_H +#define NOISE_TEXTURE_2D_H #include "noise.h" #include "core/object/ref_counted.h" #include "scene/resources/texture.h" -class NoiseTexture : public Texture2D { - GDCLASS(NoiseTexture, Texture2D); +class NoiseTexture2D : public Texture2D { + GDCLASS(NoiseTexture2D, Texture2D); private: Ref<Image> image; @@ -116,8 +116,8 @@ public: virtual Ref<Image> get_image() const override; - NoiseTexture(); - virtual ~NoiseTexture(); + NoiseTexture2D(); + virtual ~NoiseTexture2D(); }; -#endif // NOISE_TEXTURE_H +#endif // NOISE_TEXTURE_2D_H diff --git a/modules/noise/register_types.cpp b/modules/noise/register_types.cpp index d0cfc4e944..c44bf9828f 100644 --- a/modules/noise/register_types.cpp +++ b/modules/noise/register_types.cpp @@ -32,7 +32,7 @@ #include "fastnoise_lite.h" #include "noise.h" -#include "noise_texture.h" +#include "noise_texture_2d.h" #ifdef TOOLS_ENABLED #include "editor/editor_plugin.h" @@ -41,9 +41,10 @@ void initialize_noise_module(ModuleInitializationLevel p_level) { if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) { - GDREGISTER_CLASS(NoiseTexture); + GDREGISTER_CLASS(NoiseTexture2D); GDREGISTER_ABSTRACT_CLASS(Noise); GDREGISTER_CLASS(FastNoiseLite); + ClassDB::add_compatibility_class("NoiseTexture", "NoiseTexture2D"); } #ifdef TOOLS_ENABLED diff --git a/modules/raycast/SCsub b/modules/raycast/SCsub index ef4c598194..074795759a 100644 --- a/modules/raycast/SCsub +++ b/modules/raycast/SCsub @@ -66,7 +66,7 @@ if env["builtin_embree"]: env_raycast.Append(CPPDEFINES=["EMBREE_TARGET_SSE2", "EMBREE_LOWEST_ISA", "TASKING_INTERNAL", "NDEBUG"]) if not env.msvc: - if env["arch"] in ["x86", "x86_64"]: + if env["arch"] == "x86_64": env_raycast.Append(CPPFLAGS=["-msse2", "-mxsave"]) if env["platform"] == "windows": @@ -83,7 +83,7 @@ if env["builtin_embree"]: env_thirdparty.disable_warnings() env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources) - if not env["arch"] in ["x86", "x86_64"] or env.msvc: + if env["arch"] == "arm64" or env.msvc: # Embree needs those, it will automatically use SSE2NEON in ARM env_thirdparty.Append(CPPDEFINES=["__SSE2__", "__SSE__"]) diff --git a/modules/raycast/config.py b/modules/raycast/config.py index 7e8b3e9840..438779343e 100644 --- a/modules/raycast/config.py +++ b/modules/raycast/config.py @@ -1,18 +1,6 @@ def can_build(env, platform): - # Depends on Embree library, which only supports x86_64 and aarch64. - if env["arch"].startswith("rv") or env["arch"].startswith("ppc"): - return False - - if platform == "android": - return env["android_arch"] in ["arm64v8", "x86_64"] - - if platform == "javascript": - return False # No SIMD support yet - - if env["bits"] == "32": - return False - - return True + # Depends on Embree library, which only supports x86_64 and arm64. + return env["arch"] in ["x86_64", "arm64"] def configure(env): diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index 4c9302eb0c..5f839bd979 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -136,11 +136,11 @@ void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const p_extensions->push_back("svg"); } -Error ImageLoaderSVG::load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, bool p_force_linear, float p_scale) { +Error ImageLoaderSVG::load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, uint32_t p_flags, float p_scale) { String svg = p_fileaccess->get_as_utf8_string(); create_image_from_string(p_image, svg, p_scale, false, HashMap<Color, Color>()); ERR_FAIL_COND_V(p_image->is_empty(), FAILED); - if (p_force_linear) { + if (p_flags & FLAG_FORCE_LINEAR) { p_image->srgb_to_linear(); } return OK; diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h index f28df60c44..fc89b63edb 100644 --- a/modules/svg/image_loader_svg.h +++ b/modules/svg/image_loader_svg.h @@ -39,7 +39,7 @@ class ImageLoaderSVG : public ImageFormatLoader { public: void create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, const HashMap<Color, Color> &p_color_map); - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, bool p_force_linear, float p_scale) override; + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, uint32_t p_flags, float p_scale) override; virtual void get_recognized_extensions(List<String> *p_extensions) const override; }; diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index e80eb43369..366e1ba604 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -29,12 +29,12 @@ /*************************************************************************/ #include "text_server_adv.h" -#include "core/object/worker_thread_pool.h" #ifdef GDEXTENSION // Headers for building as GDExtension plug-in. #include <godot_cpp/classes/file.hpp> +#include <godot_cpp/classes/project_settings.hpp> #include <godot_cpp/classes/rendering_server.hpp> #include <godot_cpp/classes/translation_server.hpp> #include <godot_cpp/core/error_macros.hpp> @@ -44,8 +44,10 @@ using namespace godot; #else // Headers for building as built-in module. +#include "core/config/project_settings.h" #include "core/core_bind.h" #include "core/error/error_macros.h" +#include "core/object/worker_thread_pool.h" #include "core/string/print_string.h" #include "core/string/translation.h" @@ -791,6 +793,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_ for (int i = 0; i < p_data->textures.size(); i++) { const FontTexture &ct = p_data->textures[i]; + if (p_image_format != ct.format) { + continue; + } + if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture. continue; } @@ -1082,9 +1088,28 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( #endif #ifdef MODULE_FREETYPE_ENABLED -_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { +_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const { int w = bitmap.width; int h = bitmap.rows; + int color_size = 2; + + switch (bitmap.pixel_mode) { + case FT_PIXEL_MODE_MONO: + case FT_PIXEL_MODE_GRAY: { + color_size = 2; + } break; + case FT_PIXEL_MODE_BGRA: { + color_size = 4; + } break; + case FT_PIXEL_MODE_LCD: { + color_size = 4; + w /= 3; + } break; + case FT_PIXEL_MODE_LCD_V: { + color_size = 4; + h /= 3; + } break; + } int mw = w + p_rect_margin * 4; int mh = h + p_rect_margin * 4; @@ -1092,7 +1117,6 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, 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, false); @@ -1127,6 +1151,34 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; wr[ofs + 3] = bitmap.buffer[ofs_color + 3]; } break; + case FT_PIXEL_MODE_LCD: { + int ofs_color = i * bitmap.pitch + (j * 3); + if (p_bgra) { + wr[ofs + 0] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = bitmap.buffer[ofs_color + 1]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 2]; + wr[ofs + 3] = 255; + } else { + wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; + wr[ofs + 1] = bitmap.buffer[ofs_color + 1]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 3] = 255; + } + } break; + case FT_PIXEL_MODE_LCD_V: { + int ofs_color = i * bitmap.pitch * 3 + j; + if (p_bgra) { + wr[ofs + 0] = bitmap.buffer[ofs_color + bitmap.pitch * 2]; + wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 3] = 255; + } else { + wr[ofs + 0] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch]; + wr[ofs + 2] = bitmap.buffer[ofs_color + bitmap.pitch * 2]; + wr[ofs + 3] = 255; + } + } break; default: ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + "."); break; @@ -1230,9 +1282,44 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, FT_Outline_Transform(&fd->face->glyph->outline, &mat); } + FT_Render_Mode aa_mode = FT_RENDER_MODE_NORMAL; + bool bgra = false; + switch (p_font_data->antialiasing) { + case FONT_ANTIALIASING_NONE: { + aa_mode = FT_RENDER_MODE_MONO; + } break; + case FONT_ANTIALIASING_GRAY: { + aa_mode = FT_RENDER_MODE_NORMAL; + } break; + case FONT_ANTIALIASING_LCD: { + int aa_layout = (int)((p_glyph >> 24) & 7); + switch (aa_layout) { + case FONT_LCD_SUBPIXEL_LAYOUT_HRGB: { + aa_mode = FT_RENDER_MODE_LCD; + bgra = false; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_HBGR: { + aa_mode = FT_RENDER_MODE_LCD; + bgra = true; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_VRGB: { + aa_mode = FT_RENDER_MODE_LCD_V; + bgra = false; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_VBGR: { + aa_mode = FT_RENDER_MODE_LCD_V; + bgra = true; + } break; + default: { + aa_mode = FT_RENDER_MODE_NORMAL; + } break; + } + } break; + } + 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); + error = FT_Render_Glyph(fd->face->glyph, aa_mode); } FT_GlyphSlot slot = fd->face->glyph; if (!error) { @@ -1244,7 +1331,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!"); #endif } else { - gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0); + gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, bgra); } } } else { @@ -1264,11 +1351,11 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) { goto cleanup_glyph; } - if (FT_Glyph_To_Bitmap(&glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, nullptr, 1) != 0) { + if (FT_Glyph_To_Bitmap(&glyph, aa_mode, nullptr, 1) != 0) { goto cleanup_glyph; } glyph_bitmap = (FT_BitmapGlyph)glyph; - gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2()); + gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2(), bgra); cleanup_glyph: FT_Done_Glyph(glyph); @@ -1925,23 +2012,23 @@ String TextServerAdvanced::font_get_name(const RID &p_font_rid) const { return fd->font_name; } -void TextServerAdvanced::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { +void TextServerAdvanced::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) { FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); - if (fd->antialiased != p_antialiased) { + if (fd->antialiasing != p_antialiasing) { _font_clear_cache(fd); - fd->antialiased = p_antialiased; + fd->antialiasing = p_antialiasing; } } -bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const { +TextServer::FontAntialiasing TextServerAdvanced::font_get_antialiasing(RID p_font_rid) const { FontAdvanced *fd = font_owner.get_or_null(p_font_rid); - ERR_FAIL_COND_V(!fd, false); + ERR_FAIL_COND_V(!fd, TextServer::FONT_ANTIALIASING_NONE); MutexLock lock(fd->mutex); - return fd->antialiased; + return fd->antialiasing; } void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { @@ -2514,7 +2601,16 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(const RID &p_font_rid, int64_ Vector2i size = _get_size(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2557,7 +2653,16 @@ Vector2 TextServerAdvanced::font_get_glyph_offset(const RID &p_font_rid, const V Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2593,7 +2698,16 @@ Vector2 TextServerAdvanced::font_get_glyph_size(const RID &p_font_rid, const Vec Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2629,7 +2743,16 @@ Rect2 TextServerAdvanced::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Rect2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Rect2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2660,7 +2783,16 @@ int64_t TextServerAdvanced::font_get_glyph_texture_idx(const RID &p_font_rid, co Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), -1); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return -1; // Invalid or non graphicl glyph, do not display errors. } @@ -2691,7 +2823,16 @@ RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return RID(); // Invalid or non graphicl glyph, do not display errors. } @@ -2730,7 +2871,16 @@ Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, con Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Size2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2986,16 +3136,18 @@ void TextServerAdvanced::font_render_range(const RID &p_font_rid, const Vector2i if (fd->msdf) { _ensure_glyph(fd, size, (int32_t)idx); } else { - if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); - } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - } else { - _ensure_glyph(fd, size, (int32_t)idx); + for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) { + if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24)); + } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + } else { + _ensure_glyph(fd, size, (int32_t)idx | (aa << 24)); + } } } } @@ -3016,16 +3168,18 @@ void TextServerAdvanced::font_render_glyph(const RID &p_font_rid, const Vector2i if (fd->msdf) { _ensure_glyph(fd, size, (int32_t)idx); } else { - if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); - } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - } else { - _ensure_glyph(fd, size, (int32_t)idx); + for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) { + if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24)); + } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + } else { + _ensure_glyph(fd, size, (int32_t)idx | (aa << 24)); + } } } } @@ -3041,9 +3195,19 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); int32_t index = p_index & 0xffffff; // Remove subpixel shifts. + bool lcd_aa = false; #ifdef MODULE_FREETYPE_ENABLED if (!fd->msdf && fd->cache[size]->face) { + // LCD layout, bits 24, 25, 26 + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + lcd_aa = true; + index = index | (layout << 24); + } + } + // Subpixel X-shift, bits 27, 28 if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); index = index | (xshift << 27); @@ -3065,7 +3229,7 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can if (gl.texture_idx != -1) { Color modulate = p_color; #ifdef MODULE_FREETYPE_ENABLED - if (fd->cache[size]->face && fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) { + if (fd->cache[size]->face && (fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) && !lcd_aa) { modulate.r = modulate.g = modulate.b = 1.0; } #endif @@ -3103,7 +3267,11 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can } cpos += gl.rect.position; Size2 csize = gl.rect.size; - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + if (lcd_aa) { + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate); + } else { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + } } } } @@ -3119,9 +3287,19 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); int32_t index = p_index & 0xffffff; // Remove subpixel shifts. + bool lcd_aa = false; #ifdef MODULE_FREETYPE_ENABLED if (!fd->msdf && fd->cache[size]->face) { + // LCD layout, bits 24, 25, 26 + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + lcd_aa = true; + index = index | (layout << 24); + } + } + // Subpixel X-shift, bits 27, 28 if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); index = index | (xshift << 27); @@ -3181,7 +3359,11 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI } cpos += gl.rect.position; Size2 csize = gl.rect.size; - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + if (lcd_aa) { + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate); + } else { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + } } } } @@ -4947,6 +5129,14 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(p_sd->hb_buffer, &glyph_count); hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(p_sd->hb_buffer, &glyph_count); + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + // Process glyphs. if (glyph_count > 0) { Glyph *w = (Glyph *)memalloc(glyph_count * sizeof(Glyph)); @@ -5000,7 +5190,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star gl.index = glyph_info[i].codepoint; if (gl.index != 0) { - _ensure_glyph(fd, fss, gl.index); + _ensure_glyph(fd, fss, gl.index | mod); if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (subpos) { gl.advance = glyph_pos[i].x_advance / (64.0 / scale) + ea; diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 6c3e8dbdcb..02abc31c55 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -223,7 +223,7 @@ class TextServerAdvanced : public TextServerExtension { struct FontAdvanced { Mutex mutex; - bool antialiased = true; + TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY; bool mipmaps = false; bool msdf = false; int msdf_range = 14; @@ -271,7 +271,7 @@ class TextServerAdvanced : public TextServerExtension { _FORCE_INLINE_ FontGlyph rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; #endif #ifdef MODULE_FREETYPE_ENABLED - _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; + _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const; #endif _FORCE_INLINE_ bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; _FORCE_INLINE_ bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const; @@ -498,8 +498,8 @@ public: virtual void font_set_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_name(const RID &p_font_rid) const override; - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; - virtual bool font_is_antialiased(const RID &p_font_rid) const override; + virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override; + virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual bool font_get_generate_mipmaps(const 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 016bcfc886..53b303cb20 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -34,6 +34,7 @@ // Headers for building as GDExtension plug-in. #include <godot_cpp/classes/file.hpp> +#include <godot_cpp/classes/project_settings.hpp> #include <godot_cpp/classes/rendering_server.hpp> #include <godot_cpp/classes/translation_server.hpp> #include <godot_cpp/core/error_macros.hpp> @@ -43,6 +44,7 @@ using namespace godot; #else // Headers for building as built-in module. +#include "core/config/project_settings.h" #include "core/error/error_macros.h" #include "core/string/print_string.h" #include "core/string/ucaps.h" @@ -209,6 +211,10 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_ for (int i = 0; i < p_data->textures.size(); i++) { const FontTexture &ct = p_data->textures[i]; + if (p_image_format != ct.format) { + continue; + } + if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture. continue; } @@ -500,9 +506,28 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( #endif #ifdef MODULE_FREETYPE_ENABLED -_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { +_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const { int w = bitmap.width; int h = bitmap.rows; + int color_size = 2; + + switch (bitmap.pixel_mode) { + case FT_PIXEL_MODE_MONO: + case FT_PIXEL_MODE_GRAY: { + color_size = 2; + } break; + case FT_PIXEL_MODE_BGRA: { + color_size = 4; + } break; + case FT_PIXEL_MODE_LCD: { + color_size = 4; + w /= 3; + } break; + case FT_PIXEL_MODE_LCD_V: { + color_size = 4; + h /= 3; + } break; + } int mw = w + p_rect_margin * 4; int mh = h + p_rect_margin * 4; @@ -510,7 +535,6 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, 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, false); @@ -545,6 +569,34 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; wr[ofs + 3] = bitmap.buffer[ofs_color + 3]; } break; + case FT_PIXEL_MODE_LCD: { + int ofs_color = i * bitmap.pitch + (j * 3); + if (p_bgra) { + wr[ofs + 0] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = bitmap.buffer[ofs_color + 1]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 2]; + wr[ofs + 3] = 255; + } else { + wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; + wr[ofs + 1] = bitmap.buffer[ofs_color + 1]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 3] = 255; + } + } break; + case FT_PIXEL_MODE_LCD_V: { + int ofs_color = i * bitmap.pitch * 3 + j; + if (p_bgra) { + wr[ofs + 0] = bitmap.buffer[ofs_color + bitmap.pitch * 2]; + wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 3] = 255; + } else { + wr[ofs + 0] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch]; + wr[ofs + 2] = bitmap.buffer[ofs_color + bitmap.pitch * 2]; + wr[ofs + 3] = 255; + } + } break; default: ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + "."); break; @@ -650,9 +702,44 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data, FT_Outline_Transform(&fd->face->glyph->outline, &mat); } + FT_Render_Mode aa_mode = FT_RENDER_MODE_NORMAL; + bool bgra = false; + switch (p_font_data->antialiasing) { + case FONT_ANTIALIASING_NONE: { + aa_mode = FT_RENDER_MODE_MONO; + } break; + case FONT_ANTIALIASING_GRAY: { + aa_mode = FT_RENDER_MODE_NORMAL; + } break; + case FONT_ANTIALIASING_LCD: { + int aa_layout = (int)((p_glyph >> 24) & 7); + switch (aa_layout) { + case FONT_LCD_SUBPIXEL_LAYOUT_HRGB: { + aa_mode = FT_RENDER_MODE_LCD; + bgra = false; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_HBGR: { + aa_mode = FT_RENDER_MODE_LCD; + bgra = true; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_VRGB: { + aa_mode = FT_RENDER_MODE_LCD_V; + bgra = false; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_VBGR: { + aa_mode = FT_RENDER_MODE_LCD_V; + bgra = true; + } break; + default: { + aa_mode = FT_RENDER_MODE_NORMAL; + } break; + } + } break; + } + 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); + error = FT_Render_Glyph(fd->face->glyph, aa_mode); } FT_GlyphSlot slot = fd->face->glyph; if (!error) { @@ -664,7 +751,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data, ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!"); #endif } else { - gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0); + gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, bgra); } } } else { @@ -684,11 +771,11 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data, if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) { goto cleanup_glyph; } - if (FT_Glyph_To_Bitmap(&glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, nullptr, 1) != 0) { + if (FT_Glyph_To_Bitmap(&glyph, aa_mode, nullptr, 1) != 0) { goto cleanup_glyph; } glyph_bitmap = (FT_BitmapGlyph)glyph; - gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2()); + gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2(), bgra); cleanup_glyph: FT_Done_Glyph(glyph); @@ -1014,23 +1101,23 @@ String TextServerFallback::font_get_name(const RID &p_font_rid) const { return fd->font_name; } -void TextServerFallback::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { +void TextServerFallback::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) { FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); - if (fd->antialiased != p_antialiased) { + if (fd->antialiasing != p_antialiasing) { _font_clear_cache(fd); - fd->antialiased = p_antialiased; + fd->antialiasing = p_antialiasing; } } -bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const { +TextServer::FontAntialiasing TextServerFallback::font_get_antialiasing(RID p_font_rid) const { FontFallback *fd = font_owner.get_or_null(p_font_rid); - ERR_FAIL_COND_V(!fd, false); + ERR_FAIL_COND_V(!fd, TextServer::FONT_ANTIALIASING_NONE); MutexLock lock(fd->mutex); - return fd->antialiased; + return fd->antialiasing; } void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { @@ -1589,7 +1676,16 @@ Vector2 TextServerFallback::font_get_glyph_advance(const RID &p_font_rid, int64_ Vector2i size = _get_size(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -1632,7 +1728,16 @@ Vector2 TextServerFallback::font_get_glyph_offset(const RID &p_font_rid, const V Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -1668,7 +1773,16 @@ Vector2 TextServerFallback::font_get_glyph_size(const RID &p_font_rid, const Vec Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -1704,7 +1818,16 @@ Rect2 TextServerFallback::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Rect2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Rect2(); // Invalid or non graphicl glyph, do not display errors. } @@ -1735,7 +1858,16 @@ int64_t TextServerFallback::font_get_glyph_texture_idx(const RID &p_font_rid, co Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), -1); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return -1; // Invalid or non graphicl glyph, do not display errors. } @@ -1766,7 +1898,16 @@ RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return RID(); // Invalid or non graphicl glyph, do not display errors. } @@ -1805,7 +1946,16 @@ Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, con Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Size2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2043,16 +2193,18 @@ void TextServerFallback::font_render_range(const RID &p_font_rid, const Vector2i if (fd->msdf) { _ensure_glyph(fd, size, (int32_t)idx); } else { - if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); - } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - } else { - _ensure_glyph(fd, size, (int32_t)idx); + for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) { + if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24)); + } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + } else { + _ensure_glyph(fd, size, (int32_t)idx | (aa << 24)); + } } } } @@ -2073,16 +2225,18 @@ void TextServerFallback::font_render_glyph(const RID &p_font_rid, const Vector2i if (fd->msdf) { _ensure_glyph(fd, size, (int32_t)idx); } else { - if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); - } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - } else { - _ensure_glyph(fd, size, (int32_t)idx); + for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) { + if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24)); + } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + } else { + _ensure_glyph(fd, size, (int32_t)idx | (aa << 24)); + } } } } @@ -2098,9 +2252,19 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); int32_t index = p_index & 0xffffff; // Remove subpixel shifts. + bool lcd_aa = false; #ifdef MODULE_FREETYPE_ENABLED if (!fd->msdf && fd->cache[size]->face) { + // LCD layout, bits 24, 25, 26 + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + lcd_aa = true; + index = index | (layout << 24); + } + } + // Subpixel X-shift, bits 27, 28 if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); index = index | (xshift << 27); @@ -2122,7 +2286,7 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can if (gl.texture_idx != -1) { Color modulate = p_color; #ifdef MODULE_FREETYPE_ENABLED - if (fd->cache[size]->face && fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) { + if (fd->cache[size]->face && (fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) && !lcd_aa) { modulate.r = modulate.g = modulate.b = 1.0; } #endif @@ -2160,7 +2324,11 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can } cpos += gl.rect.position; Size2 csize = gl.rect.size; - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + if (lcd_aa) { + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate); + } else { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + } } } } @@ -2176,9 +2344,19 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); int32_t index = p_index & 0xffffff; // Remove subpixel shifts. + bool lcd_aa = false; #ifdef MODULE_FREETYPE_ENABLED if (!fd->msdf && fd->cache[size]->face) { + // LCD layout, bits 24, 25, 26 + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + lcd_aa = true; + index = index | (layout << 24); + } + } + // Subpixel X-shift, bits 27, 28 if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); index = index | (xshift << 27); @@ -2238,7 +2416,11 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI } cpos += gl.rect.position; Size2 csize = gl.rect.size; - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + if (lcd_aa) { + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate); + } else { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + } } } } diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 8e81433a2a..940c57a354 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -179,7 +179,7 @@ class TextServerFallback : public TextServerExtension { struct FontFallback { Mutex mutex; - bool antialiased = true; + TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY; bool mipmaps = false; bool msdf = false; int msdf_range = 14; @@ -225,7 +225,7 @@ class TextServerFallback : public TextServerExtension { _FORCE_INLINE_ FontGlyph rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; #endif #ifdef MODULE_FREETYPE_ENABLED - _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; + _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const; #endif _FORCE_INLINE_ bool _ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; _FORCE_INLINE_ bool _ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const; @@ -378,8 +378,8 @@ public: virtual void font_set_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_name(const RID &p_font_rid) const override; - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; - virtual bool font_is_antialiased(const RID &p_font_rid) const override; + virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override; + virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index 08ad1ef9f8..16d9bf7b93 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -230,7 +230,7 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff return OK; } -Error ImageLoaderTGA::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) { +Error ImageLoaderTGA::load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale) { Vector<uint8_t> src_image; uint64_t src_image_len = f->get_length(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); diff --git a/modules/tga/image_loader_tga.h b/modules/tga/image_loader_tga.h index 9b7cbbac77..d95c5ff30b 100644 --- a/modules/tga/image_loader_tga.h +++ b/modules/tga/image_loader_tga.h @@ -73,7 +73,7 @@ class ImageLoaderTGA : public ImageFormatLoader { static Error convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_input_size); public: - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale); + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderTGA(); }; diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index 864df765ee..6f61251f9b 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/modules/tinyexr/image_loader_tinyexr.cpp @@ -37,7 +37,7 @@ #include "thirdparty/tinyexr/tinyexr.h" -Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) { +Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale) { Vector<uint8_t> src_image; uint64_t src_image_len = f->get_length(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); @@ -229,7 +229,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool color.a = *a_channel++; } - if (p_force_linear) { + if (p_flags & FLAG_FORCE_LINEAR) { color = color.srgb_to_linear(); } @@ -260,7 +260,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool color.a = *a_channel++; } - if (p_force_linear) { + if (p_flags & FLAG_FORCE_LINEAR) { color = color.srgb_to_linear(); } diff --git a/modules/tinyexr/image_loader_tinyexr.h b/modules/tinyexr/image_loader_tinyexr.h index 0d3de93956..8da2a0d4af 100644 --- a/modules/tinyexr/image_loader_tinyexr.h +++ b/modules/tinyexr/image_loader_tinyexr.h @@ -35,7 +35,7 @@ class ImageLoaderTinyEXR : public ImageFormatLoader { public: - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale); + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderTinyEXR(); }; diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp index 778d562278..705ab508ab 100644 --- a/modules/webp/image_loader_webp.cpp +++ b/modules/webp/image_loader_webp.cpp @@ -48,7 +48,7 @@ static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) { return img; } -Error ImageLoaderWebP::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) { +Error ImageLoaderWebP::load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale) { Vector<uint8_t> src_image; uint64_t src_image_len = f->get_length(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); diff --git a/modules/webp/image_loader_webp.h b/modules/webp/image_loader_webp.h index 9a5dc6cd7c..d868ae3f7f 100644 --- a/modules/webp/image_loader_webp.h +++ b/modules/webp/image_loader_webp.h @@ -35,7 +35,7 @@ class ImageLoaderWebP : public ImageFormatLoader { public: - virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale); + virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, uint32_t p_flags, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderWebP(); }; diff --git a/platform/android/README.md b/platform/android/README.md index 343e588553..f6aabab708 100644 --- a/platform/android/README.md +++ b/platform/android/README.md @@ -3,6 +3,13 @@ This folder contains the Java and C++ (JNI) code for the Android platform port, using [Gradle](https://gradle.org/) as a build system. +## Documentation + +- [Compiling for Android](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_android.html) + - Instructions on building this platform port from source. +- [Exporting for Android](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_android.html) + - Instructions on using the compiled export templates to export a project. + ## Artwork license [`logo.png`](logo.png) and [`run_icon.png`](run_icon.png) are licensed under diff --git a/platform/android/SCsub b/platform/android/SCsub index d370a4d18d..344ca036de 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -41,13 +41,13 @@ lib = env_android.add_shared_library("#bin/libgodot", [android_objects], SHLIBSU env.Depends(lib, thirdparty_obj) lib_arch_dir = "" -if env["android_arch"] == "armv7": +if env["arch"] == "arm32": lib_arch_dir = "armeabi-v7a" -elif env["android_arch"] == "arm64v8": +elif env["arch"] == "arm64": lib_arch_dir = "arm64-v8a" -elif env["android_arch"] == "x86": +elif env["arch"] == "x86_32": lib_arch_dir = "x86" -elif env["android_arch"] == "x86_64": +elif env["arch"] == "x86_64": lib_arch_dir = "x86_64" else: print("WARN: Architecture not suitable for embedding into APK; keeping .so at \\bin") diff --git a/platform/android/detect.py b/platform/android/detect.py index 2ff5bf59ea..ad63821162 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -22,7 +22,6 @@ def get_opts(): return [ ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_env_android_sdk_root()), ("ndk_platform", 'Target platform (android-<api>, e.g. "android-24")', "android-24"), - EnumVariable("android_arch", "Target architecture", "arm64v8", ("armv7", "arm64v8", "x86", "x86_64")), ] @@ -46,6 +45,7 @@ def get_ndk_version(): def get_flags(): return [ + ("arch", "arm64"), # Default for convenience. ("tools", False), ] @@ -75,35 +75,37 @@ def install_ndk_if_needed(env): def configure(env): + # Validate arch. + supported_arches = ["x86_32", "x86_64", "arm32", "arm64"] + if env["arch"] not in supported_arches: + print( + 'Unsupported CPU architecture "%s" for Android. Supported architectures are: %s.' + % (env["arch"], ", ".join(supported_arches)) + ) + sys.exit() + install_ndk_if_needed(env) ndk_root = env["ANDROID_NDK_ROOT"] # Architecture - if env["android_arch"] not in ["armv7", "arm64v8", "x86", "x86_64"]: - env["android_arch"] = "arm64v8" - - print("Building for Android, platform " + env["ndk_platform"] + " (" + env["android_arch"] + ")") - - if get_min_sdk_version(env["ndk_platform"]) < 21: - if env["android_arch"] == "x86_64" or env["android_arch"] == "arm64v8": - print( - "WARNING: android_arch=" - + env["android_arch"] - + " is not supported by ndk_platform lower than android-21; setting ndk_platform=android-21" - ) - env["ndk_platform"] = "android-21" + if get_min_sdk_version(env["ndk_platform"]) < 21 and env["arch"] in ["x86_64", "arm64"]: + print( + 'WARNING: arch="%s" is not supported with "ndk_platform" lower than "android-21". Forcing platform 21.' + % env["arch"] + ) + env["ndk_platform"] = "android-21" - if env["android_arch"] == "armv7": + if env["arch"] == "arm32": target_triple = "armv7a-linux-androideabi" env.extra_suffix = ".armv7" + env.extra_suffix - elif env["android_arch"] == "arm64v8": + elif env["arch"] == "arm64": target_triple = "aarch64-linux-android" env.extra_suffix = ".armv8" + env.extra_suffix - elif env["android_arch"] == "x86": + elif env["arch"] == "x86_32": target_triple = "i686-linux-android" env.extra_suffix = ".x86" + env.extra_suffix - elif env["android_arch"] == "x86_64": + elif env["arch"] == "x86_64": target_triple = "x86_64-linux-android" env.extra_suffix = ".x86_64" + env.extra_suffix @@ -176,14 +178,14 @@ def configure(env): if get_min_sdk_version(env["ndk_platform"]) >= 24: env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)]) - if env["android_arch"] == "x86": + if env["arch"] == "x86_32": # The NDK adds this if targeting API < 24, so we can drop it when Godot targets it at least env.Append(CCFLAGS=["-mstackrealign"]) - elif env["android_arch"] == "armv7": + elif env["arch"] == "arm32": env.Append(CCFLAGS="-march=armv7-a -mfloat-abi=softfp".split()) env.Append(CPPDEFINES=["__ARM_ARCH_7__", "__ARM_ARCH_7A__"]) env.Append(CPPDEFINES=["__ARM_NEON__"]) - elif env["android_arch"] == "arm64v8": + elif env["arch"] == "arm64": env.Append(CCFLAGS=["-mfix-cortex-a53-835769"]) env.Append(CPPDEFINES=["__ARM_ARCH_8A__"]) diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index da30bd3a95..81c7130c03 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -28,7 +28,7 @@ allprojects { } ext { - supportedAbis = ["armv7", "arm64v8", "x86", "x86_64"] + supportedAbis = ["arm32", "arm64", "x86_32", "x86_64"] supportedTargetsMap = [release: "release", dev: "debug", debug: "release_debug"] supportedFlavors = ["editor", "template"] @@ -37,7 +37,7 @@ ext { // If building manually on the command line, it's recommended to use the // `./gradlew generateGodotTemplates` build command instead after running the `scons` command(s). // The {selectedAbis} values must be from the {supportedAbis} values. - selectedAbis = ["arm64v8"] + selectedAbis = ["arm64"] } def rootDir = "../../.." diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle index 6b82326a27..318ae1143f 100644 --- a/platform/android/java/lib/build.gradle +++ b/platform/android/java/lib/build.gradle @@ -159,7 +159,7 @@ android { def taskName = getSconsTaskName(flavorName, buildType, selectedAbi) tasks.create(name: taskName, type: Exec) { executable sconsExecutableFile.absolutePath - args "--directory=${pathToRootDir}", "platform=android", "tools=${toolsFlag}", "target=${sconsTarget}", "android_arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors() + args "--directory=${pathToRootDir}", "platform=android", "tools=${toolsFlag}", "target=${sconsTarget}", "arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors() } // Schedule the tasks so the generated libs are present before the aar file is packaged. diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 0f551e7f4f..f94614c741 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -370,15 +370,15 @@ bool OS_Android::_check_internal_feature_support(const String &p_feature) { return true; } #if defined(__aarch64__) - if (p_feature == "arm64-v8a") { + if (p_feature == "arm64-v8a" || p_feature == "arm64") { return true; } #elif defined(__ARM_ARCH_7A__) - if (p_feature == "armeabi-v7a" || p_feature == "armeabi") { + if (p_feature == "armeabi-v7a" || p_feature == "armeabi" || p_feature == "arm32") { return true; } #elif defined(__arm__) - if (p_feature == "armeabi") { + if (p_feature == "armeabi" || p_feature == "arm") { return true; } #endif diff --git a/platform/ios/README.md b/platform/ios/README.md new file mode 100644 index 0000000000..82c275ad31 --- /dev/null +++ b/platform/ios/README.md @@ -0,0 +1,14 @@ +# iOS platform port + +This folder contains the C++, Objective-C and Objective-C++ code for the iOS +platform port. + +See also [`misc/dist/ios_xcode`](/misc/dist/ios_xcode) folder for the Xcode +project template used for packaging the iOS export templates. + +## Documentation + +- [Compiling for iOS](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_ios.html) + - Instructions on building this platform port from source. +- [Exporting for iOS](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_ios.html) + - Instructions on using the compiled export templates to export a project. diff --git a/platform/ios/detect.py b/platform/ios/detect.py index 67c90b10a0..1a8d24d12d 100644 --- a/platform/ios/detect.py +++ b/platform/ios/detect.py @@ -36,12 +36,22 @@ def get_opts(): def get_flags(): return [ + ("arch", "arm64"), # Default for convenience. ("tools", False), ("use_volk", False), ] def configure(env): + # Validate arch. + supported_arches = ["x86_64", "arm64"] + if env["arch"] not in supported_arches: + print( + 'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.' + % (env["arch"], ", ".join(supported_arches)) + ) + sys.exit() + ## Build type if env["target"].startswith("release"): @@ -64,11 +74,6 @@ def configure(env): env.Append(CCFLAGS=["-flto"]) env.Append(LINKFLAGS=["-flto"]) - ## Architecture - env["bits"] = "64" - if env["arch"] != "x86_64": - env["arch"] = "arm64" - ## Compiler configuration # Save this in environment for use by other modules diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index 425a977569..f49cf7a88d 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -140,27 +140,27 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) 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 + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPhone/iPod Touch with Retina display + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPhone with Retina HD display - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad with Retina display - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad Pro + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad with Retina display + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad Pro - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png"), "")); // App Store + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // App Store - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight on devices with Retina display + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Spotlight + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Spotlight on devices with Retina display r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::COLOR, "storyboard/custom_bg_color"), Color())); for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); } } @@ -387,13 +387,17 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ String locale_files; Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); if (translations.size() > 0) { - int index = 0; + HashSet<String> languages; for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = " + lang + "; path = " + lang + ".lproj/InfoPlist.strings; sourceTree = \"<group>\"; };"; + if (tr.is_valid() && tr->get_locale() != "en") { + languages.insert(tr->get_locale()); } + } + + int index = 0; + for (const String &lang : languages) { + locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = " + lang + "; path = " + lang + ".lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n"; index++; } } @@ -402,13 +406,17 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ String locale_files; Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); if (translations.size() > 0) { - int index = 0; + HashSet<String> languages; for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,"; + if (tr.is_valid() && tr->get_locale() != "en") { + languages.insert(tr->get_locale()); } + } + + int index = 0; + for (const String &lang : languages) { + locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,\n"; index++; } } @@ -531,26 +539,27 @@ struct IconInfo { const char *actual_size_side; const char *scale; const char *unscaled_size; + const bool force_opaque; }; static const IconInfo icon_infos[] = { // Home screen on iPhone - { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60" }, - { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40" }, - { "icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60" }, + { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60", false }, + { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40", false }, + { "icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60", false }, // Home screen on iPad - { "icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76" }, - { "icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76" }, - { "icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5" }, + { "icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76", false }, + { "icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76", false }, + { "icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5", false }, // App Store - { "icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024" }, + { "icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024", true }, // Spotlight - { "icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40" }, - { "icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40" }, - { "icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40" } + { "icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40", false }, + { "icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40", false }, + { "icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40", false } }; Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) { @@ -570,14 +579,17 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr Ref<Image> img = memnew(Image); Error err = ImageLoader::load_image(icon_path, img); if (err != OK) { - ERR_PRINT("Invalid icon (" + String(info.preset_key) + "): '" + icon_path + "'."); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path)); + return ERR_UNCONFIGURED; + } + if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key)); return ERR_UNCONFIGURED; } img->resize(side_size, side_size); err = img->save_png(p_iconset_dir + info.export_name); if (err) { - String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'."); - ERR_PRINT(err_str.utf8().get_data()); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Failed to export icon (%s): '%s'.", info.preset_key, icon_path)); return err; } } else { @@ -585,11 +597,15 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr Ref<Image> img = memnew(Image); Error err = ImageLoader::load_image(icon_path, img); if (err != OK) { - ERR_PRINT("Invalid icon (" + String(info.preset_key) + "): '" + icon_path + "'."); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path)); + return ERR_UNCONFIGURED; + } + if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key)); return ERR_UNCONFIGURED; } if (img->get_width() != side_size || img->get_height() != side_size) { - WARN_PRINT("Icon (" + String(info.preset_key) + "): '" + icon_path + "' has incorrect size (" + String::num_int64(img->get_width()) + "x" + String::num_int64(img->get_height()) + ") and was automatically resized to " + String::num_int64(side_size) + "x" + String::num_int64(side_size) + "."); + add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s): '%s' has incorrect size %s and was automatically resized to %s.", info.preset_key, icon_path, img->get_size(), Vector2i(side_size, side_size))); img->resize(side_size, side_size); err = img->save_png(p_iconset_dir + info.export_name); } else { @@ -597,8 +613,7 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr } if (err) { - String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'."); - ERR_PRINT(err_str.utf8().get_data()); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Failed to export icon (%s): '%s'.", info.preset_key, icon_path)); return err; } } @@ -1651,27 +1666,31 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";"); } + HashSet<String> languages; for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - String fname = dest_dir + binary_name + "/" + lang + ".lproj"; - tmp_app_path->make_dir_recursive(fname); - Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); - 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() + "\";"); - } + if (tr.is_valid() && tr->get_locale() != "en") { + languages.insert(tr->get_locale()); + } + } + + for (const String &lang : languages) { + String fname = dest_dir + binary_name + "/" + lang + ".lproj"; + tmp_app_path->make_dir_recursive(fname); + Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + 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() + "\";"); } } } diff --git a/platform/javascript/README.md b/platform/javascript/README.md index f181bea9e0..812ab6778b 100644 --- a/platform/javascript/README.md +++ b/platform/javascript/README.md @@ -5,8 +5,15 @@ compiled using [Emscripten](https://emscripten.org/). It also contains a ESLint linting setup (see [`package.json`](package.json)). -See also [`misc/dist/html`](/misc/dist/html) folder for files used by this platform -such as the HTML5 shell. +See also [`misc/dist/html`](/misc/dist/html) folder for additional files used by +this platform such as the HTML5 shell. + +## Documentation + +- [Compiling for the Web](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_web.html) + - Instructions on building this platform port from source. +- [Exporting for the Web](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_web.html) + - Instructions on using the compiled export templates to export a project. ## Artwork license diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index a769260f01..048c9c2eb4 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -46,6 +46,7 @@ def get_opts(): def get_flags(): return [ + ("arch", "wasm32"), ("tools", False), ("builtin_pcre2_with_jit", False), ("vulkan", False), @@ -53,6 +54,15 @@ def get_flags(): def configure(env): + # Validate arch. + supported_arches = ["wasm32"] + if env["arch"] not in supported_arches: + print( + 'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.' + % (env["arch"], ", ".join(supported_arches)) + ) + sys.exit() + try: env["initial_memory"] = int(env["initial_memory"]) except Exception: diff --git a/platform/linuxbsd/README.md b/platform/linuxbsd/README.md index 0d3fb37be5..efa8682062 100644 --- a/platform/linuxbsd/README.md +++ b/platform/linuxbsd/README.md @@ -2,10 +2,20 @@ This folder contains the C++ code for the Linux/*BSD platform port. +See also [`misc/dist/linux`](/misc/dist/linux) folder for additional files +used by this platform. + +## Documentation + +- [Compiling for Linux/*BSD](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_linuxbsd.html) + - Instructions on building this platform port from source. +- [Exporting for Linux/*BSD](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_linux.html) + - Instructions on using the compiled export templates to export a project. + ## Artwork license [`logo.png`](logo.png) is derived from the [Linux logo](https://isc.tamu.edu/~lewing/linux/): > Permission to use and/or modify this image is granted provided you acknowledge me - <lewing@isc.tamu.edu> and [The GIMP](https://isc.tamu.edu/~lewing/gimp/) - if someone asks. +> <lewing@isc.tamu.edu> and [The GIMP](https://isc.tamu.edu/~lewing/gimp/) +> if someone asks. diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 00e2b9e6eb..dd829bdb9b 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -2,6 +2,7 @@ import os import platform import sys from methods import get_compiler_version, using_gcc +from platform_methods import detect_arch def is_active(): @@ -52,10 +53,21 @@ def get_opts(): def get_flags(): - return [] + return [ + ("arch", detect_arch()), + ] def configure(env): + # Validate arch. + supported_arches = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64"] + if env["arch"] not in supported_arches: + print( + 'Unsupported CPU architecture "%s" for Linux / *BSD. Supported architectures are: %s.' + % (env["arch"], ", ".join(supported_arches)) + ) + sys.exit() + ## Build type if env["target"] == "release": @@ -80,23 +92,7 @@ def configure(env): env.Prepend(CCFLAGS=["-g3"]) env.Append(LINKFLAGS=["-rdynamic"]) - ## Architecture - - is64 = sys.maxsize > 2**32 - if env["bits"] == "default": - env["bits"] = "64" if is64 else "32" - - machines = { - "riscv64": "rv64", - "ppc64le": "ppc64", - "ppc64": "ppc64", - "ppcle": "ppc", - "ppc": "ppc", - } - - if env["arch"] == "" and platform.machine() in machines: - env["arch"] = machines[platform.machine()] - + # CPU architecture flags. if env["arch"] == "rv64": # G = General-purpose extensions, C = Compression extension (very common). env.Append(CCFLAGS=["-march=rv64gc"]) @@ -262,8 +258,7 @@ def configure(env): env["builtin_libvorbis"] = False # Needed to link against system libtheora env.ParseConfig("pkg-config theora theoradec --cflags --libs") else: - list_of_x86 = ["x86_64", "x86", "i386", "i586"] - if any(platform.machine() in s for s in list_of_x86): + if env["arch"] in ["x86_64", "x86_32"]: env["x86_libtheora_opt_gcc"] = True if not env["builtin_libvorbis"]: @@ -392,7 +387,9 @@ def configure(env): import subprocess import re - linker_version_str = subprocess.check_output([env.subst(env["LINK"]), "-Wl,--version"]).decode("utf-8") + linker_version_str = subprocess.check_output( + [env.subst(env["LINK"]), "-Wl,--version"] + env.subst(env["LINKFLAGS"]) + ).decode("utf-8") gnu_ld_version = re.search("^GNU ld [^$]*(\d+\.\d+)$", linker_version_str, re.MULTILINE) if not gnu_ld_version: print( @@ -405,11 +402,12 @@ def configure(env): env.Append(LINKFLAGS=["-T", "platform/linuxbsd/pck_embed.legacy.ld"]) ## Cross-compilation - - if is64 and env["bits"] == "32": + # TODO: Support cross-compilation on architectures other than x86. + host_is_64_bit = sys.maxsize > 2**32 + if host_is_64_bit and env["arch"] == "x86_32": env.Append(CCFLAGS=["-m32"]) env.Append(LINKFLAGS=["-m32", "-L/usr/lib/i386-linux-gnu"]) - elif not is64 and env["bits"] == "64": + elif not host_is_64_bit and env["arch"] == "x86_64": env.Append(CCFLAGS=["-m64"]) env.Append(LINKFLAGS=["-m64", "-L/usr/lib/i686-linux-gnu"]) diff --git a/platform/macos/README.md b/platform/macos/README.md new file mode 100644 index 0000000000..feead80736 --- /dev/null +++ b/platform/macos/README.md @@ -0,0 +1,19 @@ +# macOS platform port + +This folder contains the C++, Objective-C and Objective-C++ code for the macOS +platform port. + +See also [`misc/dist/macos`](/misc/dist/macos) folder for additional files used +by this platform. [`misc/dist/macos_tools.app`](/misc/dist/macos_tools.app) is +an `.app` bundle template used for packaging the macOS editor, while +[`misc/dist/macos_template.app`](/misc/dist/macos_template.app) is used for +packaging macOS export templates. + +## Documentation + +- [Compiling for macOS](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_macos.html) + - Instructions on building this platform port from source. +- [Exporting for macOS](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_macos.html) + - Instructions on using the compiled export templates to export a project. +- [Running Godot apps on macOS](https://docs.godotengine.org/en/latest/tutorials/export/running_on_macos.html) + - Instructions on running Godot projects on macOS. diff --git a/platform/macos/detect.py b/platform/macos/detect.py index 20e7afa772..e5bcb46b02 100644 --- a/platform/macos/detect.py +++ b/platform/macos/detect.py @@ -1,6 +1,7 @@ import os import sys from methods import detect_darwin_sdk_path +from platform_methods import detect_arch def is_active(): @@ -37,6 +38,7 @@ def get_opts(): def get_flags(): return [ + ("arch", detect_arch()), ("use_volk", False), ] @@ -71,6 +73,15 @@ def get_mvk_sdk_path(): def configure(env): + # Validate arch. + supported_arches = ["x86_64", "arm64"] + if env["arch"] not in supported_arches: + print( + 'Unsupported CPU architecture "%s" for macOS. Supported architectures are: %s.' + % (env["arch"], ", ".join(supported_arches)) + ) + sys.exit() + ## Build type if env["target"] == "release": @@ -96,25 +107,20 @@ def configure(env): env.Prepend(CCFLAGS=["-g3"]) env.Prepend(LINKFLAGS=["-Xlinker", "-no_deduplicate"]) - ## Architecture - - # macOS no longer runs on 32-bit since 10.7 which is unsupported since 2014 - # As such, we only support 64-bit - env["bits"] = "64" - ## Compiler configuration # Save this in environment for use by other modules if "OSXCROSS_ROOT" in os.environ: env["osxcross"] = True + # CPU architecture. if env["arch"] == "arm64": - print("Building for macOS 11.0+, platform arm64.") + print("Building for macOS 11.0+.") env.Append(ASFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"]) env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"]) env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"]) - else: - print("Building for macOS 10.12+, platform x86_64.") + elif env["arch"] == "x86_64": + print("Building for macOS 10.12+.") env.Append(ASFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"]) env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"]) env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"]) @@ -185,9 +191,8 @@ def configure(env): ## Dependencies - if env["builtin_libtheora"]: - if env["arch"] != "arm64": - env["x86_libtheora_opt_gcc"] = True + if env["builtin_libtheora"] and env["arch"] == "x86_64": + env["x86_libtheora_opt_gcc"] = True ## Flags diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index e305ff3593..a08667a259 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -377,6 +377,11 @@ public: virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override; virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override; + virtual bool window_maximize_on_title_dbl_click() const override; + virtual bool window_minimize_on_title_dbl_click() const override; + + virtual Vector2i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual Point2i ime_get_selection() const override; virtual String ime_get_text() const override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index fa6bcda902..b06ae9f27c 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -703,6 +703,7 @@ bool DisplayServerMacOS::has_feature(Feature p_feature) const { //case FEATURE_KEEP_SCREEN_ON: case FEATURE_SWAP_BUFFERS: case FEATURE_TEXT_TO_SPEECH: + case FEATURE_EXTEND_TO_TITLE: return true; default: { } @@ -2538,6 +2539,45 @@ bool DisplayServerMacOS::window_is_maximize_allowed(WindowID p_window) const { return true; } +bool DisplayServerMacOS::window_maximize_on_title_dbl_click() const { + id value = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleActionOnDoubleClick"]; + if ([value isKindOfClass:[NSString class]]) { + return [value isEqualToString:@"Maximize"]; + } + return false; +} + +bool DisplayServerMacOS::window_minimize_on_title_dbl_click() const { + id value = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleActionOnDoubleClick"]; + if ([value isKindOfClass:[NSString class]]) { + return [value isEqualToString:@"Minimize"]; + } + return false; +} + +Vector2i DisplayServerMacOS::window_get_safe_title_margins(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Vector2i()); + const WindowData &wd = windows[p_window]; + + float max_x = 0.f; + NSButton *cb = [wd.window_object standardWindowButton:NSWindowCloseButton]; + if (cb) { + max_x = MAX(max_x, [cb frame].origin.x + [cb frame].size.width); + } + NSButton *mb = [wd.window_object standardWindowButton:NSWindowMiniaturizeButton]; + if (mb) { + max_x = MAX(max_x, [mb frame].origin.x + [mb frame].size.width); + } + NSButton *zb = [wd.window_object standardWindowButton:NSWindowZoomButton]; + if (zb) { + max_x = MAX(max_x, [zb frame].origin.x + [zb frame].size.width); + } + + return Vector2i(max_x * screen_get_max_scale(), 0); +} + void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { _THREAD_SAFE_METHOD_ @@ -2556,6 +2596,19 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win [wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskResizable]; } } break; + case WINDOW_FLAG_EXTEND_TO_TITLE: { + NSRect rect = [wd.window_object frame]; + if (p_enabled) { + [wd.window_object setTitlebarAppearsTransparent:YES]; + [wd.window_object setTitleVisibility:NSWindowTitleHidden]; + [wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskFullSizeContentView]; + } else { + [wd.window_object setTitlebarAppearsTransparent:NO]; + [wd.window_object setTitleVisibility:NSWindowTitleVisible]; + [wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskFullSizeContentView]; + } + [wd.window_object setFrame:rect display:YES]; + } break; case WINDOW_FLAG_BORDERLESS: { // OrderOut prevents a lose focus bug with the window. if ([wd.window_object isVisible]) { @@ -2623,6 +2676,9 @@ bool DisplayServerMacOS::window_get_flag(WindowFlags p_flag, WindowID p_window) case WINDOW_FLAG_RESIZE_DISABLED: { return wd.resize_disabled; } break; + case WINDOW_FLAG_EXTEND_TO_TITLE: { + return [wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView; + } break; case WINDOW_FLAG_BORDERLESS: { return [wd.window_object styleMask] == NSWindowStyleMaskBorderless; } break; diff --git a/platform/macos/export/export.cpp b/platform/macos/export/export.cpp index ff7457081f..f219616df4 100644 --- a/platform/macos/export/export.cpp +++ b/platform/macos/export/export.cpp @@ -33,8 +33,12 @@ #include "export_plugin.h" void register_macos_exporter() { - EDITOR_DEF("export/macos/force_builtin_codesign", false); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::BOOL, "export/macos/force_builtin_codesign", PROPERTY_HINT_NONE)); + EDITOR_DEF("export/macos/rcodesign", ""); +#ifdef WINDOWS_ENABLED + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/macos/rcodesign", PROPERTY_HINT_GLOBAL_FILE, "*.exe")); +#else + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/macos/rcodesign", PROPERTY_HINT_GLOBAL_FILE)); +#endif Ref<EditorExportPlatformMacOS> platform; platform.instantiate(); diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp index edce9c0380..4b453add5a 100644 --- a/platform/macos/export/export_plugin.cpp +++ b/platform/macos/export/export_plugin.cpp @@ -51,11 +51,51 @@ void EditorExportPlatformMacOS::get_preset_features(const Ref<EditorExportPreset r_features->push_back(p_preset->get("binary_format/architecture")); } -bool EditorExportPlatformMacOS::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { - // These options are not supported by built-in codesign, used on non macOS host. - if (!OS::get_singleton()->has_feature("macos")) { - if (p_option == "codesign/identity" || p_option == "codesign/timestamp" || p_option == "codesign/hardened_runtime" || p_option == "codesign/custom_options" || p_option.begins_with("notarization/")) { - return false; +bool EditorExportPlatformMacOS::get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const { + // Hide irrelevant code signing options. + if (p_preset) { + int codesign_tool = p_preset->get("codesign/codesign"); + switch (codesign_tool) { + case 1: { // built-in ad-hoc + if (p_option == "codesign/identity" || p_option == "codesign/certificate_file" || p_option == "codesign/certificate_password" || p_option == "codesign/custom_options") { + return false; + } + } break; + case 2: { // "rcodesign" + if (p_option == "codesign/identity") { + return false; + } + } break; +#ifdef MACOS_ENABLED + case 3: { // "codesign" + if (p_option == "codesign/certificate_file" || p_option == "codesign/certificate_password") { + return false; + } + } break; +#endif + default: { // disabled + if (p_option == "codesign/identity" || p_option == "codesign/certificate_file" || p_option == "codesign/certificate_password" || p_option == "codesign/custom_options" || p_option.begins_with("codesign/entitlements")) { + return false; + } + } break; + } + + // Hide irrelevant notarization options. + int notary_tool = p_preset->get("notarization/notarization"); + switch (notary_tool) { + case 1: { // "rcodesign" + if (p_option == "notarization/apple_id_name" || p_option == "notarization/apple_id_password" || p_option == "notarization/apple_team_id") { + return false; + } + } break; + case 2: { // "altool" + // All options are visible. + } break; + default: { // disabled + if (p_option == "notarization/apple_id_name" || p_option == "notarization/apple_id_password" || p_option == "notarization/apple_team_id" || p_option == "notarization/api_uuid" || p_option == "notarization/api_key") { + return false; + } + } break; } } @@ -83,40 +123,22 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options 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)); +#ifdef MACOS_ENABLED + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),PyOxidizer rcodesign,Xcode codesign"), 3, true)); +#else + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),PyOxidizer rcodesign"), 1, true)); +#endif + // "codesign" only options: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/replace_existing_signature"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/hardened_runtime"), true)); + // "rcodesign" only options: + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/certificate_file", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/certificate_password", PROPERTY_HINT_PASSWORD), "")); + // "codesign" and "rcodesign" only options: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/custom_file", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_unsigned_executable_memory"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_dyld_environment_variables"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/disable_library_validation"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/audio_input"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/camera"), false)); @@ -126,7 +148,6 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/photos_library"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/apple_events"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/debugging"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/enabled"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_server"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_client"), false)); @@ -137,13 +158,43 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_music", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::ARRAY, "codesign/entitlements/app_sandbox/helper_executables", PROPERTY_HINT_ARRAY_TYPE, itos(Variant::STRING) + "/" + itos(PROPERTY_HINT_GLOBAL_FILE) + ":"), Array())); - r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray())); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "notarization/enable"), false)); +#ifdef MACOS_ENABLED + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,PyOxidizer rcodesign,Xcode altool"), 0, true)); +#else + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,PyOxidizer rcodesign"), 0, true)); +#endif + // "altool" only options: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Apple ID email"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PLACEHOLDER_TEXT, "Enable two-factor authentication and provide app-specific password"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PASSWORD, "Enable two-factor authentication and provide app-specific password"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_team_id", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide team ID if your Apple ID belongs to multiple teams"), "")); + // "altool" and "rcodesign" only options: + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_uuid", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect issuer ID"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect API key ID"), "")); + + 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, "texture_format/s3tc"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); @@ -415,156 +466,284 @@ void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_pres */ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path) { + int notary_tool = p_preset->get("notarization/notarization"); + switch (notary_tool) { + case 1: { // "rcodesign" + print_verbose("using rcodesign notarization..."); + + String rcodesign = EditorSettings::get_singleton()->get("export/macos/rcodesign").operator String(); + if (rcodesign.is_empty()) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("rcodesign path is not set. Configure rcodesign path in the Editor Settings (Export > macOS > rcodesign).")); + return Error::FAILED; + } + + List<String> args; + + args.push_back("notary-submit"); + + if (p_preset->get("notarization/api_uuid") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect issuer ID name not specified.")); + return Error::FAILED; + } + if (p_preset->get("notarization/api_key") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect API key ID not specified.")); + return Error::FAILED; + } + + args.push_back("--api-issuer"); + args.push_back(p_preset->get("notarization/api_uuid")); + + args.push_back("--api-key"); + args.push_back(p_preset->get("notarization/api_key")); + + args.push_back(p_path); + + String str; + int exitcode = 0; + + Error err = OS::get_singleton()->execute(rcodesign, args, &str, &exitcode, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Could not start rcodesign executable.")); + return err; + } + + int rq_offset = str.find("created submission ID:"); + if (exitcode != 0 || rq_offset == -1) { + print_line("rcodesign (" + p_path + "):\n" + str); + add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed, see editor log for details.")); + return Error::FAILED; + } else { + print_verbose("rcodesign (" + p_path + "):\n" + str); + int next_nl = str.find("\n", rq_offset); + String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid)); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour.")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"rcodesign notary-log --api-issuer <api uuid> --api-key <api key> <request uuid>\""); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("Run the following command to staple the notarization ticket to the exported application (optional):")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"rcodesign staple <app path>\""); + } + } break; #ifdef MACOS_ENABLED - List<String> args; + case 2: { // "altool" + print_verbose("using altool notarization..."); - args.push_back("altool"); - args.push_back("--notarize-app"); + if (!FileAccess::exists("/usr/bin/xcrun") && !FileAccess::exists("/bin/xcrun")) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Xcode command line tools are not installed.")); + return Error::FAILED; + } - args.push_back("--primary-bundle-id"); - args.push_back(p_preset->get("application/bundle_identifier")); + List<String> args; - args.push_back("--username"); - args.push_back(p_preset->get("notarization/apple_id_name")); + args.push_back("altool"); + args.push_back("--notarize-app"); - args.push_back("--password"); - args.push_back(p_preset->get("notarization/apple_id_password")); + args.push_back("--primary-bundle-id"); + args.push_back(p_preset->get("application/bundle_identifier")); - args.push_back("--type"); - args.push_back("osx"); + if (p_preset->get("notarization/apple_id_name") == "" && p_preset->get("notarization/api_uuid") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Neither Apple ID name nor App Store Connect issuer ID name not specified.")); + return Error::FAILED; + } + if (p_preset->get("notarization/apple_id_name") != "" && p_preset->get("notarization/api_uuid") != "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Both Apple ID name and App Store Connect issuer ID name are specified, only one should be set at the same time.")); + return Error::FAILED; + } - if (p_preset->get("notarization/apple_team_id")) { - args.push_back("--asc-provider"); - args.push_back(p_preset->get("notarization/apple_team_id")); - } + if (p_preset->get("notarization/apple_id_name") != "") { + if (p_preset->get("notarization/apple_id_password") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Apple ID password not specified.")); + return Error::FAILED; + } + args.push_back("--username"); + args.push_back(p_preset->get("notarization/apple_id_name")); - args.push_back("--file"); - args.push_back(p_path); + args.push_back("--password"); + args.push_back(p_preset->get("notarization/apple_id_password")); + } else { + if (p_preset->get("notarization/api_key") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect API key ID not specified.")); + return Error::FAILED; + } + args.push_back("--apiIssuer"); + args.push_back(p_preset->get("notarization/api_uuid")); - String str; - Error err = OS::get_singleton()->execute("xcrun", args, &str, nullptr, true); - if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Could not start xcrun executable.")); - return err; - } + args.push_back("--apiKey"); + args.push_back(p_preset->get("notarization/api_key")); + } - print_verbose("altool (" + p_path + "):\n" + str); - int rq_offset = str.find("RequestUUID"); - if (rq_offset == -1) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed.")); - return FAILED; - } else { - int next_nl = str.find("\n", rq_offset); - String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid)); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour. When the process is completed, you'll receive an email.")); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:")); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun altool --notarization-history 0 -u <your email> -p <app-specific pwd>\""); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("Run the following command to staple the notarization ticket to the exported application (optional):")); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun stapler staple <app path>\""); - } + args.push_back("--type"); + args.push_back("osx"); -#endif + if (p_preset->get("notarization/apple_team_id")) { + args.push_back("--asc-provider"); + args.push_back(p_preset->get("notarization/apple_team_id")); + } + + args.push_back("--file"); + args.push_back(p_path); + String str; + int exitcode = 0; + Error err = OS::get_singleton()->execute("xcrun", args, &str, &exitcode, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Could not start xcrun executable.")); + return err; + } + + int rq_offset = str.find("RequestUUID"); + if (exitcode != 0 || rq_offset == -1) { + print_line("xcrun altool (" + p_path + "):\n" + str); + add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed, see editor log for details.")); + return Error::FAILED; + } else { + print_verbose("xcrun altool (" + p_path + "):\n" + str); + int next_nl = str.find("\n", rq_offset); + String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid)); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour. When the process is completed, you'll receive an email.")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun altool --notarization-history 0 -u <your email> -p <app-specific pwd>\""); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("Run the following command to staple the notarization ticket to the exported application (optional):")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun stapler staple <app path>\""); + } + } break; +#endif + default: { + }; + } return OK; } Error EditorExportPlatformMacOS::_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") == "-"); - - if ((!FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) || force_builtin_codesign) { - print_verbose("using built-in codesign..."); + int codesign_tool = p_preset->get("codesign/codesign"); + switch (codesign_tool) { + case 1: { // built-in ad-hoc + print_verbose("using built-in codesign..."); #ifdef MODULE_REGEX_ENABLED - -#ifdef MACOS_ENABLED - if (p_preset->get("codesign/timestamp") && p_warn) { - add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Timestamping is not compatible with ad-hoc signature, and was disabled!")); - } - if (p_preset->get("codesign/hardened_runtime") && p_warn) { - add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!")); - } -#endif - - String error_msg; - Error err = CodeSign::codesign(false, p_preset->get("codesign/replace_existing_signature"), p_path, p_ent_path, error_msg); - if (err != OK) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Built-in CodeSign failed with error \"%s\"."), error_msg)); - return FAILED; - } + String error_msg; + Error err = CodeSign::codesign(false, true, p_path, p_ent_path, error_msg); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Built-in CodeSign failed with error \"%s\"."), error_msg)); + return Error::FAILED; + } #else - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Built-in CodeSign require regex module.")); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Built-in CodeSign require regex module.")); #endif - return OK; - } else { - print_verbose("using external codesign..."); - List<String> args; - if (p_preset->get("codesign/timestamp")) { - if (ad_hoc) { - if (p_warn) { - add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Timestamping is not compatible with ad-hoc signature, and was disabled!")); - } - } else { - args.push_back("--timestamp"); + } break; + case 2: { // "rcodesign" + print_verbose("using rcodesign codesign..."); + + String rcodesign = EditorSettings::get_singleton()->get("export/macos/rcodesign").operator String(); + if (rcodesign.is_empty()) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Xrcodesign path is not set. Configure rcodesign path in the Editor Settings (Export > macOS > rcodesign).")); + return Error::FAILED; } - } - if (p_preset->get("codesign/hardened_runtime")) { - if (ad_hoc) { - if (p_warn) { - add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!")); - } + + List<String> args; + args.push_back("sign"); + + if (p_path.get_extension() != "dmg") { + args.push_back("--entitlements-xml-path"); + args.push_back(p_ent_path); + } + + String certificate_file = p_preset->get("codesign/certificate_file"); + String certificate_pass = p_preset->get("codesign/certificate_password"); + if (!certificate_file.is_empty() && !certificate_file.is_empty()) { + args.push_back("--p12-file"); + args.push_back(certificate_file); + args.push_back("--p12-password"); + args.push_back(certificate_pass); + } + + args.push_back("-v"); /* provide some more feedback */ + + args.push_back(p_path); + + String str; + int exitcode = 0; + + Error err = OS::get_singleton()->execute(rcodesign, args, &str, &exitcode, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start rcodesign executable.")); + return err; + } + + if (exitcode != 0) { + print_line("rcodesign (" + p_path + "):\n" + str); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Code signing failed, see editor log for details.")); + return Error::FAILED; } else { + print_verbose("rcodesign (" + p_path + "):\n" + str); + } + } break; +#ifdef MACOS_ENABLED + case 3: { // "codesign" + print_verbose("using xcode codesign..."); + + if (!FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Xcode command line tools are not installed.")); + return Error::FAILED; + } + + bool ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); + + List<String> args; + if (!ad_hoc) { + args.push_back("--timestamp"); args.push_back("--options"); args.push_back("runtime"); } - } - if (p_path.get_extension() != "dmg") { - args.push_back("--entitlements"); - args.push_back(p_ent_path); - } - - PackedStringArray user_args = p_preset->get("codesign/custom_options"); - for (int i = 0; i < user_args.size(); i++) { - String user_arg = user_args[i].strip_edges(); - if (!user_arg.is_empty()) { - args.push_back(user_arg); + if (p_path.get_extension() != "dmg") { + args.push_back("--entitlements"); + args.push_back(p_ent_path); } - } - args.push_back("-s"); - if (ad_hoc) { - args.push_back("-"); - } else { - args.push_back(p_preset->get("codesign/identity")); - } + PackedStringArray user_args = p_preset->get("codesign/custom_options"); + for (int i = 0; i < user_args.size(); i++) { + String user_arg = user_args[i].strip_edges(); + if (!user_arg.is_empty()) { + args.push_back(user_arg); + } + } - args.push_back("-v"); /* provide some more feedback */ + args.push_back("-s"); + if (ad_hoc) { + args.push_back("-"); + } else { + args.push_back(p_preset->get("codesign/identity")); + } - if (p_preset->get("codesign/replace_existing_signature")) { + args.push_back("-v"); /* provide some more feedback */ args.push_back("-f"); - } - args.push_back(p_path); + args.push_back(p_path); - String str; - Error err = OS::get_singleton()->execute("codesign", args, &str, nullptr, true); - if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start codesign executable, make sure Xcode command line tools are installed.")); - return err; - } + String str; + int exitcode = 0; - print_verbose("codesign (" + p_path + "):\n" + str); - if (str.find("no identity found") != -1) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found.")); - return FAILED; - } - if ((str.find("unrecognized blob type") != -1) || (str.find("cannot read entitlement data") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Invalid entitlements file.")); - return FAILED; - } - return OK; + Error err = OS::get_singleton()->execute("codesign", args, &str, nullptr, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start codesign executable, make sure Xcode command line tools are installed.")); + return err; + } + + if (exitcode != 0) { + print_line("codesign (" + p_path + "):\n" + str); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Code signing failed, see editor log for details.")); + return Error::FAILED; + } else { + print_verbose("codesign (" + p_path + "):\n" + str); + } + } break; +#endif + default: { + }; } + + return OK; } Error EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, @@ -816,7 +995,9 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p err = ERR_CANT_CREATE; } - DirAccess::remove_file_or_error(scr_path); + if (FileAccess::exists(scr_path)) { + DirAccess::remove_file_or_error(scr_path); + } if (DirAccess::exists(tmp_app_path_name)) { String old_dir = tmp_app_dir->get_current_dir(); if (tmp_app_dir->change_dir(tmp_app_path_name) == OK) { @@ -919,54 +1100,58 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p f->store_line("NSHumanReadableCopyright = \"" + p_preset->get("application/copyright").operator String() + "\";"); } + HashSet<String> languages; for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj"; - tmp_app_dir->make_dir_recursive(fname); - Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); - 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() + "\";"); - } + if (tr.is_valid() && tr->get_locale() != "en") { + languages.insert(tr->get_locale()); + } + } + + for (const String &lang : languages) { + String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj"; + tmp_app_dir->make_dir_recursive(fname); + Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + 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() + "\";"); } } } @@ -1144,7 +1329,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p 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"); + bool sign_enabled = (p_preset->get("codesign/codesign").operator int() > 0); String ent_path = p_preset->get("codesign/entitlements/custom_file"); String hlp_ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + "_helper.entitlements"); @@ -1310,14 +1495,25 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p } } - bool ad_hoc = true; - if (err == OK) { + bool ad_hoc = false; + int codesign_tool = p_preset->get("codesign/codesign"); + switch (codesign_tool) { + case 1: { // built-in ad-hoc + ad_hoc = true; + } break; + case 2: { // "rcodesign" + ad_hoc = p_preset->get("codesign/certificate_file").operator String().is_empty() || p_preset->get("codesign/certificate_password").operator String().is_empty(); + } break; #ifdef MACOS_ENABLED - String sign_identity = p_preset->get("codesign/identity"); -#else - String sign_identity = "-"; + case 3: { // "codesign" + ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); + } break; #endif - ad_hoc = (sign_identity == "" || sign_identity == "-"); + default: { + }; + } + + if (err == OK) { bool lib_validation = p_preset->get("codesign/entitlements/disable_library_validation"); if ((!dylibs_found.is_empty() || !shared_objects.is_empty()) && sign_enabled && ad_hoc && !lib_validation) { add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Ad-hoc signed applications require the 'Disable Library Validation' entitlement to load dynamic libraries.")); @@ -1400,8 +1596,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p } } -#ifdef MACOS_ENABLED - bool noto_enabled = p_preset->get("notarization/enable"); + bool noto_enabled = (p_preset->get("notarization/notarization").operator int() > 0); if (err == OK && noto_enabled) { if (export_format == "app") { add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("Notarization requires the app to be archived first, select the DMG or ZIP export format instead.")); @@ -1412,10 +1607,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p err = _notarize(p_preset, p_path); } } -#endif // Clean up temporary entitlements files. - DirAccess::remove_file_or_error(hlp_ent_path); + if (FileAccess::exists(hlp_ent_path)) { + DirAccess::remove_file_or_error(hlp_ent_path); + } // Clean up temporary .app dir and generated entitlements. if ((String)(p_preset->get("codesign/entitlements/custom_file")) == "") { @@ -1598,65 +1794,98 @@ bool EditorExportPlatformMacOS::has_valid_project_configuration(const Ref<Editor valid = false; } - bool sign_enabled = p_preset->get("codesign/enable"); - + bool ad_hoc = false; + int codesign_tool = p_preset->get("codesign/codesign"); + switch (codesign_tool) { + case 1: { // built-in ad-hoc + ad_hoc = true; + } break; + case 2: { // "rcodesign" + ad_hoc = p_preset->get("codesign/certificate_file").operator String().is_empty() || p_preset->get("codesign/certificate_password").operator String().is_empty(); + } break; #ifdef MACOS_ENABLED - bool noto_enabled = p_preset->get("notarization/enable"); - bool ad_hoc = ((p_preset->get("codesign/identity") == "") || (p_preset->get("codesign/identity") == "-")); - - if (!ad_hoc && (bool)EditorSettings::get_singleton()->get("export/macos/force_builtin_codesign")) { - err += TTR("Warning: Built-in \"codesign\" is selected in the Editor Settings. Code signing is limited to ad-hoc signature only.") + "\n"; - } - if (!ad_hoc && !FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) { - err += TTR("Warning: Xcode command line tools are not installed, using built-in \"codesign\". Code signing is limited to ad-hoc signature only.") + "\n"; + case 3: { // "codesign" + ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); + } break; +#endif + default: { + }; } + int notary_tool = p_preset->get("notarization/notarization"); - if (noto_enabled) { + if (notary_tool > 0) { if (ad_hoc) { err += TTR("Notarization: Notarization with an ad-hoc signature is not supported.") + "\n"; valid = false; } - if (!sign_enabled) { + if (codesign_tool == 0) { err += TTR("Notarization: Code signing is required for notarization.") + "\n"; valid = false; } - if (!(bool)p_preset->get("codesign/hardened_runtime")) { - err += TTR("Notarization: Hardened runtime is required for notarization.") + "\n"; - valid = false; - } - if (!(bool)p_preset->get("codesign/timestamp")) { - err += TTR("Notarization: Timestamping is required for notarization.") + "\n"; - valid = false; - } - if (p_preset->get("notarization/apple_id_name") == "") { - err += TTR("Notarization: Apple ID name not specified.") + "\n"; - valid = false; - } - if (p_preset->get("notarization/apple_id_password") == "") { - err += TTR("Notarization: Apple ID password not specified.") + "\n"; - valid = false; + if (notary_tool == 2) { + if (!FileAccess::exists("/usr/bin/xcrun") && !FileAccess::exists("/bin/xcrun")) { + err += TTR("Notarization: Xcode command line tools are not installed.") + "\n"; + valid = false; + } + if (p_preset->get("notarization/apple_id_name") == "" && p_preset->get("notarization/api_uuid") == "") { + err += TTR("Notarization: Neither Apple ID name nor App Store Connect issuer ID name not specified.") + "\n"; + valid = false; + } else if (p_preset->get("notarization/apple_id_name") != "" && p_preset->get("notarization/api_uuid") != "") { + err += TTR("Notarization: Both Apple ID name and App Store Connect issuer ID name are specified, only one should be set at the same time.") + "\n"; + valid = false; + } else { + if (p_preset->get("notarization/apple_id_name") != "") { + if (p_preset->get("notarization/apple_id_password") == "") { + err += TTR("Notarization: Apple ID password not specified.") + "\n"; + } + valid = false; + } + if (p_preset->get("notarization/api_uuid") != "") { + if (p_preset->get("notarization/api_key") == "") { + err += TTR("Notarization: App Store Connect API key ID not specified.") + "\n"; + valid = false; + } + } + } + } else if (notary_tool == 1) { + if (p_preset->get("notarization/api_uuid") == "") { + err += TTR("Notarization: App Store Connect issuer ID name not specified.") + "\n"; + valid = false; + } + if (p_preset->get("notarization/api_key") == "") { + err += TTR("Notarization: App Store Connect API key ID not specified.") + "\n"; + valid = false; + } + + String rcodesign = EditorSettings::get_singleton()->get("export/macos/rcodesign").operator String(); + if (rcodesign.is_empty()) { + err += TTR("Notarization: rcodesign path is not set. Configure rcodesign path in the Editor Settings (Export > macOS > rcodesign).") + "\n"; + valid = false; + } } } else { err += TTR("Warning: Notarization is disabled. The exported project will be blocked by Gatekeeper if it's downloaded from an unknown source.") + "\n"; - if (!sign_enabled) { + if (codesign_tool == 0) { err += TTR("Code signing is disabled. The exported project will not run on Macs with enabled Gatekeeper and Apple Silicon powered Macs.") + "\n"; - } else { - if ((bool)p_preset->get("codesign/hardened_runtime") && ad_hoc) { - err += TTR("Hardened Runtime is not compatible with ad-hoc signature, and will be disabled!") + "\n"; - } - if ((bool)p_preset->get("codesign/timestamp") && ad_hoc) { - err += TTR("Timestamping is not compatible with ad-hoc signature, and will be disabled!") + "\n"; - } } } -#else - err += TTR("Warning: Notarization is not supported from this OS. The exported project will be blocked by Gatekeeper if it's downloaded from an unknown source.") + "\n"; - if (!sign_enabled) { - err += TTR("Code signing is disabled. The exported project will not run on Macs with enabled Gatekeeper and Apple Silicon powered Macs.") + "\n"; - } -#endif - if (sign_enabled) { + if (codesign_tool > 0) { + if (ad_hoc) { + err += TTR("Code signing: Using ad-hoc signature. The exported project will be blocked by Gatekeeper") + "\n"; + } + if (codesign_tool == 3) { + if (!FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) { + err += TTR("Code signing: Xcode command line tools are not installed.") + "\n"; + valid = false; + } + } else if (codesign_tool == 2) { + String rcodesign = EditorSettings::get_singleton()->get("export/macos/rcodesign").operator String(); + if (rcodesign.is_empty()) { + err += TTR("Code signing: rcodesign path is not set. Configure rcodesign path in the Editor Settings (Export > macOS > rcodesign).") + "\n"; + valid = false; + } + } if ((bool)p_preset->get("codesign/entitlements/audio_input") && ((String)p_preset->get("privacy/microphone_usage_description")).is_empty()) { err += TTR("Privacy: Microphone access is enabled, but usage description is not specified.") + "\n"; valid = false; diff --git a/platform/macos/export/export_plugin.h b/platform/macos/export/export_plugin.h index 4603c61a28..87790129d3 100644 --- a/platform/macos/export/export_plugin.h +++ b/platform/macos/export/export_plugin.h @@ -101,7 +101,7 @@ class EditorExportPlatformMacOS : public EditorExportPlatform { protected: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; virtual void get_export_options(List<ExportOption> *r_options) override; - virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const override; + virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; public: virtual String get_name() const override { return "macOS"; } diff --git a/platform/uwp/README.md b/platform/uwp/README.md new file mode 100644 index 0000000000..575f90e3c7 --- /dev/null +++ b/platform/uwp/README.md @@ -0,0 +1,20 @@ +# UWP platform port + +> **Warning** +> +> The UWP platform port is not currently in a working state for the `master` +> branch, and may be dropped in the future. + +This folder contains the C++ code for the Universal Windows Platform (UWP) +platform port. **This is not to be confused with the "standard" Win32 port**, +which is available in [`platform/windows`](/platform/windows). + +See also [`misc/dist/uwp_template`](/misc/dist/uwp_template) folder for the UWP +project template used for packaging the UWP export templates. + +## Documentation + +- [Compiling for Universal Windows Platform](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_uwp.html) + - Instructions on building this platform port from source. +- [Exporting for Universal Windows Platform](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_uwp.html) + - Instructions on using the compiled export templates to export a project. diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index 9c91378b22..2c5746cb06 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -1,6 +1,7 @@ import methods import os import sys +from platform_methods import detect_arch def is_active(): @@ -31,6 +32,7 @@ def get_opts(): def get_flags(): return [ + ("arch", detect_arch()), ("tools", False), ("xaudio2", True), ("builtin_pcre2_with_jit", False), @@ -38,19 +40,17 @@ def get_flags(): def configure(env): - env.msvc = True - - if env["bits"] != "default": - print("Error: bits argument is disabled for MSVC") + # Validate arch. + supported_arches = ["x86_32", "x86_64", "arm32"] + if env["arch"] not in supported_arches: print( - """ - Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console - (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits - argument (example: scons p=uwp) and SCons will attempt to detect what MSVC compiler will be executed and inform you. - """ + 'Unsupported CPU architecture "%s" for UWP. Supported architectures are: %s.' + % (env["arch"], ", ".join(supported_arches)) ) sys.exit() + env.msvc = True + ## Build type if env["target"] == "release": @@ -101,11 +101,10 @@ def configure(env): arch = "" if str(os.getenv("Platform")).lower() == "arm": - - print("Compiled program architecture will be an ARM executable. (forcing bits=32).") + print("Compiled program architecture will be an ARM executable (forcing arch=arm32).") arch = "arm" - env["bits"] = "32" + env["arch"] = "arm32" env.Append(LINKFLAGS=["/MACHINE:ARM"]) env.Append(LIBPATH=[vc_base_path + "lib/store/arm"]) @@ -117,20 +116,20 @@ def configure(env): compiler_version_str = methods.detect_visual_c_compiler_version(env["ENV"]) if compiler_version_str == "amd64" or compiler_version_str == "x86_amd64": - env["bits"] = "64" - print("Compiled program architecture will be a x64 executable (forcing bits=64).") + env["arch"] = "x86_64" + print("Compiled program architecture will be a x64 executable (forcing arch=x86_64).") elif compiler_version_str == "x86" or compiler_version_str == "amd64_x86": - env["bits"] = "32" - print("Compiled program architecture will be a x86 executable. (forcing bits=32).") + env["arch"] = "x86_32" + print("Compiled program architecture will be a x86 executable (forcing arch=x86_32).") else: print( - "Failed to detect MSVC compiler architecture version... Defaulting to 32-bit executable settings" - " (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture" + "Failed to detect MSVC compiler architecture version... Defaulting to x86 32-bit executable settings" + " (forcing arch=x86_32). Compilation attempt will continue, but SCons can not detect for what architecture" " this build is compiled for. You should check your settings/compilation setup." ) - env["bits"] = "32" + env["arch"] = "x86_32" - if env["bits"] == "32": + if env["arch"] == "x86_32": arch = "x86" angle_build_cmd += "Win32" diff --git a/platform/windows/README.md b/platform/windows/README.md new file mode 100644 index 0000000000..17ce6f216b --- /dev/null +++ b/platform/windows/README.md @@ -0,0 +1,15 @@ +# Windows platform port + +This folder contains the C++ and JavaScript code for the Windows platform port. + +See also [`misc/dist/windows`](/misc/dist/windows) folder for additional files +used by this platform. + +## Documentation + +- [Compiling for Windows](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_windows.html) + - Instructions on building this platform port from source. +- [Exporting for Windows](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_windows.html) + - Instructions on using the compiled export templates to export a project. +- [Changing application icon for Windows](https://docs.godotengine.org/en/stable/tutorials/export/changing_application_icon_for_windows.html) + - Instructions on using a custom icon for the exported project executable. diff --git a/platform/windows/detect.py b/platform/windows/detect.py index dd2df1f004..6dd6892757 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -1,5 +1,6 @@ import methods import os +from platform_methods import detect_arch # To match other platforms STACK_SIZE = 8388608 @@ -46,6 +47,7 @@ def can_build(): def get_opts(): from SCons.Variables import BoolVariable, EnumVariable + # TODO: These shouldn't be hard-coded for x86. mingw32 = "" mingw64 = "" if os.name == "posix": @@ -77,11 +79,14 @@ def get_opts(): def get_flags(): - return [] + return [ + ("arch", detect_arch()), + ] def build_res_file(target, source, env): - if env["bits"] == "32": + # TODO: This shouldn't be hard-coded for x86. + if env["arch"] == "x86_32": cmdbase = env["mingw_prefix_32"] else: cmdbase = env["mingw_prefix_64"] @@ -100,21 +105,27 @@ def build_res_file(target, source, env): def setup_msvc_manual(env): + # FIXME: This is super hacky, and probably obsolete. + # Won't work with detect_arch() used for `arch` by default. + """Set up env to use MSVC manually, using VCINSTALLDIR""" - if env["bits"] != "default": + if env["arch"] != "auto": print( """ - Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console - (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits - argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you. + Arch argument is not supported for MSVC manual configuration (VCINSTALLDIR configured). + Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings) that is being used to run SCons. + As a consequence, the arch argument is disabled. Run scons again without arch argument (example: scons p=windows) + and SCons will attempt to detect what MSVC compiler will be executed and inform you. """ ) - raise SCons.Errors.UserError("Bits argument should not be used when using VCINSTALLDIR") + raise SCons.Errors.UserError("Arch argument should not be used when using VCINSTALLDIR") - # Force bits arg + # Force ARCH arg # (Actually msys2 mingw can support 64-bit, we could detect that) - env["bits"] = "32" - env["x86_libtheora_opt_vc"] = True + # TODO: This is wrong, but not sure what to do about it. + # We want to determine the arch and bitness in the SConstruct only. + # We can check if it's correct in here, but if it's not, it should + # just fail with an error message instead of trying to force it. # find compiler manually compiler_version_str = methods.detect_visual_c_compiler_version(env["ENV"]) @@ -122,17 +133,19 @@ def setup_msvc_manual(env): # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writing)... vc compiler for 64bit can not compile _asm if compiler_version_str == "amd64" or compiler_version_str == "x86_amd64": - env["bits"] = "64" + env["arch"] = "x86_64" env["x86_libtheora_opt_vc"] = False - print("Compiled program architecture will be a 64 bit executable (forcing bits=64).") + print("Compiled program architecture will be a 64 bit executable (forcing arch=x86_64).") elif compiler_version_str == "x86" or compiler_version_str == "amd64_x86": - print("Compiled program architecture will be a 32 bit executable. (forcing bits=32).") + env["arch"] = "x86_32" + env["x86_libtheora_opt_vc"] = True + print("Compiled program architecture will be a 32 bit executable (forcing arch=x86_32).") else: print( - "Failed to manually detect MSVC compiler architecture version... Defaulting to 32bit executable settings" - " (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this" - " build is compiled for. You should check your settings/compilation setup, or avoid setting VCINSTALLDIR." + "Failed to manually detect MSVC compiler architecture version.\n" + "You should check your settings/compilation setup, or avoid setting VCINSTALLDIR." ) + sys.exit() def setup_msvc_auto(env): @@ -141,6 +154,18 @@ def setup_msvc_auto(env): # If MSVC_VERSION is set by SCons, we know MSVC is installed. # But we may want a different version or target arch. + # Valid architectures for MSVC's TARGET_ARCH: + # ['amd64', 'emt64', 'i386', 'i486', 'i586', 'i686', 'ia64', 'itanium', 'x86', 'x86_64', 'arm', 'arm64', 'aarch64'] + # Our x86_64 and arm64 are the same, and we need to map the 32-bit + # architectures to other names since MSVC isn't as explicit. + # The rest we don't need to worry about because they are + # aliases or aren't supported by Godot (itanium & ia64). + msvc_arch_aliases = {"x86_32": "x86", "arm32": "arm"} + if env["arch"] in msvc_arch_aliases.keys(): + env["TARGET_ARCH"] = msvc_arch_aliases[env["arch"]] + else: + env["TARGET_ARCH"] = env["arch"] + # The env may have already been set up with default MSVC tools, so # reset a few things so we can set it up with the tools we want. # (Ideally we'd decide on the tool config before configuring any @@ -149,21 +174,14 @@ def setup_msvc_auto(env): env["MSVC_SETUP_RUN"] = False # Need to set this to re-run the tool env["MSVS_VERSION"] = None env["MSVC_VERSION"] = None - env["TARGET_ARCH"] = None - if env["bits"] != "default": - env["TARGET_ARCH"] = {"32": "x86", "64": "x86_64"}[env["bits"]] + if "msvc_version" in env: env["MSVC_VERSION"] = env["msvc_version"] env.Tool("msvc") env.Tool("mssdk") # we want the MS SDK # Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015 - # Get actual target arch into bits (it may be "default" at this point): - if env["TARGET_ARCH"] in ("amd64", "x86_64"): - env["bits"] = "64" - else: - env["bits"] = "32" - print("Found MSVC version %s, arch %s, bits=%s" % (env["MSVC_VERSION"], env["TARGET_ARCH"], env["bits"])) - if env["TARGET_ARCH"] in ("amd64", "x86_64"): + print("Found MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["TARGET_ARCH"])) + if env["arch"] == "x86_32": env["x86_libtheora_opt_vc"] = False @@ -244,7 +262,7 @@ def configure_msvc(env, manual_msvc_config): ] ) env.AppendUnique(CPPDEFINES=["NOMINMAX"]) # disable bogus min/max WinDef.h macros - if env["bits"] == "64": + if env["arch"] == "x86_64": env.AppendUnique(CPPDEFINES=["_WIN64"]) ## Libs @@ -328,10 +346,10 @@ def configure_mingw(env): env.Append(CCFLAGS=["-msse2"]) if env["optimize"] == "speed": # optimize for speed (default) - if env["bits"] == "64": - env.Append(CCFLAGS=["-O3"]) - else: + if env["arch"] == "x86_32": env.Append(CCFLAGS=["-O2"]) + else: + env.Append(CCFLAGS=["-O3"]) else: # optimize for size env.Prepend(CCFLAGS=["-Os"]) @@ -365,15 +383,12 @@ def configure_mingw(env): if os.name != "nt": env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation - if env["bits"] == "default": - if os.name == "nt": - env["bits"] = "64" if "PROGRAMFILES(X86)" in os.environ else "32" - else: # default to 64-bit on Linux - env["bits"] = "64" - mingw_prefix = "" - if env["bits"] == "32": + # TODO: This doesn't seem to be working, or maybe I just have + # MinGW set up incorrectly. It always gives me x86_64 builds, + # even though arch == "x86_32" and the file name has x86_32 in it. + if env["arch"] == "x86_32": if env["use_static_cpp"]: env.Append(LINKFLAGS=["-static"]) env.Append(LINKFLAGS=["-static-libgcc"]) @@ -460,11 +475,18 @@ def configure_mingw(env): def configure(env): + # Validate arch. + supported_arches = ["x86_32", "x86_64", "arm32", "arm64"] + if env["arch"] not in supported_arches: + print( + 'Unsupported CPU architecture "%s" for Windows. Supported architectures are: %s.' + % (env["arch"], ", ".join(supported_arches)) + ) + sys.exit() + # At this point the env has been set up with basic tools/compilers. env.Prepend(CPPPATH=["#platform/windows"]) - print("Configuring for Windows: target=%s, bits=%s" % (env["target"], env["bits"])) - if os.name == "nt": env["ENV"] = os.environ # this makes build less repeatable, but simplifies some things env["ENV"]["TMP"] = os.environ["TMP"] diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 9d3ec31f73..cb0bd44cfb 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -113,7 +113,7 @@ List<String> EditorExportPlatformWindows::get_binary_extensions(const Ref<Editor return list; } -bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { +bool EditorExportPlatformWindows::get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const { // This option is not supported by "osslsigncode", used on non-Windows host. if (!OS::get_singleton()->has_feature("windows") && p_option == "codesign/identity_type") { return false; @@ -128,7 +128,7 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password", PROPERTY_HINT_PASSWORD), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1)); @@ -231,7 +231,7 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset String str; Error err = OS::get_singleton()->execute(rcedit_path, args, &str, nullptr, true); if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable. Configure rcedit path in the Editor Settings (Export > Windows > Rcedit), or disable \"Application > Modify Resources\" in the export preset.")); + add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable. Configure rcedit path in the Editor Settings (Export > Windows > rcedit), or disable \"Application > Modify Resources\" in the export preset.")); return err; } print_line("rcedit (" + p_path + "): " + str); @@ -379,7 +379,11 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p String str; Error err = OS::get_singleton()->execute(signtool_path, args, &str, nullptr, true); if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable. Configure signtool path in the Editor Settings (Export > Windows > Signtool), or disable \"Codesign\" in the export preset.")); +#ifndef WINDOWS_ENABLED + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable. Configure signtool path in the Editor Settings (Export > Windows > signtool), or disable \"Codesign\" in the export preset.")); +#else + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start osslsigncode executable. Configure signtool path in the Editor Settings (Export > Windows > osslsigncode), or disable \"Codesign\" in the export preset.")); +#endif return err; } @@ -418,7 +422,7 @@ bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref<Edito String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); if (p_preset->get("application/modify_resources") && rcedit_path.is_empty()) { - err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > Rcedit) to change the icon or app information data.") + "\n"; + err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > rcedit) to change the icon or app information data.") + "\n"; } if (!err.is_empty()) { diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 3ea8ff3dc9..f85331c898 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -48,9 +48,9 @@ public: virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override; virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override; virtual void get_export_options(List<ExportOption> *r_options) override; - virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const override; virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override; + virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; virtual String get_template_file_name(const String &p_target, const String &p_arch) const override; virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override; }; diff --git a/platform/windows/platform_windows_builders.py b/platform/windows/platform_windows_builders.py index 22e33b51b4..33ca2e8ffa 100644 --- a/platform/windows/platform_windows_builders.py +++ b/platform/windows/platform_windows_builders.py @@ -9,7 +9,7 @@ from platform_methods import subprocess_main def make_debug_mingw(target, source, env): mingw_prefix = "" - if env["bits"] == "32": + if env["arch"] == "x86_32": mingw_prefix = env["mingw_prefix_32"] else: mingw_prefix = env["mingw_prefix_64"] diff --git a/platform_methods.py b/platform_methods.py index be4957475d..1a2520794c 100644 --- a/platform_methods.py +++ b/platform_methods.py @@ -1,6 +1,7 @@ import os import sys import json +import platform import uuid import functools import subprocess @@ -71,9 +72,42 @@ def run_in_subprocess(builder_function): def subprocess_main(namespace): - with open(sys.argv[1]) as json_file: data = json.load(json_file) fn = namespace[data["fn"]] fn(*data["args"]) + + +# CPU architecture options. +architectures = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64", "wasm32"] +architecture_aliases = { + "x86": "x86_32", + "x64": "x86_64", + "amd64": "x86_64", + "armv7": "arm32", + "armv8": "arm64", + "arm64v8": "arm64", + "aarch64": "arm64", + "rv": "rv64", + "riscv": "rv64", + "riscv64": "rv64", + "ppcle": "ppc32", + "ppc": "ppc32", + "ppc64le": "ppc64", +} + + +def detect_arch(): + host_machine = platform.machine().lower() + if host_machine in architectures: + return host_machine + elif host_machine in architecture_aliases.keys(): + return architecture_aliases[host_machine] + elif "86" in host_machine: + # Catches x86, i386, i486, i586, i686, etc. + return "x86_32" + else: + print("Unsupported CPU architecture: " + host_machine) + print("Falling back to x86_64.") + return "x86_64" diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index 177f587f4f..4565462247 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -115,14 +115,17 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { names.sort_custom<StringName::AlphCompare>(); bool current_found = false; + bool is_first_element = true; - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - if (E->prev()) { + for (const StringName &E : names) { + if (!is_first_element) { p_property.hint_string += ","; + } else { + is_first_element = false; } - p_property.hint_string += String(E->get()); - if (animation == E->get()) { + p_property.hint_string += String(E); + if (animation == E) { current_found = true; } } diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index fa49552085..fc019b6cf9 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -185,7 +185,7 @@ void AudioStreamPlayer2D::_update_panning() { } float multiplier = Math::pow(1.0f - dist / max_distance, attenuation); - multiplier *= Math::db2linear(volume_db); //also apply player volume! + multiplier *= Math::db_to_linear(volume_db); //also apply player volume! float pan = relative_to_listener.x / screen_size.x; // Don't let the panning effect extend (too far) beyond the screen. diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 8df29851e5..04cd999982 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -239,7 +239,7 @@ TypedArray<String> CollisionPolygon2D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject2D>(get_parent())) { - warnings.push_back(RTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidDynamicBody2D, CharacterBody2D, etc. to give them a shape.")); + warnings.push_back(RTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape.")); } int polygon_count = polygon.size(); diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 9c0c26f6d9..cbecf28877 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -172,7 +172,7 @@ TypedArray<String> CollisionShape2D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject2D>(get_parent())) { - warnings.push_back(RTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidDynamicBody2D, CharacterBody2D, etc. to give them a shape.")); + warnings.push_back(RTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape.")); } if (!shape.is_valid()) { warnings.push_back(RTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!")); diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 40f74d3f50..1929475c8f 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -32,7 +32,7 @@ #include "core/core_string_names.h" #include "scene/2d/gpu_particles_2d.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" void CPUParticles2D::set_emitting(bool p_emitting) { if (emitting == p_emitting) { @@ -745,12 +745,12 @@ void CPUParticles2D::_particles_process(double p_delta) { p.start_color_rand = Color(1, 1, 1, 1); } - real_t angle1_rad = direction.angle() + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread); + real_t angle1_rad = direction.angle() + Math::deg_to_rad((Math::randf() * 2.0 - 1.0) * spread); Vector2 rot = Vector2(Math::cos(angle1_rad), Math::sin(angle1_rad)); p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf()); real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand); - p.rotation = Math::deg2rad(base_angle); + p.rotation = Math::deg_to_rad(base_angle); p.custom[0] = 0.0; // unused p.custom[1] = 0.0; // phase [0..1] @@ -890,7 +890,7 @@ void CPUParticles2D::_particles_process(double p_delta) { real_t orbit_amount = tex_orbit_velocity * Math::lerp(parameters_min[PARAM_ORBIT_VELOCITY], parameters_max[PARAM_ORBIT_VELOCITY], rand_from_seed(alt_seed)); if (orbit_amount != 0.0) { real_t ang = orbit_amount * local_delta * Math_TAU; - // Not sure why the ParticlesMaterial code uses a clockwise rotation matrix, + // Not sure why the ParticleProcessMaterial code uses a clockwise rotation matrix, // but we use -ang here to reproduce its behavior. Transform2D rot = Transform2D(-ang, Vector2()); p.transform[2] -= diff; @@ -912,7 +912,7 @@ void CPUParticles2D::_particles_process(double p_delta) { } real_t base_angle = (tex_angle)*Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand); base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(alt_seed)); - p.rotation = Math::deg2rad(base_angle); //angle + p.rotation = Math::deg_to_rad(base_angle); //angle p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + tv * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed)); } //apply color @@ -1184,7 +1184,7 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) { set_material(mat); } - Ref<ParticlesMaterial> material = particles->get_process_material(); + Ref<ParticleProcessMaterial> material = particles->get_process_material(); if (material.is_null()) { return; } @@ -1205,14 +1205,14 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) { set_color_initial_ramp(gti->get_gradient()); } - set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); + set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); set_emission_shape(EmissionShape(material->get_emission_shape())); set_emission_sphere_radius(material->get_emission_sphere_radius()); Vector2 rect_extents = Vector2(material->get_emission_box_extents().x, material->get_emission_box_extents().y); set_emission_rect_extents(rect_extents); - Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticlesMaterial::PARAM_SCALE); + Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticleProcessMaterial::PARAM_SCALE); if (scale3D.is_valid()) { split_scale = true; scale_curve_x = scale3D->get_curve_x(); @@ -1222,14 +1222,14 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) { set_gravity(gravity); set_lifetime_randomness(material->get_lifetime_randomness()); -#define CONVERT_PARAM(m_param) \ - set_param_min(m_param, material->get_param_min(ParticlesMaterial::m_param)); \ - { \ - Ref<CurveTexture> ctex = material->get_param_texture(ParticlesMaterial::m_param); \ - if (ctex.is_valid()) \ - set_param_curve(m_param, ctex->get_curve()); \ - } \ - set_param_max(m_param, material->get_param_max(ParticlesMaterial::m_param)); +#define CONVERT_PARAM(m_param) \ + set_param_min(m_param, material->get_param_min(ParticleProcessMaterial::m_param)); \ + { \ + Ref<CurveTexture> ctex = material->get_param_texture(ParticleProcessMaterial::m_param); \ + if (ctex.is_valid()) \ + set_param_curve(m_param, ctex->get_curve()); \ + } \ + set_param_max(m_param, material->get_param_max(ParticleProcessMaterial::m_param)); CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY); CONVERT_PARAM(PARAM_ANGULAR_VELOCITY); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index e4354a69e2..65ead7afbc 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -30,7 +30,7 @@ #include "gpu_particles_2d.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" #ifdef TOOLS_ENABLED #include "core/config/engine.h" @@ -123,10 +123,10 @@ void GPUParticles2D::_update_particle_emission_transform() { void GPUParticles2D::set_process_material(const Ref<Material> &p_material) { process_material = p_material; - Ref<ParticlesMaterial> pm = p_material; - if (pm.is_valid() && !pm->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_DISABLE_Z) && pm->get_gravity() == Vector3(0, -9.8, 0)) { + Ref<ParticleProcessMaterial> pm = p_material; + if (pm.is_valid() && !pm->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_DISABLE_Z) && pm->get_gravity() == Vector3(0, -9.8, 0)) { // Likely a new (3D) material, modify it to match 2D space - pm->set_particle_flag(ParticlesMaterial::PARTICLE_FLAG_DISABLE_Z, true); + pm->set_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_DISABLE_Z, true); pm->set_gravity(Vector3(0, 98, 0)); } RID material_rid; @@ -308,10 +308,10 @@ TypedArray<String> GPUParticles2D::get_configuration_warnings() const { CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(get_material().ptr()); if (get_material().is_null() || (mat && !mat->get_particles_animation())) { - const ParticlesMaterial *process = Object::cast_to<ParticlesMaterial>(process_material.ptr()); + const ParticleProcessMaterial *process = Object::cast_to<ParticleProcessMaterial>(process_material.ptr()); if (process && - (process->get_param_max(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param_max(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || - process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { + (process->get_param_max(ParticleProcessMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param_max(ParticleProcessMaterial::PARAM_ANIM_OFFSET) != 0.0 || + process->get_param_texture(ParticleProcessMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticleProcessMaterial::PARAM_ANIM_OFFSET).is_valid())) { warnings.push_back(RTR("Particles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled.")); } } @@ -625,7 +625,7 @@ void GPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_trail_sections", "get_trail_sections"); ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_section_subdivisions", PROPERTY_HINT_RANGE, "1,1024,1"), "set_trail_section_subdivisions", "get_trail_section_subdivisions"); ADD_GROUP("Process Material", "process_"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material"); ADD_GROUP("Textures", ""); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index a5f7faffef..d7f75c63a4 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -49,8 +49,8 @@ void NavigationAgent2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent2D::set_radius); ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent2D::get_radius); - ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent2D::set_neighbor_dist); - ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent2D::get_neighbor_dist); + ClassDB::bind_method(D_METHOD("set_neighbor_distance", "neighbor_distance"), &NavigationAgent2D::set_neighbor_distance); + ClassDB::bind_method(D_METHOD("get_neighbor_distance"), &NavigationAgent2D::get_neighbor_distance); ClassDB::bind_method(D_METHOD("set_max_neighbors", "max_neighbors"), &NavigationAgent2D::set_max_neighbors); ClassDB::bind_method(D_METHOD("get_max_neighbors"), &NavigationAgent2D::get_max_neighbors); @@ -96,7 +96,7 @@ void NavigationAgent2D::_bind_methods() { ADD_GROUP("Avoidance", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01,suffix:px"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px"), "set_neighbor_dist", "get_neighbor_dist"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px"), "set_neighbor_distance", "get_neighbor_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed"); @@ -173,7 +173,7 @@ void NavigationAgent2D::_notification(int p_what) { NavigationAgent2D::NavigationAgent2D() { agent = NavigationServer2D::get_singleton()->agent_create(); - set_neighbor_dist(500.0); + set_neighbor_distance(500.0); set_max_neighbors(10); set_time_horizon(20.0); set_radius(10.0); @@ -275,9 +275,9 @@ void NavigationAgent2D::set_radius(real_t p_radius) { NavigationServer2D::get_singleton()->agent_set_radius(agent, radius); } -void NavigationAgent2D::set_neighbor_dist(real_t p_dist) { - neighbor_dist = p_dist; - NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); +void NavigationAgent2D::set_neighbor_distance(real_t p_distance) { + neighbor_distance = p_distance; + NavigationServer2D::get_singleton()->agent_set_neighbor_distance(agent, neighbor_distance); } void NavigationAgent2D::set_max_neighbors(int p_count) { diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 76eba20058..11b845665d 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -50,7 +50,7 @@ class NavigationAgent2D : public Node { real_t path_desired_distance = 1.0; real_t target_desired_distance = 1.0; real_t radius = 0.0; - real_t neighbor_dist = 0.0; + real_t neighbor_distance = 0.0; int max_neighbors = 0; real_t time_horizon = 0.0; real_t max_speed = 0.0; @@ -110,9 +110,9 @@ public: return radius; } - void set_neighbor_dist(real_t p_dist); - real_t get_neighbor_dist() const { - return neighbor_dist; + void set_neighbor_distance(real_t p_distance); + real_t get_neighbor_distance() const { + return neighbor_distance; } void set_max_neighbors(int p_count); diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index 0320c6c917..a592d20cba 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -127,7 +127,7 @@ TypedArray<String> NavigationObstacle2D::get_configuration_warnings() const { } if (Object::cast_to<StaticBody2D>(get_parent())) { - warnings.push_back(RTR("The NavigationObstacle2D is intended for constantly moving bodies like CharacterBody2D or RigidDynamicBody2D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." + warnings.push_back(RTR("The NavigationObstacle2D is intended for constantly moving bodies like CharacterBody2D or RigidBody2D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." "\nNot constantly moving or complete static objects should be captured with a refreshed NavigationPolygon so agents can not only avoid them but also move along those objects outline at high detail")); } @@ -135,7 +135,7 @@ TypedArray<String> NavigationObstacle2D::get_configuration_warnings() const { } void NavigationObstacle2D::initialize_agent() { - NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + NavigationServer2D::get_singleton()->agent_set_neighbor_distance(agent, 0.0); NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0); NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0); NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0); diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 3c393f9752..bbc326a4b4 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -175,10 +175,10 @@ void PathFollow2D::_update_transform() { if (path_length == 0) { return; } - Vector2 pos = c->interpolate_baked(offset, cubic); + Vector2 pos = c->interpolate_baked(progress, cubic); if (rotates) { - real_t ahead = offset + lookahead; + real_t ahead = progress + lookahead; if (loop && ahead >= path_length) { // If our lookahead will loop, we need to check if the path is closed. @@ -202,7 +202,7 @@ void PathFollow2D::_update_transform() { // This will happen at the end of non-looping or non-closed paths. // We'll try a look behind instead, in order to get a meaningful angle. tangent_to_curve = - (pos - c->interpolate_baked(offset - lookahead, cubic)).normalized(); + (pos - c->interpolate_baked(progress - lookahead, cubic)).normalized(); } else { tangent_to_curve = (ahead_pos - pos).normalized(); } @@ -269,8 +269,8 @@ TypedArray<String> PathFollow2D::get_configuration_warnings() const { } void PathFollow2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_offset", "offset"), &PathFollow2D::set_offset); - ClassDB::bind_method(D_METHOD("get_offset"), &PathFollow2D::get_offset); + ClassDB::bind_method(D_METHOD("set_progress", "progress"), &PathFollow2D::set_progress); + ClassDB::bind_method(D_METHOD("get_progress"), &PathFollow2D::get_progress); ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &PathFollow2D::set_h_offset); ClassDB::bind_method(D_METHOD("get_h_offset"), &PathFollow2D::get_h_offset); @@ -278,8 +278,8 @@ void PathFollow2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &PathFollow2D::set_v_offset); ClassDB::bind_method(D_METHOD("get_v_offset"), &PathFollow2D::get_v_offset); - ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &PathFollow2D::set_unit_offset); - ClassDB::bind_method(D_METHOD("get_unit_offset"), &PathFollow2D::get_unit_offset); + ClassDB::bind_method(D_METHOD("set_progress_ratio", "ratio"), &PathFollow2D::set_progress_ratio); + ClassDB::bind_method(D_METHOD("get_progress_ratio"), &PathFollow2D::get_progress_ratio); ClassDB::bind_method(D_METHOD("set_rotates", "enable"), &PathFollow2D::set_rotates); ClassDB::bind_method(D_METHOD("is_rotating"), &PathFollow2D::is_rotating); @@ -293,8 +293,8 @@ void PathFollow2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_lookahead", "lookahead"), &PathFollow2D::set_lookahead); ClassDB::bind_method(D_METHOD("get_lookahead"), &PathFollow2D::get_lookahead); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater,suffix:px"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater,suffix:px"), "set_progress", "get_progress"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotates"), "set_rotates", "is_rotating"); @@ -303,20 +303,20 @@ void PathFollow2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"), "set_lookahead", "get_lookahead"); } -void PathFollow2D::set_offset(real_t p_offset) { - ERR_FAIL_COND(!isfinite(p_offset)); - offset = p_offset; +void PathFollow2D::set_progress(real_t p_progress) { + ERR_FAIL_COND(!isfinite(p_progress)); + progress = p_progress; if (path) { if (path->get_curve().is_valid()) { real_t path_length = path->get_curve()->get_baked_length(); if (loop && path_length) { - offset = Math::fposmod(offset, path_length); - if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) { - offset = path_length; + progress = Math::fposmod(progress, path_length); + if (!Math::is_zero_approx(p_progress) && Math::is_zero_approx(progress)) { + progress = path_length; } } else { - offset = CLAMP(offset, 0, path_length); + progress = CLAMP(progress, 0, path_length); } } @@ -346,19 +346,19 @@ real_t PathFollow2D::get_v_offset() const { return v_offset; } -real_t PathFollow2D::get_offset() const { - return offset; +real_t PathFollow2D::get_progress() const { + return progress; } -void PathFollow2D::set_unit_offset(real_t p_unit_offset) { +void PathFollow2D::set_progress_ratio(real_t p_ratio) { if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { - set_offset(p_unit_offset * path->get_curve()->get_baked_length()); + set_progress(p_ratio * path->get_curve()->get_baked_length()); } } -real_t PathFollow2D::get_unit_offset() const { +real_t PathFollow2D::get_progress_ratio() const { if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { - return get_offset() / path->get_curve()->get_baked_length(); + return get_progress() / path->get_curve()->get_baked_length(); } else { return 0; } diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 1f3ee08a2b..3d66ca1fab 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -65,7 +65,7 @@ class PathFollow2D : public Node2D { public: private: Path2D *path = nullptr; - real_t offset = 0.0; + real_t progress = 0.0; real_t h_offset = 0.0; real_t v_offset = 0.0; real_t lookahead = 4.0; @@ -82,8 +82,8 @@ protected: static void _bind_methods(); public: - void set_offset(real_t p_offset); - real_t get_offset() const; + void set_progress(real_t p_progress); + real_t get_progress() const; void set_h_offset(real_t p_h_offset); real_t get_h_offset() const; @@ -91,8 +91,8 @@ public: void set_v_offset(real_t p_v_offset); real_t get_v_offset() const; - void set_unit_offset(real_t p_unit_offset); - real_t get_unit_offset() const; + void set_progress_ratio(real_t p_ratio); + real_t get_progress_ratio() const; void set_lookahead(real_t p_lookahead); real_t get_lookahead() const; diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physical_bone_2d.cpp index 62f4d855ef..e6933b8a40 100644 --- a/scene/2d/physical_bone_2d.cpp +++ b/scene/2d/physical_bone_2d.cpp @@ -35,7 +35,7 @@ void PhysicalBone2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - // Position the RigidDynamicBody in the correct position. + // Position the RigidBody in the correct position. if (follow_bone_when_simulating) { _position_at_bone2d(); } @@ -287,7 +287,7 @@ void PhysicalBone2D::_bind_methods() { } PhysicalBone2D::PhysicalBone2D() { - // Stop the RigidDynamicBody from executing its force integration. + // Stop the RigidBody from executing its force integration. PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0); PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0); PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC); diff --git a/scene/2d/physical_bone_2d.h b/scene/2d/physical_bone_2d.h index 22d329c320..9fbfa04100 100644 --- a/scene/2d/physical_bone_2d.h +++ b/scene/2d/physical_bone_2d.h @@ -36,8 +36,8 @@ class Joint2D; -class PhysicalBone2D : public RigidDynamicBody2D { - GDCLASS(PhysicalBone2D, RigidDynamicBody2D); +class PhysicalBone2D : public RigidBody2D { + GDCLASS(PhysicalBone2D, RigidBody2D); protected: void _notification(int p_what); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index c7ef3a47ad..43158344b4 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -325,7 +325,7 @@ AnimatableBody2D::AnimatableBody2D() : StaticBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) { } -void RigidDynamicBody2D::_body_enter_tree(ObjectID p_id) { +void RigidBody2D::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); @@ -347,7 +347,7 @@ void RigidDynamicBody2D::_body_enter_tree(ObjectID p_id) { contact_monitor->locked = false; } -void RigidDynamicBody2D::_body_exit_tree(ObjectID p_id) { +void RigidBody2D::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); @@ -368,7 +368,7 @@ void RigidDynamicBody2D::_body_exit_tree(ObjectID p_id) { contact_monitor->locked = false; } -void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { +void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { bool body_in = p_status == 1; ObjectID objid = p_instance; @@ -387,8 +387,8 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p //E->value.rc=0; E->value.in_scene = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree).bind(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree).bind(objid)); if (E->value.in_scene) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } @@ -416,8 +416,8 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p if (E->value.shapes.is_empty()) { if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree)); if (in_scene) { emit_signal(SceneStringNames::get_singleton()->body_exited, node); } @@ -431,19 +431,19 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p } } -struct _RigidDynamicBody2DInOut { +struct _RigidBody2DInOut { RID rid; ObjectID id; int shape = 0; int local_shape = 0; }; -void RigidDynamicBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) { - RigidDynamicBody2D *body = static_cast<RigidDynamicBody2D *>(p_instance); +void RigidBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) { + RigidBody2D *body = static_cast<RigidBody2D *>(p_instance); body->_body_state_changed(p_state); } -void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) { +void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) { set_block_transform_notify(true); // don't want notify (would feedback loop) if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) { set_global_transform(p_state->get_transform()); @@ -473,9 +473,9 @@ void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) } } - _RigidDynamicBody2DInOut *toadd = (_RigidDynamicBody2DInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidDynamicBody2DInOut)); + _RigidBody2DInOut *toadd = (_RigidBody2DInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBody2DInOut)); int toadd_count = 0; //state->get_contact_count(); - RigidDynamicBody2D_RemoveAction *toremove = (RigidDynamicBody2D_RemoveAction *)alloca(rc * sizeof(RigidDynamicBody2D_RemoveAction)); + RigidBody2D_RemoveAction *toremove = (RigidBody2D_RemoveAction *)alloca(rc * sizeof(RigidBody2D_RemoveAction)); int toremove_count = 0; //put the ones to add @@ -539,7 +539,7 @@ void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) } } -void RigidDynamicBody2D::_apply_body_mode() { +void RigidBody2D::_apply_body_mode() { if (freeze) { switch (freeze_mode) { case FREEZE_MODE_STATIC: { @@ -550,13 +550,13 @@ void RigidDynamicBody2D::_apply_body_mode() { } break; } } else if (lock_rotation) { - set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR); + set_body_mode(PhysicsServer2D::BODY_MODE_RIGID_LINEAR); } else { - set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer2D::BODY_MODE_RIGID); } } -void RigidDynamicBody2D::set_lock_rotation_enabled(bool p_lock_rotation) { +void RigidBody2D::set_lock_rotation_enabled(bool p_lock_rotation) { if (p_lock_rotation == lock_rotation) { return; } @@ -565,11 +565,11 @@ void RigidDynamicBody2D::set_lock_rotation_enabled(bool p_lock_rotation) { _apply_body_mode(); } -bool RigidDynamicBody2D::is_lock_rotation_enabled() const { +bool RigidBody2D::is_lock_rotation_enabled() const { return lock_rotation; } -void RigidDynamicBody2D::set_freeze_enabled(bool p_freeze) { +void RigidBody2D::set_freeze_enabled(bool p_freeze) { if (p_freeze == freeze) { return; } @@ -578,11 +578,11 @@ void RigidDynamicBody2D::set_freeze_enabled(bool p_freeze) { _apply_body_mode(); } -bool RigidDynamicBody2D::is_freeze_enabled() const { +bool RigidBody2D::is_freeze_enabled() const { return freeze; } -void RigidDynamicBody2D::set_freeze_mode(FreezeMode p_freeze_mode) { +void RigidBody2D::set_freeze_mode(FreezeMode p_freeze_mode) { if (p_freeze_mode == freeze_mode) { return; } @@ -591,31 +591,31 @@ void RigidDynamicBody2D::set_freeze_mode(FreezeMode p_freeze_mode) { _apply_body_mode(); } -RigidDynamicBody2D::FreezeMode RigidDynamicBody2D::get_freeze_mode() const { +RigidBody2D::FreezeMode RigidBody2D::get_freeze_mode() const { return freeze_mode; } -void RigidDynamicBody2D::set_mass(real_t p_mass) { +void RigidBody2D::set_mass(real_t p_mass) { ERR_FAIL_COND(p_mass <= 0); mass = p_mass; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_MASS, mass); } -real_t RigidDynamicBody2D::get_mass() const { +real_t RigidBody2D::get_mass() const { return mass; } -void RigidDynamicBody2D::set_inertia(real_t p_inertia) { +void RigidBody2D::set_inertia(real_t p_inertia) { ERR_FAIL_COND(p_inertia < 0); inertia = p_inertia; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia); } -real_t RigidDynamicBody2D::get_inertia() const { +real_t RigidBody2D::get_inertia() const { return inertia; } -void RigidDynamicBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) { +void RigidBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) { if (center_of_mass_mode == p_mode) { return; } @@ -637,11 +637,11 @@ void RigidDynamicBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) { } } -RigidDynamicBody2D::CenterOfMassMode RigidDynamicBody2D::get_center_of_mass_mode() const { +RigidBody2D::CenterOfMassMode RigidBody2D::get_center_of_mass_mode() const { return center_of_mass_mode; } -void RigidDynamicBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) { +void RigidBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) { if (center_of_mass == p_center_of_mass) { return; } @@ -652,102 +652,102 @@ void RigidDynamicBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) { PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass); } -const Vector2 &RigidDynamicBody2D::get_center_of_mass() const { +const Vector2 &RigidBody2D::get_center_of_mass() const { return center_of_mass; } -void RigidDynamicBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { +void RigidBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { if (physics_material_override.is_valid()) { - if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody2D::_reload_physics_characteristics))) { - physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody2D::_reload_physics_characteristics)); + if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics))) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics)); } } physics_material_override = p_physics_material_override; if (physics_material_override.is_valid()) { - physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody2D::_reload_physics_characteristics)); + physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics)); } _reload_physics_characteristics(); } -Ref<PhysicsMaterial> RigidDynamicBody2D::get_physics_material_override() const { +Ref<PhysicsMaterial> RigidBody2D::get_physics_material_override() const { return physics_material_override; } -void RigidDynamicBody2D::set_gravity_scale(real_t p_gravity_scale) { +void RigidBody2D::set_gravity_scale(real_t p_gravity_scale) { gravity_scale = p_gravity_scale; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE, gravity_scale); } -real_t RigidDynamicBody2D::get_gravity_scale() const { +real_t RigidBody2D::get_gravity_scale() const { return gravity_scale; } -void RigidDynamicBody2D::set_linear_damp_mode(DampMode p_mode) { +void RigidBody2D::set_linear_damp_mode(DampMode p_mode) { linear_damp_mode = p_mode; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode); } -RigidDynamicBody2D::DampMode RigidDynamicBody2D::get_linear_damp_mode() const { +RigidBody2D::DampMode RigidBody2D::get_linear_damp_mode() const { return linear_damp_mode; } -void RigidDynamicBody2D::set_angular_damp_mode(DampMode p_mode) { +void RigidBody2D::set_angular_damp_mode(DampMode p_mode) { angular_damp_mode = p_mode; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode); } -RigidDynamicBody2D::DampMode RigidDynamicBody2D::get_angular_damp_mode() const { +RigidBody2D::DampMode RigidBody2D::get_angular_damp_mode() const { return angular_damp_mode; } -void RigidDynamicBody2D::set_linear_damp(real_t p_linear_damp) { +void RigidBody2D::set_linear_damp(real_t p_linear_damp) { ERR_FAIL_COND(p_linear_damp < -1); linear_damp = p_linear_damp; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP, linear_damp); } -real_t RigidDynamicBody2D::get_linear_damp() const { +real_t RigidBody2D::get_linear_damp() const { return linear_damp; } -void RigidDynamicBody2D::set_angular_damp(real_t p_angular_damp) { +void RigidBody2D::set_angular_damp(real_t p_angular_damp) { ERR_FAIL_COND(p_angular_damp < -1); angular_damp = p_angular_damp; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP, angular_damp); } -real_t RigidDynamicBody2D::get_angular_damp() const { +real_t RigidBody2D::get_angular_damp() const { return angular_damp; } -void RigidDynamicBody2D::set_axis_velocity(const Vector2 &p_axis) { +void RigidBody2D::set_axis_velocity(const Vector2 &p_axis) { Vector2 axis = p_axis.normalized(); linear_velocity -= axis * axis.dot(linear_velocity); linear_velocity += p_axis; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } -void RigidDynamicBody2D::set_linear_velocity(const Vector2 &p_velocity) { +void RigidBody2D::set_linear_velocity(const Vector2 &p_velocity) { linear_velocity = p_velocity; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } -Vector2 RigidDynamicBody2D::get_linear_velocity() const { +Vector2 RigidBody2D::get_linear_velocity() const { return linear_velocity; } -void RigidDynamicBody2D::set_angular_velocity(real_t p_velocity) { +void RigidBody2D::set_angular_velocity(real_t p_velocity) { angular_velocity = p_velocity; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); } -real_t RigidDynamicBody2D::get_angular_velocity() const { +real_t RigidBody2D::get_angular_velocity() const { return angular_velocity; } -void RigidDynamicBody2D::set_use_custom_integrator(bool p_enable) { +void RigidBody2D::set_use_custom_integrator(bool p_enable) { if (custom_integrator == p_enable) { return; } @@ -756,99 +756,105 @@ void RigidDynamicBody2D::set_use_custom_integrator(bool p_enable) { PhysicsServer2D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); } -bool RigidDynamicBody2D::is_using_custom_integrator() { +bool RigidBody2D::is_using_custom_integrator() { return custom_integrator; } -void RigidDynamicBody2D::set_sleeping(bool p_sleeping) { +void RigidBody2D::set_sleeping(bool p_sleeping) { sleeping = p_sleeping; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_SLEEPING, sleeping); } -void RigidDynamicBody2D::set_can_sleep(bool p_active) { +void RigidBody2D::set_can_sleep(bool p_active) { can_sleep = p_active; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_CAN_SLEEP, p_active); } -bool RigidDynamicBody2D::is_able_to_sleep() const { +bool RigidBody2D::is_able_to_sleep() const { return can_sleep; } -bool RigidDynamicBody2D::is_sleeping() const { +bool RigidBody2D::is_sleeping() const { return sleeping; } -void RigidDynamicBody2D::set_max_contacts_reported(int p_amount) { +void RigidBody2D::set_max_contacts_reported(int p_amount) { max_contacts_reported = p_amount; PhysicsServer2D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); } -int RigidDynamicBody2D::get_max_contacts_reported() const { +int RigidBody2D::get_max_contacts_reported() const { return max_contacts_reported; } -void RigidDynamicBody2D::apply_central_impulse(const Vector2 &p_impulse) { +int RigidBody2D::get_contact_count() const { + PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(get_rid()); + ERR_FAIL_NULL_V(bs, 0); + return bs->get_contact_count(); +} + +void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) { PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } -void RigidDynamicBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) { +void RigidBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) { PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position); } -void RigidDynamicBody2D::apply_torque_impulse(real_t p_torque) { +void RigidBody2D::apply_torque_impulse(real_t p_torque) { PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque); } -void RigidDynamicBody2D::apply_central_force(const Vector2 &p_force) { +void RigidBody2D::apply_central_force(const Vector2 &p_force) { PhysicsServer2D::get_singleton()->body_apply_central_force(get_rid(), p_force); } -void RigidDynamicBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) { +void RigidBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) { PhysicsServer2D::get_singleton()->body_apply_force(get_rid(), p_force, p_position); } -void RigidDynamicBody2D::apply_torque(real_t p_torque) { +void RigidBody2D::apply_torque(real_t p_torque) { PhysicsServer2D::get_singleton()->body_apply_torque(get_rid(), p_torque); } -void RigidDynamicBody2D::add_constant_central_force(const Vector2 &p_force) { +void RigidBody2D::add_constant_central_force(const Vector2 &p_force) { PhysicsServer2D::get_singleton()->body_add_constant_central_force(get_rid(), p_force); } -void RigidDynamicBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) { +void RigidBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) { PhysicsServer2D::get_singleton()->body_add_constant_force(get_rid(), p_force, p_position); } -void RigidDynamicBody2D::add_constant_torque(const real_t p_torque) { +void RigidBody2D::add_constant_torque(const real_t p_torque) { PhysicsServer2D::get_singleton()->body_add_constant_torque(get_rid(), p_torque); } -void RigidDynamicBody2D::set_constant_force(const Vector2 &p_force) { +void RigidBody2D::set_constant_force(const Vector2 &p_force) { PhysicsServer2D::get_singleton()->body_set_constant_force(get_rid(), p_force); } -Vector2 RigidDynamicBody2D::get_constant_force() const { +Vector2 RigidBody2D::get_constant_force() const { return PhysicsServer2D::get_singleton()->body_get_constant_force(get_rid()); } -void RigidDynamicBody2D::set_constant_torque(real_t p_torque) { +void RigidBody2D::set_constant_torque(real_t p_torque) { PhysicsServer2D::get_singleton()->body_set_constant_torque(get_rid(), p_torque); } -real_t RigidDynamicBody2D::get_constant_torque() const { +real_t RigidBody2D::get_constant_torque() const { return PhysicsServer2D::get_singleton()->body_get_constant_torque(get_rid()); } -void RigidDynamicBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) { +void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) { ccd_mode = p_mode; PhysicsServer2D::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(), PhysicsServer2D::CCDMode(p_mode)); } -RigidDynamicBody2D::CCDMode RigidDynamicBody2D::get_continuous_collision_detection_mode() const { +RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() const { return ccd_mode; } -TypedArray<Node2D> RigidDynamicBody2D::get_colliding_bodies() const { +TypedArray<Node2D> RigidBody2D::get_colliding_bodies() const { ERR_FAIL_COND_V(!contact_monitor, TypedArray<Node2D>()); TypedArray<Node2D> ret; @@ -866,7 +872,7 @@ TypedArray<Node2D> RigidDynamicBody2D::get_colliding_bodies() const { return ret; } -void RigidDynamicBody2D::set_contact_monitor(bool p_enabled) { +void RigidBody2D::set_contact_monitor(bool p_enabled) { if (p_enabled == is_contact_monitor_enabled()) { return; } @@ -880,8 +886,8 @@ void RigidDynamicBody2D::set_contact_monitor(bool p_enabled) { Node *node = Object::cast_to<Node>(obj); if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree)); } } @@ -893,11 +899,11 @@ void RigidDynamicBody2D::set_contact_monitor(bool p_enabled) { } } -bool RigidDynamicBody2D::is_contact_monitor_enabled() const { +bool RigidBody2D::is_contact_monitor_enabled() const { return contact_monitor != nullptr; } -void RigidDynamicBody2D::_notification(int p_what) { +void RigidBody2D::_notification(int p_what) { #ifdef TOOLS_ENABLED switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -915,102 +921,103 @@ void RigidDynamicBody2D::_notification(int p_what) { #endif } -TypedArray<String> RigidDynamicBody2D::get_configuration_warnings() const { +TypedArray<String> RigidBody2D::get_configuration_warnings() const { Transform2D t = get_transform(); TypedArray<String> warnings = CollisionObject2D::get_configuration_warnings(); if (ABS(t.columns[0].length() - 1.0) > 0.05 || ABS(t.columns[1].length() - 1.0) > 0.05) { - warnings.push_back(RTR("Size changes to RigidDynamicBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); + warnings.push_back(RTR("Size changes to RigidBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } return warnings; } -void RigidDynamicBody2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidDynamicBody2D::set_mass); - ClassDB::bind_method(D_METHOD("get_mass"), &RigidDynamicBody2D::get_mass); +void RigidBody2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody2D::set_mass); + ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody2D::get_mass); - ClassDB::bind_method(D_METHOD("get_inertia"), &RigidDynamicBody2D::get_inertia); - ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidDynamicBody2D::set_inertia); + ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody2D::get_inertia); + ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody2D::set_inertia); - ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidDynamicBody2D::set_center_of_mass_mode); - ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidDynamicBody2D::get_center_of_mass_mode); + ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody2D::set_center_of_mass_mode); + ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody2D::get_center_of_mass_mode); - ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidDynamicBody2D::set_center_of_mass); - ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidDynamicBody2D::get_center_of_mass); + ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody2D::set_center_of_mass); + ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody2D::get_center_of_mass); - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidDynamicBody2D::set_physics_material_override); - ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidDynamicBody2D::get_physics_material_override); + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody2D::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody2D::get_physics_material_override); - ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidDynamicBody2D::set_gravity_scale); - ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidDynamicBody2D::get_gravity_scale); + ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody2D::set_gravity_scale); + ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody2D::get_gravity_scale); - ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidDynamicBody2D::set_linear_damp_mode); - ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidDynamicBody2D::get_linear_damp_mode); + ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody2D::set_linear_damp_mode); + ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody2D::get_linear_damp_mode); - ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidDynamicBody2D::set_angular_damp_mode); - ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidDynamicBody2D::get_angular_damp_mode); + ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody2D::set_angular_damp_mode); + ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody2D::get_angular_damp_mode); - ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidDynamicBody2D::set_linear_damp); - ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidDynamicBody2D::get_linear_damp); + ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody2D::set_linear_damp); + ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody2D::get_linear_damp); - ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidDynamicBody2D::set_angular_damp); - ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidDynamicBody2D::get_angular_damp); + ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody2D::set_angular_damp); + ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody2D::get_angular_damp); - ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidDynamicBody2D::set_linear_velocity); - ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidDynamicBody2D::get_linear_velocity); + ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody2D::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody2D::get_linear_velocity); - ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidDynamicBody2D::set_angular_velocity); - ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidDynamicBody2D::get_angular_velocity); + ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody2D::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody2D::get_angular_velocity); - ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidDynamicBody2D::set_max_contacts_reported); - ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidDynamicBody2D::get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody2D::set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody2D::get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody2D::get_contact_count); - ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidDynamicBody2D::set_use_custom_integrator); - ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidDynamicBody2D::is_using_custom_integrator); + ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody2D::set_use_custom_integrator); + ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody2D::is_using_custom_integrator); - ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidDynamicBody2D::set_contact_monitor); - ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidDynamicBody2D::is_contact_monitor_enabled); + ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody2D::set_contact_monitor); + ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody2D::is_contact_monitor_enabled); - ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode", "mode"), &RigidDynamicBody2D::set_continuous_collision_detection_mode); - ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidDynamicBody2D::get_continuous_collision_detection_mode); + ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode", "mode"), &RigidBody2D::set_continuous_collision_detection_mode); + ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidBody2D::get_continuous_collision_detection_mode); - ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidDynamicBody2D::set_axis_velocity); - ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidDynamicBody2D::apply_central_impulse, Vector2()); - ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidDynamicBody2D::apply_impulse, Vector2()); - ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidDynamicBody2D::apply_torque_impulse); + ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody2D::set_axis_velocity); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse, Vector2()); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody2D::apply_impulse, Vector2()); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidBody2D::apply_torque_impulse); - ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidDynamicBody2D::apply_central_force); - ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidDynamicBody2D::apply_force, Vector2()); - ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidDynamicBody2D::apply_torque); + ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody2D::apply_central_force); + ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody2D::apply_force, Vector2()); + ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody2D::apply_torque); - ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidDynamicBody2D::add_constant_central_force); - ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidDynamicBody2D::add_constant_force, Vector2()); - ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidDynamicBody2D::add_constant_torque); + ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody2D::add_constant_central_force); + ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody2D::add_constant_force, Vector2()); + ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody2D::add_constant_torque); - ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidDynamicBody2D::set_constant_force); - ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidDynamicBody2D::get_constant_force); + ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody2D::set_constant_force); + ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody2D::get_constant_force); - ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidDynamicBody2D::set_constant_torque); - ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidDynamicBody2D::get_constant_torque); + ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody2D::set_constant_torque); + ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody2D::get_constant_torque); - ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidDynamicBody2D::set_sleeping); - ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidDynamicBody2D::is_sleeping); + ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody2D::set_sleeping); + ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody2D::is_sleeping); - ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidDynamicBody2D::set_can_sleep); - ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidDynamicBody2D::is_able_to_sleep); + ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep); + ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep); - ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidDynamicBody2D::set_lock_rotation_enabled); - ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidDynamicBody2D::is_lock_rotation_enabled); + ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody2D::set_lock_rotation_enabled); + ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody2D::is_lock_rotation_enabled); - ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidDynamicBody2D::set_freeze_enabled); - ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidDynamicBody2D::is_freeze_enabled); + ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody2D::set_freeze_enabled); + ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody2D::is_freeze_enabled); - ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidDynamicBody2D::set_freeze_mode); - ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidDynamicBody2D::get_freeze_mode); + ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody2D::set_freeze_mode); + ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody2D::get_freeze_mode); - ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidDynamicBody2D::get_colliding_bodies); + ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies); GDVIRTUAL_BIND(_integrate_forces, "state"); @@ -1023,7 +1030,7 @@ void RigidDynamicBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); @@ -1062,7 +1069,7 @@ void RigidDynamicBody2D::_bind_methods() { BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE); } -void RigidDynamicBody2D::_validate_property(PropertyInfo &p_property) const { +void RigidBody2D::_validate_property(PropertyInfo &p_property) const { if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) { if (p_property.name == "center_of_mass") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; @@ -1070,18 +1077,18 @@ void RigidDynamicBody2D::_validate_property(PropertyInfo &p_property) const { } } -RigidDynamicBody2D::RigidDynamicBody2D() : - PhysicsBody2D(PhysicsServer2D::BODY_MODE_DYNAMIC) { +RigidBody2D::RigidBody2D() : + PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) { PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); } -RigidDynamicBody2D::~RigidDynamicBody2D() { +RigidBody2D::~RigidBody2D() { if (contact_monitor) { memdelete(contact_monitor); } } -void RigidDynamicBody2D::_reload_physics_characteristics() { +void RigidBody2D::_reload_physics_characteristics() { if (physics_material_override.is_null()) { PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0); PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1); @@ -1107,9 +1114,9 @@ bool CharacterBody2D::move_and_slide() { if ((on_floor || on_wall) && platform_rid.is_valid()) { bool excluded = false; if (on_floor) { - excluded = (moving_platform_floor_layers & platform_layer) == 0; + excluded = (platform_floor_layers & platform_layer) == 0; } else if (on_wall) { - excluded = (moving_platform_wall_layers & platform_layer) == 0; + excluded = (platform_wall_layers & platform_layer) == 0; } if (!excluded) { //this approach makes sure there is less delay between the actual body velocity and the one we saved @@ -1159,10 +1166,10 @@ bool CharacterBody2D::move_and_slide() { // Compute real velocity. real_velocity = get_position_delta() / delta; - if (moving_platform_apply_velocity_on_leave != PLATFORM_VEL_ON_LEAVE_NEVER) { + if (platform_on_leave != PLATFORM_ON_LEAVE_DO_NOTHING) { // Add last platform velocity when just left a moving platform. if (!on_floor && !on_wall) { - if (moving_platform_apply_velocity_on_leave == PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY && current_platform_velocity.dot(up_direction) < 0) { + if (platform_on_leave == PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY && current_platform_velocity.dot(up_direction) < 0) { current_platform_velocity = current_platform_velocity.slide(up_direction); } velocity += current_platform_velocity; @@ -1606,20 +1613,20 @@ void CharacterBody2D::set_slide_on_ceiling_enabled(bool p_enabled) { slide_on_ceiling = p_enabled; } -uint32_t CharacterBody2D::get_moving_platform_floor_layers() const { - return moving_platform_floor_layers; +uint32_t CharacterBody2D::get_platform_floor_layers() const { + return platform_floor_layers; } -void CharacterBody2D::set_moving_platform_floor_layers(uint32_t p_exclude_layers) { - moving_platform_floor_layers = p_exclude_layers; +void CharacterBody2D::set_platform_floor_layers(uint32_t p_exclude_layers) { + platform_floor_layers = p_exclude_layers; } -uint32_t CharacterBody2D::get_moving_platform_wall_layers() const { - return moving_platform_wall_layers; +uint32_t CharacterBody2D::get_platform_wall_layers() const { + return platform_wall_layers; } -void CharacterBody2D::set_moving_platform_wall_layers(uint32_t p_exclude_layers) { - moving_platform_wall_layers = p_exclude_layers; +void CharacterBody2D::set_platform_wall_layers(uint32_t p_exclude_layers) { + platform_wall_layers = p_exclude_layers; } void CharacterBody2D::set_motion_mode(MotionMode p_mode) { @@ -1630,12 +1637,12 @@ CharacterBody2D::MotionMode CharacterBody2D::get_motion_mode() const { return motion_mode; } -void CharacterBody2D::set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_apply_velocity) { - moving_platform_apply_velocity_on_leave = p_on_leave_apply_velocity; +void CharacterBody2D::set_platform_on_leave(PlatformOnLeave p_on_leave_apply_velocity) { + platform_on_leave = p_on_leave_apply_velocity; } -CharacterBody2D::MovingPlatformApplyVelocityOnLeave CharacterBody2D::get_moving_platform_apply_velocity_on_leave() const { - return moving_platform_apply_velocity_on_leave; +CharacterBody2D::PlatformOnLeave CharacterBody2D::get_platform_on_leave() const { + return platform_on_leave; } int CharacterBody2D::get_max_slides() const { @@ -1713,10 +1720,10 @@ void CharacterBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody2D::set_slide_on_ceiling_enabled); ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody2D::is_slide_on_ceiling_enabled); - ClassDB::bind_method(D_METHOD("set_moving_platform_floor_layers", "exclude_layer"), &CharacterBody2D::set_moving_platform_floor_layers); - ClassDB::bind_method(D_METHOD("get_moving_platform_floor_layers"), &CharacterBody2D::get_moving_platform_floor_layers); - ClassDB::bind_method(D_METHOD("set_moving_platform_wall_layers", "exclude_layer"), &CharacterBody2D::set_moving_platform_wall_layers); - ClassDB::bind_method(D_METHOD("get_moving_platform_wall_layers"), &CharacterBody2D::get_moving_platform_wall_layers); + ClassDB::bind_method(D_METHOD("set_platform_floor_layers", "exclude_layer"), &CharacterBody2D::set_platform_floor_layers); + ClassDB::bind_method(D_METHOD("get_platform_floor_layers"), &CharacterBody2D::get_platform_floor_layers); + ClassDB::bind_method(D_METHOD("set_platform_wall_layers", "exclude_layer"), &CharacterBody2D::set_platform_wall_layers); + ClassDB::bind_method(D_METHOD("get_platform_wall_layers"), &CharacterBody2D::get_platform_wall_layers); ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides); ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides); @@ -1730,8 +1737,8 @@ void CharacterBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction); ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody2D::set_motion_mode); ClassDB::bind_method(D_METHOD("get_motion_mode"), &CharacterBody2D::get_motion_mode); - ClassDB::bind_method(D_METHOD("set_moving_platform_apply_velocity_on_leave", "on_leave_apply_velocity"), &CharacterBody2D::set_moving_platform_apply_velocity_on_leave); - ClassDB::bind_method(D_METHOD("get_moving_platform_apply_velocity_on_leave"), &CharacterBody2D::get_moving_platform_apply_velocity_on_leave); + ClassDB::bind_method(D_METHOD("set_platform_on_leave", "on_leave_apply_velocity"), &CharacterBody2D::set_platform_on_leave); + ClassDB::bind_method(D_METHOD("get_platform_on_leave"), &CharacterBody2D::get_platform_on_leave); ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody2D::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody2D::is_on_floor_only); @@ -1764,10 +1771,10 @@ void CharacterBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater,suffix:px"), "set_floor_snap_length", "get_floor_snap_length"); - ADD_GROUP("Moving Platform", "moving_platform"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_apply_velocity_on_leave", PROPERTY_HINT_ENUM, "Always,Upward Only,Never", PROPERTY_USAGE_DEFAULT), "set_moving_platform_apply_velocity_on_leave", "get_moving_platform_apply_velocity_on_leave"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_moving_platform_floor_layers", "get_moving_platform_floor_layers"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_wall_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_moving_platform_wall_layers", "get_moving_platform_wall_layers"); + ADD_GROUP("Moving Platform", "platform"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_on_leave", PROPERTY_HINT_ENUM, "Add Velocity,Add Upward Velocity,Do Nothing", PROPERTY_USAGE_DEFAULT), "set_platform_on_leave", "get_platform_on_leave"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_floor_layers", "get_platform_floor_layers"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_wall_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_wall_layers", "get_platform_wall_layers"); ADD_GROUP("Collision", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001,suffix:px"), "set_safe_margin", "get_safe_margin"); @@ -1775,9 +1782,9 @@ void CharacterBody2D::_bind_methods() { BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED); BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING); - BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_ALWAYS); - BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY); - BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_NEVER); + BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_VELOCITY); + BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY); + BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_DO_NOTHING); } void CharacterBody2D::_validate_property(PropertyInfo &p_property) const { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 75ea535424..eaba9aadad 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -113,8 +113,8 @@ private: bool is_sync_to_physics_enabled() const; }; -class RigidDynamicBody2D : public PhysicsBody2D { - GDCLASS(RigidDynamicBody2D, PhysicsBody2D); +class RigidBody2D : public PhysicsBody2D { + GDCLASS(RigidBody2D, PhysicsBody2D); public: enum FreezeMode { @@ -186,7 +186,7 @@ private: local_shape = p_ls; } }; - struct RigidDynamicBody2D_RemoveAction { + struct RigidBody2D_RemoveAction { RID rid; ObjectID body_id; ShapePair pair; @@ -284,6 +284,7 @@ public: void set_max_contacts_reported(int p_amount); int get_max_contacts_reported() const; + int get_contact_count() const; void set_continuous_collision_detection_mode(CCDMode p_mode); CCDMode get_continuous_collision_detection_mode() const; @@ -310,17 +311,17 @@ public: virtual TypedArray<String> get_configuration_warnings() const override; - RigidDynamicBody2D(); - ~RigidDynamicBody2D(); + RigidBody2D(); + ~RigidBody2D(); private: void _reload_physics_characteristics(); }; -VARIANT_ENUM_CAST(RigidDynamicBody2D::FreezeMode); -VARIANT_ENUM_CAST(RigidDynamicBody2D::CenterOfMassMode); -VARIANT_ENUM_CAST(RigidDynamicBody2D::DampMode); -VARIANT_ENUM_CAST(RigidDynamicBody2D::CCDMode); +VARIANT_ENUM_CAST(RigidBody2D::FreezeMode); +VARIANT_ENUM_CAST(RigidBody2D::CenterOfMassMode); +VARIANT_ENUM_CAST(RigidBody2D::DampMode); +VARIANT_ENUM_CAST(RigidBody2D::CCDMode); class CharacterBody2D : public PhysicsBody2D { GDCLASS(CharacterBody2D, PhysicsBody2D); @@ -330,10 +331,10 @@ public: MOTION_MODE_GROUNDED, MOTION_MODE_FLOATING, }; - enum MovingPlatformApplyVelocityOnLeave { - PLATFORM_VEL_ON_LEAVE_ALWAYS, - PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY, - PLATFORM_VEL_ON_LEAVE_NEVER, + enum PlatformOnLeave { + PLATFORM_ON_LEAVE_ADD_VELOCITY, + PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY, + PLATFORM_ON_LEAVE_DO_NOTHING, }; bool move_and_slide(); @@ -364,7 +365,7 @@ public: private: real_t margin = 0.08; MotionMode motion_mode = MOTION_MODE_GROUNDED; - MovingPlatformApplyVelocityOnLeave moving_platform_apply_velocity_on_leave = PLATFORM_VEL_ON_LEAVE_ALWAYS; + PlatformOnLeave platform_on_leave = PLATFORM_ON_LEAVE_ADD_VELOCITY; bool floor_constant_speed = false; bool floor_stop_on_slope = true; @@ -372,12 +373,12 @@ private: bool slide_on_ceiling = true; int max_slides = 4; int platform_layer = 0; - real_t floor_max_angle = Math::deg2rad((real_t)45.0); + real_t floor_max_angle = Math::deg_to_rad((real_t)45.0); real_t floor_snap_length = 1; - real_t wall_min_slide_angle = Math::deg2rad((real_t)15.0); + real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0); Vector2 up_direction = Vector2(0.0, -1.0); - uint32_t moving_platform_floor_layers = UINT32_MAX; - uint32_t moving_platform_wall_layers = 0; + uint32_t platform_floor_layers = UINT32_MAX; + uint32_t platform_wall_layers = 0; Vector2 velocity; Vector2 floor_normal; @@ -423,17 +424,17 @@ private: real_t get_wall_min_slide_angle() const; void set_wall_min_slide_angle(real_t p_radians); - uint32_t get_moving_platform_floor_layers() const; - void set_moving_platform_floor_layers(const uint32_t p_exclude_layer); + uint32_t get_platform_floor_layers() const; + void set_platform_floor_layers(const uint32_t p_exclude_layer); - uint32_t get_moving_platform_wall_layers() const; - void set_moving_platform_wall_layers(const uint32_t p_exclude_layer); + uint32_t get_platform_wall_layers() const; + void set_platform_wall_layers(const uint32_t p_exclude_layer); void set_motion_mode(MotionMode p_mode); MotionMode get_motion_mode() const; - void set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_velocity); - MovingPlatformApplyVelocityOnLeave get_moving_platform_apply_velocity_on_leave() const; + void set_platform_on_leave(PlatformOnLeave p_on_leave_velocity); + PlatformOnLeave get_platform_on_leave() const; void _move_and_slide_floating(double p_delta); void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); @@ -454,7 +455,7 @@ protected: }; VARIANT_ENUM_CAST(CharacterBody2D::MotionMode); -VARIANT_ENUM_CAST(CharacterBody2D::MovingPlatformApplyVelocityOnLeave); +VARIANT_ENUM_CAST(CharacterBody2D::PlatformOnLeave); class KinematicCollision2D : public RefCounted { GDCLASS(KinematicCollision2D, RefCounted); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index cb918ecb8b..8161fb5bd9 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -602,8 +602,8 @@ void Polygon2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture_scale", "texture_scale"), &Polygon2D::set_texture_scale); ClassDB::bind_method(D_METHOD("get_texture_scale"), &Polygon2D::get_texture_scale); - ClassDB::bind_method(D_METHOD("set_invert", "invert"), &Polygon2D::set_invert); - ClassDB::bind_method(D_METHOD("get_invert"), &Polygon2D::get_invert); + ClassDB::bind_method(D_METHOD("set_invert_enabled", "invert"), &Polygon2D::set_invert); + ClassDB::bind_method(D_METHOD("get_invert_enabled"), &Polygon2D::get_invert); ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &Polygon2D::set_antialiased); ClassDB::bind_method(D_METHOD("get_antialiased"), &Polygon2D::get_antialiased); @@ -646,7 +646,7 @@ void Polygon2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton2D"), "set_skeleton", "get_skeleton"); ADD_GROUP("Invert", "invert_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_enable"), "set_invert", "get_invert"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_enabled"), "set_invert_enabled", "get_invert_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "invert_border", PROPERTY_HINT_RANGE, "0.1,16384,0.1,suffix:px"), "set_invert_border", "get_invert_border"); ADD_GROUP("Data", ""); diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index cbacb7f579..13a32fbfd4 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -44,7 +44,7 @@ bool Bone2D::_set(const StringName &p_path, const Variant &p_value) { } else if (path.begins_with("length")) { set_length(p_value); } else if (path.begins_with("bone_angle")) { - set_bone_angle(Math::deg2rad(real_t(p_value))); + set_bone_angle(Math::deg_to_rad(real_t(p_value))); } else if (path.begins_with("default_length")) { set_length(p_value); } @@ -66,7 +66,7 @@ bool Bone2D::_get(const StringName &p_path, Variant &r_ret) const { } else if (path.begins_with("length")) { r_ret = get_length(); } else if (path.begins_with("bone_angle")) { - r_ret = Math::rad2deg(get_bone_angle()); + r_ret = Math::rad_to_deg(get_bone_angle()); } else if (path.begins_with("default_length")) { r_ret = get_length(); } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 13bdd2bd5f..129cce93fa 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -553,7 +553,7 @@ int TileMap::get_layers_count() const { void TileMap::add_layer(int p_to_pos) { if (p_to_pos < 0) { - p_to_pos = layers.size(); + p_to_pos = layers.size() + p_to_pos + 1; } ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1); @@ -612,6 +612,9 @@ void TileMap::remove_layer(int p_layer) { } void TileMap::set_layer_name(int p_layer, String p_name) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].name = p_name; emit_signal(SNAME("changed")); @@ -623,6 +626,9 @@ String TileMap::get_layer_name(int p_layer) const { } void TileMap::set_layer_enabled(int p_layer, bool p_enabled) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].enabled = p_enabled; _clear_layer_internals(p_layer); @@ -638,6 +644,9 @@ bool TileMap::is_layer_enabled(int p_layer) const { } void TileMap::set_layer_modulate(int p_layer, Color p_modulate) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].modulate = p_modulate; _clear_layer_internals(p_layer); @@ -651,6 +660,9 @@ Color TileMap::get_layer_modulate(int p_layer) const { } void TileMap::set_layer_y_sort_enabled(int p_layer, bool p_y_sort_enabled) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].y_sort_enabled = p_y_sort_enabled; _clear_layer_internals(p_layer); @@ -666,6 +678,9 @@ bool TileMap::is_layer_y_sort_enabled(int p_layer) const { } void TileMap::set_layer_y_sort_origin(int p_layer, int p_y_sort_origin) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].y_sort_origin = p_y_sort_origin; _clear_layer_internals(p_layer); @@ -679,6 +694,9 @@ int TileMap::get_layer_y_sort_origin(int p_layer) const { } void TileMap::set_layer_z_index(int p_layer, int p_z_index) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].z_index = p_z_index; _clear_layer_internals(p_layer); @@ -3839,7 +3857,7 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("get_layer_name", "layer"), &TileMap::get_layer_name); ClassDB::bind_method(D_METHOD("set_layer_enabled", "layer", "enabled"), &TileMap::set_layer_enabled); ClassDB::bind_method(D_METHOD("is_layer_enabled", "layer"), &TileMap::is_layer_enabled); - ClassDB::bind_method(D_METHOD("set_layer_modulate", "layer", "enabled"), &TileMap::set_layer_modulate); + ClassDB::bind_method(D_METHOD("set_layer_modulate", "layer", "modulate"), &TileMap::set_layer_modulate); ClassDB::bind_method(D_METHOD("get_layer_modulate", "layer"), &TileMap::get_layer_modulate); ClassDB::bind_method(D_METHOD("set_layer_y_sort_enabled", "layer", "y_sort_enabled"), &TileMap::set_layer_y_sort_enabled); ClassDB::bind_method(D_METHOD("is_layer_y_sort_enabled", "layer"), &TileMap::is_layer_y_sort_enabled); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 93e91f9b5b..0e7b71f74a 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -149,7 +149,7 @@ void AudioStreamPlayer3D::_calc_reverb_vol(Area3D *area, Vector3 listener_area_p if (uniformity > 0.0) { float distance = listener_area_pos.length(); - float attenuation = Math::db2linear(_get_attenuation_db(distance)); + float attenuation = Math::db_to_linear(_get_attenuation_db(distance)); // Determine the fraction of sound that would come from each speaker if they were all driven uniformly. float center_val[3] = { 0.5f, 0.25f, 0.16666f }; @@ -213,12 +213,12 @@ float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const { float att = 0; switch (attenuation_model) { case ATTENUATION_INVERSE_DISTANCE: { - att = Math::linear2db(1.0 / ((p_distance / unit_size) + CMP_EPSILON)); + att = Math::linear_to_db(1.0 / ((p_distance / unit_size) + CMP_EPSILON)); } break; case ATTENUATION_INVERSE_SQUARE_DISTANCE: { float d = (p_distance / unit_size); d *= d; - att = Math::linear2db(1.0 / (d + CMP_EPSILON)); + att = Math::linear_to_db(1.0 / (d + CMP_EPSILON)); } break; case ATTENUATION_LOGARITHMIC: { att = -20 * Math::log(p_distance / unit_size + CMP_EPSILON); @@ -443,7 +443,7 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() { } } - float multiplier = Math::db2linear(_get_attenuation_db(dist)); + float multiplier = Math::db_to_linear(_get_attenuation_db(dist)); if (max_distance > 0) { multiplier *= MAX(0, 1.0 - (dist / max_distance)); } @@ -453,13 +453,13 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() { if (emission_angle_enabled) { Vector3 listenertopos = global_pos - listener_node->get_global_transform().origin; float c = listenertopos.normalized().dot(get_global_transform().basis.get_column(2).normalized()); //it's z negative - float angle = Math::rad2deg(Math::acos(c)); + float angle = Math::rad_to_deg(Math::acos(c)); if (angle > emission_angle) { db_att -= -emission_angle_filter_attenuation_db; } } - linear_attenuation = Math::db2linear(db_att); + linear_attenuation = Math::db_to_linear(db_att); for (Ref<AudioStreamPlayback> &playback : stream_playbacks) { AudioServer::get_singleton()->set_playback_highshelf_params(playback, linear_attenuation, attenuation_filter_cutoff_hz); } diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp index bd6a70e566..90099d787b 100644 --- a/scene/3d/collision_polygon_3d.cpp +++ b/scene/3d/collision_polygon_3d.cpp @@ -171,7 +171,7 @@ TypedArray<String> CollisionPolygon3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject3D>(get_parent())) { - warnings.push_back(RTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidDynamicBody3D, CharacterBody3D, etc. to give them a shape.")); + warnings.push_back(RTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape.")); } if (polygon.is_empty()) { diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 759997de7b..a9bc28b464 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -118,7 +118,7 @@ TypedArray<String> CollisionShape3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject3D>(get_parent())) { - warnings.push_back(RTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidDynamicBody3D, CharacterBody3D, etc. to give them a shape.")); + warnings.push_back(RTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape.")); } if (!shape.is_valid()) { @@ -126,9 +126,9 @@ TypedArray<String> CollisionShape3D::get_configuration_warnings() const { } if (shape.is_valid() && - Object::cast_to<RigidDynamicBody3D>(get_parent()) && + Object::cast_to<RigidBody3D>(get_parent()) && Object::cast_to<ConcavePolygonShape3D>(*shape)) { - warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidDynamicBody3D in another mode than static.")); + warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static.")); } return warnings; diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index a79fd15b1a..9dc61b35af 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -33,7 +33,7 @@ #include "scene/3d/camera_3d.h" #include "scene/3d/gpu_particles_3d.h" #include "scene/main/viewport.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" AABB CPUParticles3D::get_aabb() const { return AABB(); @@ -766,13 +766,13 @@ void CPUParticles3D::_particles_process(double p_delta) { } if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { - real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread); + real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg_to_rad((Math::randf() * 2.0 - 1.0) * spread); Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0); p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf()); } else { //initiate velocity spread in 3D - real_t angle1_rad = Math::deg2rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * spread); - real_t angle2_rad = Math::deg2rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread); + real_t angle1_rad = Math::deg_to_rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * spread); + real_t angle2_rad = Math::deg_to_rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread); Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad)); Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad)); @@ -796,7 +796,7 @@ void CPUParticles3D::_particles_process(double p_delta) { } real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand); - p.custom[0] = Math::deg2rad(base_angle); //angle + p.custom[0] = Math::deg_to_rad(base_angle); //angle p.custom[1] = 0.0; //phase p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand); //animation offset (0-1) p.transform = Transform3D(); @@ -983,7 +983,7 @@ void CPUParticles3D::_particles_process(double p_delta) { real_t orbit_amount = tex_orbit_velocity * Math::lerp(parameters_min[PARAM_ORBIT_VELOCITY], parameters_max[PARAM_ORBIT_VELOCITY], rand_from_seed(alt_seed)); if (orbit_amount != 0.0) { real_t ang = orbit_amount * local_delta * Math_TAU; - // Not sure why the ParticlesMaterial code uses a clockwise rotation matrix, + // Not sure why the ParticleProcessMaterial code uses a clockwise rotation matrix, // but we use -ang here to reproduce its behavior. Transform2D rot = Transform2D(-ang, Vector2()); Vector2 rotv = rot.basis_xform(Vector2(diff.x, diff.y)); @@ -1007,7 +1007,7 @@ void CPUParticles3D::_particles_process(double p_delta) { } real_t base_angle = (tex_angle)*Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand); base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(alt_seed)); - p.custom[0] = Math::deg2rad(base_angle); //angle + p.custom[0] = Math::deg_to_rad(base_angle); //angle p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + tv * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed)); //angle } //apply color @@ -1343,7 +1343,7 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) { set_draw_order(DrawOrder(particles->get_draw_order())); set_mesh(particles->get_draw_pass_mesh(0)); - Ref<ParticlesMaterial> material = particles->get_process_material(); + Ref<ParticleProcessMaterial> material = particles->get_process_material(); if (material.is_null()) { return; } @@ -1364,14 +1364,14 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) { set_color_initial_ramp(gti->get_gradient()); } - set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); - set_particle_flag(PARTICLE_FLAG_ROTATE_Y, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ROTATE_Y)); - set_particle_flag(PARTICLE_FLAG_DISABLE_Z, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_DISABLE_Z)); + set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); + set_particle_flag(PARTICLE_FLAG_ROTATE_Y, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_ROTATE_Y)); + set_particle_flag(PARTICLE_FLAG_DISABLE_Z, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_DISABLE_Z)); set_emission_shape(EmissionShape(material->get_emission_shape())); set_emission_sphere_radius(material->get_emission_sphere_radius()); set_emission_box_extents(material->get_emission_box_extents()); - Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticlesMaterial::PARAM_SCALE); + Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticleProcessMaterial::PARAM_SCALE); if (scale3D.is_valid()) { split_scale = true; scale_curve_x = scale3D->get_curve_x(); @@ -1382,14 +1382,14 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) { set_gravity(material->get_gravity()); set_lifetime_randomness(material->get_lifetime_randomness()); -#define CONVERT_PARAM(m_param) \ - set_param_min(m_param, material->get_param_min(ParticlesMaterial::m_param)); \ - { \ - Ref<CurveTexture> ctex = material->get_param_texture(ParticlesMaterial::m_param); \ - if (ctex.is_valid()) \ - set_param_curve(m_param, ctex->get_curve()); \ - } \ - set_param_max(m_param, material->get_param_max(ParticlesMaterial::m_param)); +#define CONVERT_PARAM(m_param) \ + set_param_min(m_param, material->get_param_min(ParticleProcessMaterial::m_param)); \ + { \ + Ref<CurveTexture> ctex = material->get_param_texture(ParticleProcessMaterial::m_param); \ + if (ctex.is_valid()) \ + set_param_curve(m_param, ctex->get_curve()); \ + } \ + set_param_max(m_param, material->get_param_max(ParticleProcessMaterial::m_param)); CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY); CONVERT_PARAM(PARAM_ANGULAR_VELOCITY); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index b46e6a8b71..bd63939d74 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -30,7 +30,7 @@ #include "gpu_particles_3d.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" AABB GPUParticles3D::get_aabb() const { return AABB(); @@ -306,10 +306,10 @@ TypedArray<String> GPUParticles3D::get_configuration_warnings() const { if (process_material.is_null()) { warnings.push_back(RTR("A material to process the particles is not assigned, so no behavior is imprinted.")); } else { - const ParticlesMaterial *process = Object::cast_to<ParticlesMaterial>(process_material.ptr()); + const ParticleProcessMaterial *process = Object::cast_to<ParticleProcessMaterial>(process_material.ptr()); if (!anim_material_found && process && - (process->get_param_max(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param_max(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || - process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { + (process->get_param_max(ParticleProcessMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param_max(ParticleProcessMaterial::PARAM_ANIM_OFFSET) != 0.0 || + process->get_param_texture(ParticleProcessMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticleProcessMaterial::PARAM_ANIM_OFFSET).is_valid())) { warnings.push_back(RTR("Particles animation requires the usage of a BaseMaterial3D whose Billboard Mode is set to \"Particle Billboard\".")); } } @@ -585,7 +585,7 @@ void GPUParticles3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_trail_enabled", "is_trail_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_trail_length", "get_trail_length"); ADD_GROUP("Process Material", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material"); ADD_GROUP("Draw Passes", "draw_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_passes", PROPERTY_HINT_RANGE, "0," + itos(MAX_DRAW_PASSES) + ",1"), "set_draw_passes", "get_draw_passes"); for (int i = 0; i < MAX_DRAW_PASSES; i++) { diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 35036b70d8..40b8af7d63 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -31,6 +31,7 @@ #include "label_3d.h" #include "core/core_string_names.h" +#include "scene/main/viewport.h" #include "scene/resources/theme.h" #include "scene/scene_string_names.h" @@ -184,6 +185,14 @@ void Label3D::_notification(int p_what) { if (!pending_update) { _im_update(); } + Viewport *viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + viewport->connect("size_changed", callable_mp(this, &Label3D::_font_changed)); + } break; + case NOTIFICATION_EXIT_TREE: { + Viewport *viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + viewport->disconnect("size_changed", callable_mp(this, &Label3D::_font_changed)); } break; case NOTIFICATION_TRANSLATION_CHANGED: { String new_text = tr(text); diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 0581544e07..8d96d13f0c 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -149,7 +149,7 @@ AABB Light3D::get_aabb() const { } else if (type == RenderingServer::LIGHT_SPOT) { real_t len = param[PARAM_RANGE]; - real_t size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len; + real_t size = Math::tan(Math::deg_to_rad(param[PARAM_SPOT_ANGLE])) * len; return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); } diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 3752713d6a..34e84861a2 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -53,8 +53,8 @@ void NavigationAgent3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_ignore_y", "ignore"), &NavigationAgent3D::set_ignore_y); ClassDB::bind_method(D_METHOD("get_ignore_y"), &NavigationAgent3D::get_ignore_y); - ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent3D::set_neighbor_dist); - ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent3D::get_neighbor_dist); + ClassDB::bind_method(D_METHOD("set_neighbor_distance", "neighbor_distance"), &NavigationAgent3D::set_neighbor_distance); + ClassDB::bind_method(D_METHOD("get_neighbor_distance"), &NavigationAgent3D::get_neighbor_distance); ClassDB::bind_method(D_METHOD("set_max_neighbors", "max_neighbors"), &NavigationAgent3D::set_max_neighbors); ClassDB::bind_method(D_METHOD("get_max_neighbors"), &NavigationAgent3D::get_max_neighbors); @@ -101,7 +101,7 @@ void NavigationAgent3D::_bind_methods() { ADD_GROUP("Avoidance", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m"), "set_neighbor_dist", "get_neighbor_dist"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m"), "set_neighbor_distance", "get_neighbor_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m/s"), "set_max_speed", "get_max_speed"); @@ -179,7 +179,7 @@ void NavigationAgent3D::_notification(int p_what) { NavigationAgent3D::NavigationAgent3D() { agent = NavigationServer3D::get_singleton()->agent_create(); - set_neighbor_dist(50.0); + set_neighbor_distance(50.0); set_max_neighbors(10); set_time_horizon(5.0); set_radius(1.0); @@ -291,9 +291,9 @@ void NavigationAgent3D::set_ignore_y(bool p_ignore_y) { NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, ignore_y); } -void NavigationAgent3D::set_neighbor_dist(real_t p_dist) { - neighbor_dist = p_dist; - NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); +void NavigationAgent3D::set_neighbor_distance(real_t p_distance) { + neighbor_distance = p_distance; + NavigationServer3D::get_singleton()->agent_set_neighbor_distance(agent, neighbor_distance); } void NavigationAgent3D::set_max_neighbors(int p_count) { diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index e05f0287f7..35c1b1175a 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -52,7 +52,7 @@ class NavigationAgent3D : public Node { real_t radius = 0.0; real_t navigation_height_offset = 0.0; bool ignore_y = false; - real_t neighbor_dist = 0.0; + real_t neighbor_distance = 0.0; int max_neighbors = 0; real_t time_horizon = 0.0; real_t max_speed = 0.0; @@ -122,9 +122,9 @@ public: return ignore_y; } - void set_neighbor_dist(real_t p_dist); - real_t get_neighbor_dist() const { - return neighbor_dist; + void set_neighbor_distance(real_t p_distance); + real_t get_neighbor_distance() const { + return neighbor_distance; } void set_max_neighbors(int p_count); diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index c6eda1f9cd..953e52e591 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -133,7 +133,7 @@ TypedArray<String> NavigationObstacle3D::get_configuration_warnings() const { } if (Object::cast_to<StaticBody3D>(get_parent())) { - warnings.push_back(RTR("The NavigationObstacle3D is intended for constantly moving bodies like CharacterBody3D or RigidDynamicBody3D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." + warnings.push_back(RTR("The NavigationObstacle3D is intended for constantly moving bodies like CharacterBody3D or RigidBody3D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." "\nNot constantly moving or complete static objects should be (re)baked to a NavigationMesh so agents can not only avoid them but also move along those objects outline at high detail")); } @@ -141,7 +141,7 @@ TypedArray<String> NavigationObstacle3D::get_configuration_warnings() const { } void NavigationObstacle3D::initialize_agent() { - NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + NavigationServer3D::get_singleton()->agent_set_neighbor_distance(agent, 0.0); NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0); NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0); NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0); diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index 8c4e5c5275..7d79d9b4fd 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -183,8 +183,8 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { return; } real_t bi = c->get_bake_interval(); - real_t o_next = offset + bi; - real_t o_prev = offset - bi; + real_t o_next = progress + bi; + real_t o_prev = progress - bi; if (loop) { o_next = Math::fposmod(o_next, bl); @@ -198,7 +198,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { } } - Vector3 pos = c->interpolate_baked(offset, cubic); + Vector3 pos = c->interpolate_baked(progress, cubic); Transform3D t = get_transform(); // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used @@ -217,9 +217,9 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { forward.normalize(); } - Vector3 up = c->interpolate_baked_up_vector(offset, true); + Vector3 up = c->interpolate_baked_up_vector(progress, true); - if (o_next < offset) { + if (o_next < progress) { Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); Vector3 axis = up.cross(up1); @@ -247,12 +247,12 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { // for a discussion about why not Frenet frame. t.origin = pos; - if (p_update_xyz_rot && prev_offset != offset) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree. + if (p_update_xyz_rot && prev_offset != progress) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree. real_t sample_distance = bi * 0.01; Vector3 t_prev_pos_a = c->interpolate_baked(prev_offset - sample_distance, cubic); Vector3 t_prev_pos_b = c->interpolate_baked(prev_offset + sample_distance, cubic); - Vector3 t_cur_pos_a = c->interpolate_baked(offset - sample_distance, cubic); - Vector3 t_cur_pos_b = c->interpolate_baked(offset + sample_distance, cubic); + Vector3 t_cur_pos_a = c->interpolate_baked(progress - sample_distance, cubic); + Vector3 t_cur_pos_b = c->interpolate_baked(progress + sample_distance, cubic); Vector3 t_prev = (t_prev_pos_a - t_prev_pos_b).normalized(); Vector3 t_cur = (t_cur_pos_a - t_cur_pos_b).normalized(); @@ -277,7 +277,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) { } // do the additional tilting - real_t tilt_angle = c->interpolate_baked_tilt(offset); + real_t tilt_angle = c->interpolate_baked_tilt(progress); Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct?? if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) { @@ -359,8 +359,8 @@ TypedArray<String> PathFollow3D::get_configuration_warnings() const { } void PathFollow3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_offset", "offset"), &PathFollow3D::set_offset); - ClassDB::bind_method(D_METHOD("get_offset"), &PathFollow3D::get_offset); + ClassDB::bind_method(D_METHOD("set_progress", "progress"), &PathFollow3D::set_progress); + ClassDB::bind_method(D_METHOD("get_progress"), &PathFollow3D::get_progress); ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &PathFollow3D::set_h_offset); ClassDB::bind_method(D_METHOD("get_h_offset"), &PathFollow3D::get_h_offset); @@ -368,8 +368,8 @@ void PathFollow3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &PathFollow3D::set_v_offset); ClassDB::bind_method(D_METHOD("get_v_offset"), &PathFollow3D::get_v_offset); - ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &PathFollow3D::set_unit_offset); - ClassDB::bind_method(D_METHOD("get_unit_offset"), &PathFollow3D::get_unit_offset); + ClassDB::bind_method(D_METHOD("set_progress_ratio", "ratio"), &PathFollow3D::set_progress_ratio); + ClassDB::bind_method(D_METHOD("get_progress_ratio"), &PathFollow3D::get_progress_ratio); ClassDB::bind_method(D_METHOD("set_rotation_mode", "rotation_mode"), &PathFollow3D::set_rotation_mode); ClassDB::bind_method(D_METHOD("get_rotation_mode"), &PathFollow3D::get_rotation_mode); @@ -380,8 +380,8 @@ void PathFollow3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow3D::set_loop); ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow3D::has_loop); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater,suffix:m"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater,suffix:m"), "set_progress", "get_progress"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode"); @@ -395,22 +395,22 @@ void PathFollow3D::_bind_methods() { BIND_ENUM_CONSTANT(ROTATION_ORIENTED); } -void PathFollow3D::set_offset(real_t p_offset) { - ERR_FAIL_COND(!isfinite(p_offset)); - prev_offset = offset; - offset = p_offset; +void PathFollow3D::set_progress(real_t p_progress) { + ERR_FAIL_COND(!isfinite(p_progress)); + prev_offset = progress; + progress = p_progress; if (path) { if (path->get_curve().is_valid()) { real_t path_length = path->get_curve()->get_baked_length(); if (loop && path_length) { - offset = Math::fposmod(offset, path_length); - if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) { - offset = path_length; + progress = Math::fposmod(progress, path_length); + if (!Math::is_zero_approx(p_progress) && Math::is_zero_approx(progress)) { + progress = path_length; } } else { - offset = CLAMP(offset, 0, path_length); + progress = CLAMP(progress, 0, path_length); } } @@ -440,19 +440,19 @@ real_t PathFollow3D::get_v_offset() const { return v_offset; } -real_t PathFollow3D::get_offset() const { - return offset; +real_t PathFollow3D::get_progress() const { + return progress; } -void PathFollow3D::set_unit_offset(real_t p_unit_offset) { +void PathFollow3D::set_progress_ratio(real_t p_ratio) { if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { - set_offset(p_unit_offset * path->get_curve()->get_baked_length()); + set_progress(p_ratio * path->get_curve()->get_baked_length()); } } -real_t PathFollow3D::get_unit_offset() const { +real_t PathFollow3D::get_progress_ratio() const { if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { - return get_offset() / path->get_curve()->get_baked_length(); + return get_progress() / path->get_curve()->get_baked_length(); } else { return 0; } diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h index bc4db61a01..45fa2c8917 100644 --- a/scene/3d/path_3d.h +++ b/scene/3d/path_3d.h @@ -75,7 +75,7 @@ public: private: Path3D *path = nullptr; real_t prev_offset = 0.0; // Offset during the last _update_transform. - real_t offset = 0.0; + real_t progress = 0.0; real_t h_offset = 0.0; real_t v_offset = 0.0; bool cubic = true; @@ -91,8 +91,8 @@ protected: static void _bind_methods(); public: - void set_offset(real_t p_offset); - real_t get_offset() const; + void set_progress(real_t p_progress); + real_t get_progress() const; void set_h_offset(real_t p_h_offset); real_t get_h_offset() const; @@ -100,8 +100,8 @@ public: void set_v_offset(real_t p_v_offset); real_t get_v_offset() const; - void set_unit_offset(real_t p_unit_offset); - real_t get_unit_offset() const; + void set_progress_ratio(real_t p_ratio); + real_t get_progress_ratio() const; void set_loop(bool p_loop); bool has_loop() const; diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index d8c0516a94..5534bc28f1 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -376,7 +376,7 @@ AnimatableBody3D::AnimatableBody3D() : PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); } -void RigidDynamicBody3D::_body_enter_tree(ObjectID p_id) { +void RigidBody3D::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); @@ -399,7 +399,7 @@ void RigidDynamicBody3D::_body_enter_tree(ObjectID p_id) { contact_monitor->locked = false; } -void RigidDynamicBody3D::_body_exit_tree(ObjectID p_id) { +void RigidBody3D::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); @@ -420,7 +420,7 @@ void RigidDynamicBody3D::_body_exit_tree(ObjectID p_id) { contact_monitor->locked = false; } -void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { +void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { bool body_in = p_status == 1; ObjectID objid = p_instance; @@ -439,8 +439,8 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p //E->value.rc=0; E->value.in_tree = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree).bind(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree).bind(objid)); if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } @@ -466,8 +466,8 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p if (E->value.shapes.is_empty()) { if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree)); if (in_tree) { emit_signal(SceneStringNames::get_singleton()->body_exited, node); } @@ -481,19 +481,19 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p } } -struct _RigidDynamicBodyInOut { +struct _RigidBodyInOut { RID rid; ObjectID id; int shape = 0; int local_shape = 0; }; -void RigidDynamicBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) { - RigidDynamicBody3D *body = (RigidDynamicBody3D *)p_instance; +void RigidBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) { + RigidBody3D *body = (RigidBody3D *)p_instance; body->_body_state_changed(p_state); } -void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { +void RigidBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { set_ignore_transform_notification(true); set_global_transform(p_state->get_transform()); @@ -524,9 +524,9 @@ void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) } } - _RigidDynamicBodyInOut *toadd = (_RigidDynamicBodyInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidDynamicBodyInOut)); - int toadd_count = 0; //state->get_contact_count(); - RigidDynamicBody3D_RemoveAction *toremove = (RigidDynamicBody3D_RemoveAction *)alloca(rc * sizeof(RigidDynamicBody3D_RemoveAction)); + _RigidBodyInOut *toadd = (_RigidBodyInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBodyInOut)); + int toadd_count = 0; + RigidBody3D_RemoveAction *toremove = (RigidBody3D_RemoveAction *)alloca(rc * sizeof(RigidBody3D_RemoveAction)); int toremove_count = 0; //put the ones to add @@ -537,8 +537,6 @@ void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) int local_shape = p_state->get_contact_local_shape(i); int shape = p_state->get_contact_collider_shape(i); - //bool found=false; - HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(obj); if (!E) { toadd[toadd_count].rid = rid; @@ -592,7 +590,7 @@ void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) } } -void RigidDynamicBody3D::_notification(int p_what) { +void RigidBody3D::_notification(int p_what) { #ifdef TOOLS_ENABLED switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -610,7 +608,7 @@ void RigidDynamicBody3D::_notification(int p_what) { #endif } -void RigidDynamicBody3D::_apply_body_mode() { +void RigidBody3D::_apply_body_mode() { if (freeze) { switch (freeze_mode) { case FREEZE_MODE_STATIC: { @@ -621,13 +619,13 @@ void RigidDynamicBody3D::_apply_body_mode() { } break; } } else if (lock_rotation) { - set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR); + set_body_mode(PhysicsServer3D::BODY_MODE_RIGID_LINEAR); } else { - set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer3D::BODY_MODE_RIGID); } } -void RigidDynamicBody3D::set_lock_rotation_enabled(bool p_lock_rotation) { +void RigidBody3D::set_lock_rotation_enabled(bool p_lock_rotation) { if (p_lock_rotation == lock_rotation) { return; } @@ -636,11 +634,11 @@ void RigidDynamicBody3D::set_lock_rotation_enabled(bool p_lock_rotation) { _apply_body_mode(); } -bool RigidDynamicBody3D::is_lock_rotation_enabled() const { +bool RigidBody3D::is_lock_rotation_enabled() const { return lock_rotation; } -void RigidDynamicBody3D::set_freeze_enabled(bool p_freeze) { +void RigidBody3D::set_freeze_enabled(bool p_freeze) { if (p_freeze == freeze) { return; } @@ -649,11 +647,11 @@ void RigidDynamicBody3D::set_freeze_enabled(bool p_freeze) { _apply_body_mode(); } -bool RigidDynamicBody3D::is_freeze_enabled() const { +bool RigidBody3D::is_freeze_enabled() const { return freeze; } -void RigidDynamicBody3D::set_freeze_mode(FreezeMode p_freeze_mode) { +void RigidBody3D::set_freeze_mode(FreezeMode p_freeze_mode) { if (p_freeze_mode == freeze_mode) { return; } @@ -662,21 +660,21 @@ void RigidDynamicBody3D::set_freeze_mode(FreezeMode p_freeze_mode) { _apply_body_mode(); } -RigidDynamicBody3D::FreezeMode RigidDynamicBody3D::get_freeze_mode() const { +RigidBody3D::FreezeMode RigidBody3D::get_freeze_mode() const { return freeze_mode; } -void RigidDynamicBody3D::set_mass(real_t p_mass) { +void RigidBody3D::set_mass(real_t p_mass) { ERR_FAIL_COND(p_mass <= 0); mass = p_mass; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass); } -real_t RigidDynamicBody3D::get_mass() const { +real_t RigidBody3D::get_mass() const { return mass; } -void RigidDynamicBody3D::set_inertia(const Vector3 &p_inertia) { +void RigidBody3D::set_inertia(const Vector3 &p_inertia) { ERR_FAIL_COND(p_inertia.x < 0); ERR_FAIL_COND(p_inertia.y < 0); ERR_FAIL_COND(p_inertia.z < 0); @@ -685,11 +683,11 @@ void RigidDynamicBody3D::set_inertia(const Vector3 &p_inertia) { PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_INERTIA, inertia); } -const Vector3 &RigidDynamicBody3D::get_inertia() const { +const Vector3 &RigidBody3D::get_inertia() const { return inertia; } -void RigidDynamicBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) { +void RigidBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) { if (center_of_mass_mode == p_mode) { return; } @@ -711,11 +709,11 @@ void RigidDynamicBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) { } } -RigidDynamicBody3D::CenterOfMassMode RigidDynamicBody3D::get_center_of_mass_mode() const { +RigidBody3D::CenterOfMassMode RigidBody3D::get_center_of_mass_mode() const { return center_of_mass_mode; } -void RigidDynamicBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) { +void RigidBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) { if (center_of_mass == p_center_of_mass) { return; } @@ -726,106 +724,106 @@ void RigidDynamicBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) { PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass); } -const Vector3 &RigidDynamicBody3D::get_center_of_mass() const { +const Vector3 &RigidBody3D::get_center_of_mass() const { return center_of_mass; } -void RigidDynamicBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { +void RigidBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { if (physics_material_override.is_valid()) { - if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody3D::_reload_physics_characteristics))) { - physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody3D::_reload_physics_characteristics)); + if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics))) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics)); } } physics_material_override = p_physics_material_override; if (physics_material_override.is_valid()) { - physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody3D::_reload_physics_characteristics)); + physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics)); } _reload_physics_characteristics(); } -Ref<PhysicsMaterial> RigidDynamicBody3D::get_physics_material_override() const { +Ref<PhysicsMaterial> RigidBody3D::get_physics_material_override() const { return physics_material_override; } -void RigidDynamicBody3D::set_gravity_scale(real_t p_gravity_scale) { +void RigidBody3D::set_gravity_scale(real_t p_gravity_scale) { gravity_scale = p_gravity_scale; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale); } -real_t RigidDynamicBody3D::get_gravity_scale() const { +real_t RigidBody3D::get_gravity_scale() const { return gravity_scale; } -void RigidDynamicBody3D::set_linear_damp_mode(DampMode p_mode) { +void RigidBody3D::set_linear_damp_mode(DampMode p_mode) { linear_damp_mode = p_mode; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode); } -RigidDynamicBody3D::DampMode RigidDynamicBody3D::get_linear_damp_mode() const { +RigidBody3D::DampMode RigidBody3D::get_linear_damp_mode() const { return linear_damp_mode; } -void RigidDynamicBody3D::set_angular_damp_mode(DampMode p_mode) { +void RigidBody3D::set_angular_damp_mode(DampMode p_mode) { angular_damp_mode = p_mode; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode); } -RigidDynamicBody3D::DampMode RigidDynamicBody3D::get_angular_damp_mode() const { +RigidBody3D::DampMode RigidBody3D::get_angular_damp_mode() const { return angular_damp_mode; } -void RigidDynamicBody3D::set_linear_damp(real_t p_linear_damp) { +void RigidBody3D::set_linear_damp(real_t p_linear_damp) { ERR_FAIL_COND(p_linear_damp < 0.0); linear_damp = p_linear_damp; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp); } -real_t RigidDynamicBody3D::get_linear_damp() const { +real_t RigidBody3D::get_linear_damp() const { return linear_damp; } -void RigidDynamicBody3D::set_angular_damp(real_t p_angular_damp) { +void RigidBody3D::set_angular_damp(real_t p_angular_damp) { ERR_FAIL_COND(p_angular_damp < 0.0); angular_damp = p_angular_damp; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp); } -real_t RigidDynamicBody3D::get_angular_damp() const { +real_t RigidBody3D::get_angular_damp() const { return angular_damp; } -void RigidDynamicBody3D::set_axis_velocity(const Vector3 &p_axis) { +void RigidBody3D::set_axis_velocity(const Vector3 &p_axis) { Vector3 axis = p_axis.normalized(); linear_velocity -= axis * axis.dot(linear_velocity); linear_velocity += p_axis; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } -void RigidDynamicBody3D::set_linear_velocity(const Vector3 &p_velocity) { +void RigidBody3D::set_linear_velocity(const Vector3 &p_velocity) { linear_velocity = p_velocity; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } -Vector3 RigidDynamicBody3D::get_linear_velocity() const { +Vector3 RigidBody3D::get_linear_velocity() const { return linear_velocity; } -void RigidDynamicBody3D::set_angular_velocity(const Vector3 &p_velocity) { +void RigidBody3D::set_angular_velocity(const Vector3 &p_velocity) { angular_velocity = p_velocity; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); } -Vector3 RigidDynamicBody3D::get_angular_velocity() const { +Vector3 RigidBody3D::get_angular_velocity() const { return angular_velocity; } -Basis RigidDynamicBody3D::get_inverse_inertia_tensor() const { +Basis RigidBody3D::get_inverse_inertia_tensor() const { return inverse_inertia_tensor; } -void RigidDynamicBody3D::set_use_custom_integrator(bool p_enable) { +void RigidBody3D::set_use_custom_integrator(bool p_enable) { if (custom_integrator == p_enable) { return; } @@ -834,102 +832,108 @@ void RigidDynamicBody3D::set_use_custom_integrator(bool p_enable) { PhysicsServer3D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); } -bool RigidDynamicBody3D::is_using_custom_integrator() { +bool RigidBody3D::is_using_custom_integrator() { return custom_integrator; } -void RigidDynamicBody3D::set_sleeping(bool p_sleeping) { +void RigidBody3D::set_sleeping(bool p_sleeping) { sleeping = p_sleeping; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_SLEEPING, sleeping); } -void RigidDynamicBody3D::set_can_sleep(bool p_active) { +void RigidBody3D::set_can_sleep(bool p_active) { can_sleep = p_active; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_CAN_SLEEP, p_active); } -bool RigidDynamicBody3D::is_able_to_sleep() const { +bool RigidBody3D::is_able_to_sleep() const { return can_sleep; } -bool RigidDynamicBody3D::is_sleeping() const { +bool RigidBody3D::is_sleeping() const { return sleeping; } -void RigidDynamicBody3D::set_max_contacts_reported(int p_amount) { +void RigidBody3D::set_max_contacts_reported(int p_amount) { max_contacts_reported = p_amount; PhysicsServer3D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); } -int RigidDynamicBody3D::get_max_contacts_reported() const { +int RigidBody3D::get_max_contacts_reported() const { return max_contacts_reported; } -void RigidDynamicBody3D::apply_central_impulse(const Vector3 &p_impulse) { +int RigidBody3D::get_contact_count() const { + PhysicsDirectBodyState3D *bs = PhysicsServer3D::get_singleton()->body_get_direct_state(get_rid()); + ERR_FAIL_NULL_V(bs, 0); + return bs->get_contact_count(); +} + +void RigidBody3D::apply_central_impulse(const Vector3 &p_impulse) { PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } -void RigidDynamicBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { +void RigidBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { PhysicsServer3D *singleton = PhysicsServer3D::get_singleton(); singleton->body_apply_impulse(get_rid(), p_impulse, p_position); } -void RigidDynamicBody3D::apply_torque_impulse(const Vector3 &p_impulse) { +void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) { PhysicsServer3D::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse); } -void RigidDynamicBody3D::apply_central_force(const Vector3 &p_force) { +void RigidBody3D::apply_central_force(const Vector3 &p_force) { PhysicsServer3D::get_singleton()->body_apply_central_force(get_rid(), p_force); } -void RigidDynamicBody3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) { +void RigidBody3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) { PhysicsServer3D *singleton = PhysicsServer3D::get_singleton(); singleton->body_apply_force(get_rid(), p_force, p_position); } -void RigidDynamicBody3D::apply_torque(const Vector3 &p_torque) { +void RigidBody3D::apply_torque(const Vector3 &p_torque) { PhysicsServer3D::get_singleton()->body_apply_torque(get_rid(), p_torque); } -void RigidDynamicBody3D::add_constant_central_force(const Vector3 &p_force) { +void RigidBody3D::add_constant_central_force(const Vector3 &p_force) { PhysicsServer3D::get_singleton()->body_add_constant_central_force(get_rid(), p_force); } -void RigidDynamicBody3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) { +void RigidBody3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) { PhysicsServer3D *singleton = PhysicsServer3D::get_singleton(); singleton->body_add_constant_force(get_rid(), p_force, p_position); } -void RigidDynamicBody3D::add_constant_torque(const Vector3 &p_torque) { +void RigidBody3D::add_constant_torque(const Vector3 &p_torque) { PhysicsServer3D::get_singleton()->body_add_constant_torque(get_rid(), p_torque); } -void RigidDynamicBody3D::set_constant_force(const Vector3 &p_force) { +void RigidBody3D::set_constant_force(const Vector3 &p_force) { PhysicsServer3D::get_singleton()->body_set_constant_force(get_rid(), p_force); } -Vector3 RigidDynamicBody3D::get_constant_force() const { +Vector3 RigidBody3D::get_constant_force() const { return PhysicsServer3D::get_singleton()->body_get_constant_force(get_rid()); } -void RigidDynamicBody3D::set_constant_torque(const Vector3 &p_torque) { +void RigidBody3D::set_constant_torque(const Vector3 &p_torque) { PhysicsServer3D::get_singleton()->body_set_constant_torque(get_rid(), p_torque); } -Vector3 RigidDynamicBody3D::get_constant_torque() const { +Vector3 RigidBody3D::get_constant_torque() const { return PhysicsServer3D::get_singleton()->body_get_constant_torque(get_rid()); } -void RigidDynamicBody3D::set_use_continuous_collision_detection(bool p_enable) { +void RigidBody3D::set_use_continuous_collision_detection(bool p_enable) { ccd = p_enable; PhysicsServer3D::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(), p_enable); } -bool RigidDynamicBody3D::is_using_continuous_collision_detection() const { +bool RigidBody3D::is_using_continuous_collision_detection() const { return ccd; } -void RigidDynamicBody3D::set_contact_monitor(bool p_enabled) { +void RigidBody3D::set_contact_monitor(bool p_enabled) { if (p_enabled == is_contact_monitor_enabled()) { return; } @@ -943,8 +947,8 @@ void RigidDynamicBody3D::set_contact_monitor(bool p_enabled) { Node *node = Object::cast_to<Node>(obj); if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree)); } } @@ -956,11 +960,11 @@ void RigidDynamicBody3D::set_contact_monitor(bool p_enabled) { } } -bool RigidDynamicBody3D::is_contact_monitor_enabled() const { +bool RigidBody3D::is_contact_monitor_enabled() const { return contact_monitor != nullptr; } -TypedArray<Node3D> RigidDynamicBody3D::get_colliding_bodies() const { +TypedArray<Node3D> RigidBody3D::get_colliding_bodies() const { ERR_FAIL_COND_V(!contact_monitor, TypedArray<Node3D>()); TypedArray<Node3D> ret; @@ -978,105 +982,106 @@ TypedArray<Node3D> RigidDynamicBody3D::get_colliding_bodies() const { return ret; } -TypedArray<String> RigidDynamicBody3D::get_configuration_warnings() const { +TypedArray<String> RigidBody3D::get_configuration_warnings() const { Transform3D t = get_transform(); TypedArray<String> warnings = Node::get_configuration_warnings(); if (ABS(t.basis.get_column(0).length() - 1.0) > 0.05 || ABS(t.basis.get_column(1).length() - 1.0) > 0.05 || ABS(t.basis.get_column(2).length() - 1.0) > 0.05) { - warnings.push_back(RTR("Size changes to RigidDynamicBody will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); + warnings.push_back(RTR("Size changes to RigidBody will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } return warnings; } -void RigidDynamicBody3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidDynamicBody3D::set_mass); - ClassDB::bind_method(D_METHOD("get_mass"), &RigidDynamicBody3D::get_mass); +void RigidBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody3D::set_mass); + ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody3D::get_mass); - ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidDynamicBody3D::set_inertia); - ClassDB::bind_method(D_METHOD("get_inertia"), &RigidDynamicBody3D::get_inertia); + ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody3D::set_inertia); + ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody3D::get_inertia); - ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidDynamicBody3D::set_center_of_mass_mode); - ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidDynamicBody3D::get_center_of_mass_mode); + ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody3D::set_center_of_mass_mode); + ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody3D::get_center_of_mass_mode); - ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidDynamicBody3D::set_center_of_mass); - ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidDynamicBody3D::get_center_of_mass); + ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody3D::set_center_of_mass); + ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody3D::get_center_of_mass); - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidDynamicBody3D::set_physics_material_override); - ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidDynamicBody3D::get_physics_material_override); + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody3D::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody3D::get_physics_material_override); - ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidDynamicBody3D::set_linear_velocity); - ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidDynamicBody3D::get_linear_velocity); + ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody3D::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody3D::get_linear_velocity); - ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidDynamicBody3D::set_angular_velocity); - ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidDynamicBody3D::get_angular_velocity); + ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody3D::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody3D::get_angular_velocity); - ClassDB::bind_method(D_METHOD("get_inverse_inertia_tensor"), &RigidDynamicBody3D::get_inverse_inertia_tensor); + ClassDB::bind_method(D_METHOD("get_inverse_inertia_tensor"), &RigidBody3D::get_inverse_inertia_tensor); - ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidDynamicBody3D::set_gravity_scale); - ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidDynamicBody3D::get_gravity_scale); + ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody3D::set_gravity_scale); + ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody3D::get_gravity_scale); - ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidDynamicBody3D::set_linear_damp_mode); - ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidDynamicBody3D::get_linear_damp_mode); + ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody3D::set_linear_damp_mode); + ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody3D::get_linear_damp_mode); - ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidDynamicBody3D::set_angular_damp_mode); - ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidDynamicBody3D::get_angular_damp_mode); + ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody3D::set_angular_damp_mode); + ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody3D::get_angular_damp_mode); - ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidDynamicBody3D::set_linear_damp); - ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidDynamicBody3D::get_linear_damp); + ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody3D::set_linear_damp); + ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody3D::get_linear_damp); - ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidDynamicBody3D::set_angular_damp); - ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidDynamicBody3D::get_angular_damp); + ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody3D::set_angular_damp); + ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody3D::get_angular_damp); - ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidDynamicBody3D::set_max_contacts_reported); - ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidDynamicBody3D::get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody3D::set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody3D::get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody3D::get_contact_count); - ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidDynamicBody3D::set_use_custom_integrator); - ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidDynamicBody3D::is_using_custom_integrator); + ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody3D::set_use_custom_integrator); + ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody3D::is_using_custom_integrator); - ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidDynamicBody3D::set_contact_monitor); - ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidDynamicBody3D::is_contact_monitor_enabled); + ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody3D::set_contact_monitor); + ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody3D::is_contact_monitor_enabled); - ClassDB::bind_method(D_METHOD("set_use_continuous_collision_detection", "enable"), &RigidDynamicBody3D::set_use_continuous_collision_detection); - ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidDynamicBody3D::is_using_continuous_collision_detection); + ClassDB::bind_method(D_METHOD("set_use_continuous_collision_detection", "enable"), &RigidBody3D::set_use_continuous_collision_detection); + ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidBody3D::is_using_continuous_collision_detection); - ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidDynamicBody3D::set_axis_velocity); + ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody3D::set_axis_velocity); - ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidDynamicBody3D::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidDynamicBody3D::apply_impulse, Vector3()); - ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidDynamicBody3D::apply_torque_impulse); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody3D::apply_central_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody3D::apply_impulse, Vector3()); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody3D::apply_torque_impulse); - ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidDynamicBody3D::apply_central_force); - ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidDynamicBody3D::apply_force, Vector3()); - ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidDynamicBody3D::apply_torque); + ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody3D::apply_central_force); + ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody3D::apply_force, Vector3()); + ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody3D::apply_torque); - ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidDynamicBody3D::add_constant_central_force); - ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidDynamicBody3D::add_constant_force, Vector3()); - ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidDynamicBody3D::add_constant_torque); + ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody3D::add_constant_central_force); + ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody3D::add_constant_force, Vector3()); + ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody3D::add_constant_torque); - ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidDynamicBody3D::set_constant_force); - ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidDynamicBody3D::get_constant_force); + ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody3D::set_constant_force); + ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody3D::get_constant_force); - ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidDynamicBody3D::set_constant_torque); - ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidDynamicBody3D::get_constant_torque); + ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody3D::set_constant_torque); + ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody3D::get_constant_torque); - ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidDynamicBody3D::set_sleeping); - ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidDynamicBody3D::is_sleeping); + ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody3D::set_sleeping); + ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody3D::is_sleeping); - ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidDynamicBody3D::set_can_sleep); - ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidDynamicBody3D::is_able_to_sleep); + ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody3D::set_can_sleep); + ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody3D::is_able_to_sleep); - ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidDynamicBody3D::set_lock_rotation_enabled); - ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidDynamicBody3D::is_lock_rotation_enabled); + ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody3D::set_lock_rotation_enabled); + ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody3D::is_lock_rotation_enabled); - ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidDynamicBody3D::set_freeze_enabled); - ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidDynamicBody3D::is_freeze_enabled); + ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody3D::set_freeze_enabled); + ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody3D::is_freeze_enabled); - ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidDynamicBody3D::set_freeze_mode); - ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidDynamicBody3D::get_freeze_mode); + ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody3D::set_freeze_mode); + ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody3D::get_freeze_mode); - ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidDynamicBody3D::get_colliding_bodies); + ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody3D::get_colliding_bodies); GDVIRTUAL_BIND(_integrate_forces, "state"); @@ -1089,7 +1094,7 @@ void RigidDynamicBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); @@ -1124,7 +1129,7 @@ void RigidDynamicBody3D::_bind_methods() { BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE); } -void RigidDynamicBody3D::_validate_property(PropertyInfo &p_property) const { +void RigidBody3D::_validate_property(PropertyInfo &p_property) const { if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) { if (p_property.name == "center_of_mass") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; @@ -1132,18 +1137,18 @@ void RigidDynamicBody3D::_validate_property(PropertyInfo &p_property) const { } } -RigidDynamicBody3D::RigidDynamicBody3D() : - PhysicsBody3D(PhysicsServer3D::BODY_MODE_DYNAMIC) { +RigidBody3D::RigidBody3D() : + PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) { PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); } -RigidDynamicBody3D::~RigidDynamicBody3D() { +RigidBody3D::~RigidBody3D() { if (contact_monitor) { memdelete(contact_monitor); } } -void RigidDynamicBody3D::_reload_physics_characteristics() { +void RigidBody3D::_reload_physics_characteristics() { if (physics_material_override.is_null()) { PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0); PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1); @@ -1176,9 +1181,9 @@ bool CharacterBody3D::move_and_slide() { if ((collision_state.floor || collision_state.wall) && platform_rid.is_valid()) { bool excluded = false; if (collision_state.floor) { - excluded = (moving_platform_floor_layers & platform_layer) == 0; + excluded = (platform_floor_layers & platform_layer) == 0; } else if (collision_state.wall) { - excluded = (moving_platform_wall_layers & platform_layer) == 0; + excluded = (platform_wall_layers & platform_layer) == 0; } if (!excluded) { //this approach makes sure there is less delay between the actual body velocity and the one we saved @@ -1230,10 +1235,10 @@ bool CharacterBody3D::move_and_slide() { // Compute real velocity. real_velocity = get_position_delta() / delta; - if (moving_platform_apply_velocity_on_leave != PLATFORM_VEL_ON_LEAVE_NEVER) { + if (platform_on_leave != PLATFORM_ON_LEAVE_DO_NOTHING) { // Add last platform velocity when just left a moving platform. if (!collision_state.floor && !collision_state.wall) { - if (moving_platform_apply_velocity_on_leave == PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY && current_platform_velocity.dot(up_direction) < 0) { + if (platform_on_leave == PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY && current_platform_velocity.dot(up_direction) < 0) { current_platform_velocity = current_platform_velocity.slide(up_direction); } velocity += current_platform_velocity; @@ -1853,20 +1858,20 @@ void CharacterBody3D::set_slide_on_ceiling_enabled(bool p_enabled) { slide_on_ceiling = p_enabled; } -uint32_t CharacterBody3D::get_moving_platform_floor_layers() const { - return moving_platform_floor_layers; +uint32_t CharacterBody3D::get_platform_floor_layers() const { + return platform_floor_layers; } -void CharacterBody3D::set_moving_platform_floor_layers(uint32_t p_exclude_layers) { - moving_platform_floor_layers = p_exclude_layers; +void CharacterBody3D::set_platform_floor_layers(uint32_t p_exclude_layers) { + platform_floor_layers = p_exclude_layers; } -uint32_t CharacterBody3D::get_moving_platform_wall_layers() const { - return moving_platform_wall_layers; +uint32_t CharacterBody3D::get_platform_wall_layers() const { + return platform_wall_layers; } -void CharacterBody3D::set_moving_platform_wall_layers(uint32_t p_exclude_layers) { - moving_platform_wall_layers = p_exclude_layers; +void CharacterBody3D::set_platform_wall_layers(uint32_t p_exclude_layers) { + platform_wall_layers = p_exclude_layers; } void CharacterBody3D::set_motion_mode(MotionMode p_mode) { @@ -1877,12 +1882,12 @@ CharacterBody3D::MotionMode CharacterBody3D::get_motion_mode() const { return motion_mode; } -void CharacterBody3D::set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_apply_velocity) { - moving_platform_apply_velocity_on_leave = p_on_leave_apply_velocity; +void CharacterBody3D::set_platform_on_leave(PlatformOnLeave p_on_leave_apply_velocity) { + platform_on_leave = p_on_leave_apply_velocity; } -CharacterBody3D::MovingPlatformApplyVelocityOnLeave CharacterBody3D::get_moving_platform_apply_velocity_on_leave() const { - return moving_platform_apply_velocity_on_leave; +CharacterBody3D::PlatformOnLeave CharacterBody3D::get_platform_on_leave() const { + return platform_on_leave; } int CharacterBody3D::get_max_slides() const { @@ -1958,10 +1963,10 @@ void CharacterBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody3D::set_slide_on_ceiling_enabled); ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody3D::is_slide_on_ceiling_enabled); - ClassDB::bind_method(D_METHOD("set_moving_platform_floor_layers", "exclude_layer"), &CharacterBody3D::set_moving_platform_floor_layers); - ClassDB::bind_method(D_METHOD("get_moving_platform_floor_layers"), &CharacterBody3D::get_moving_platform_floor_layers); - ClassDB::bind_method(D_METHOD("set_moving_platform_wall_layers", "exclude_layer"), &CharacterBody3D::set_moving_platform_wall_layers); - ClassDB::bind_method(D_METHOD("get_moving_platform_wall_layers"), &CharacterBody3D::get_moving_platform_wall_layers); + ClassDB::bind_method(D_METHOD("set_platform_floor_layers", "exclude_layer"), &CharacterBody3D::set_platform_floor_layers); + ClassDB::bind_method(D_METHOD("get_platform_floor_layers"), &CharacterBody3D::get_platform_floor_layers); + ClassDB::bind_method(D_METHOD("set_platform_wall_layers", "exclude_layer"), &CharacterBody3D::set_platform_wall_layers); + ClassDB::bind_method(D_METHOD("get_platform_wall_layers"), &CharacterBody3D::get_platform_wall_layers); ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody3D::get_max_slides); ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody3D::set_max_slides); @@ -1975,8 +1980,8 @@ void CharacterBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody3D::set_up_direction); ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody3D::set_motion_mode); ClassDB::bind_method(D_METHOD("get_motion_mode"), &CharacterBody3D::get_motion_mode); - ClassDB::bind_method(D_METHOD("set_moving_platform_apply_velocity_on_leave", "on_leave_apply_velocity"), &CharacterBody3D::set_moving_platform_apply_velocity_on_leave); - ClassDB::bind_method(D_METHOD("get_moving_platform_apply_velocity_on_leave"), &CharacterBody3D::get_moving_platform_apply_velocity_on_leave); + ClassDB::bind_method(D_METHOD("set_platform_on_leave", "on_leave_apply_velocity"), &CharacterBody3D::set_platform_on_leave); + ClassDB::bind_method(D_METHOD("get_platform_on_leave"), &CharacterBody3D::get_platform_on_leave); ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody3D::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody3D::is_on_floor_only); @@ -2009,10 +2014,10 @@ void CharacterBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater,suffix:m"), "set_floor_snap_length", "get_floor_snap_length"); - ADD_GROUP("Moving Platform", "moving_platform"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_apply_velocity_on_leave", PROPERTY_HINT_ENUM, "Always,Upward Only,Never", PROPERTY_USAGE_DEFAULT), "set_moving_platform_apply_velocity_on_leave", "get_moving_platform_apply_velocity_on_leave"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_moving_platform_floor_layers", "get_moving_platform_floor_layers"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "moving_platform_wall_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_moving_platform_wall_layers", "get_moving_platform_wall_layers"); + ADD_GROUP("Moving Platform", "platform_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_on_leave", PROPERTY_HINT_ENUM, "Add Velocity,Add Upward Velocity,Do Nothing", PROPERTY_USAGE_DEFAULT), "set_platform_on_leave", "get_platform_on_leave"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_floor_layers", "get_platform_floor_layers"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_wall_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_wall_layers", "get_platform_wall_layers"); ADD_GROUP("Collision", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001,suffix:m"), "set_safe_margin", "get_safe_margin"); @@ -2020,9 +2025,9 @@ void CharacterBody3D::_bind_methods() { BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED); BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING); - BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_ALWAYS); - BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY); - BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_NEVER); + BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_VELOCITY); + BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY); + BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_DO_NOTHING); } void CharacterBody3D::_validate_property(PropertyInfo &p_property) const { @@ -2279,13 +2284,13 @@ bool PhysicalBone3D::ConeJointData::_set(const StringName &p_name, const Variant } if ("joint_constraints/swing_span" == p_name) { - swing_span = Math::deg2rad(real_t(p_value)); + swing_span = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, swing_span); } } else if ("joint_constraints/twist_span" == p_name) { - twist_span = Math::deg2rad(real_t(p_value)); + twist_span = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, twist_span); } @@ -2321,9 +2326,9 @@ bool PhysicalBone3D::ConeJointData::_get(const StringName &p_name, Variant &r_re } if ("joint_constraints/swing_span" == p_name) { - r_ret = Math::rad2deg(swing_span); + r_ret = Math::rad_to_deg(swing_span); } else if ("joint_constraints/twist_span" == p_name) { - r_ret = Math::rad2deg(twist_span); + r_ret = Math::rad_to_deg(twist_span); } else if ("joint_constraints/bias" == p_name) { r_ret = bias; } else if ("joint_constraints/softness" == p_name) { @@ -2359,13 +2364,13 @@ bool PhysicalBone3D::HingeJointData::_set(const StringName &p_name, const Varian } } else if ("joint_constraints/angular_limit_upper" == p_name) { - angular_limit_upper = Math::deg2rad(real_t(p_value)); + angular_limit_upper = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper); } } else if ("joint_constraints/angular_limit_lower" == p_name) { - angular_limit_lower = Math::deg2rad(real_t(p_value)); + angular_limit_lower = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower); } @@ -2403,9 +2408,9 @@ bool PhysicalBone3D::HingeJointData::_get(const StringName &p_name, Variant &r_r if ("joint_constraints/angular_limit_enabled" == p_name) { r_ret = angular_limit_enabled; } else if ("joint_constraints/angular_limit_upper" == p_name) { - r_ret = Math::rad2deg(angular_limit_upper); + r_ret = Math::rad_to_deg(angular_limit_upper); } else if ("joint_constraints/angular_limit_lower" == p_name) { - r_ret = Math::rad2deg(angular_limit_lower); + r_ret = Math::rad_to_deg(angular_limit_lower); } else if ("joint_constraints/angular_limit_bias" == p_name) { r_ret = angular_limit_bias; } else if ("joint_constraints/angular_limit_softness" == p_name) { @@ -2466,13 +2471,13 @@ bool PhysicalBone3D::SliderJointData::_set(const StringName &p_name, const Varia } } else if ("joint_constraints/angular_limit_upper" == p_name) { - angular_limit_upper = Math::deg2rad(real_t(p_value)); + angular_limit_upper = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper); } } else if ("joint_constraints/angular_limit_lower" == p_name) { - angular_limit_lower = Math::deg2rad(real_t(p_value)); + angular_limit_lower = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower); } @@ -2518,9 +2523,9 @@ bool PhysicalBone3D::SliderJointData::_get(const StringName &p_name, Variant &r_ } else if ("joint_constraints/linear_limit_damping" == p_name) { r_ret = linear_limit_damping; } else if ("joint_constraints/angular_limit_upper" == p_name) { - r_ret = Math::rad2deg(angular_limit_upper); + r_ret = Math::rad_to_deg(angular_limit_upper); } else if ("joint_constraints/angular_limit_lower" == p_name) { - r_ret = Math::rad2deg(angular_limit_lower); + r_ret = Math::rad_to_deg(angular_limit_lower); } else if ("joint_constraints/angular_limit_softness" == p_name) { r_ret = angular_limit_softness; } else if ("joint_constraints/angular_limit_restitution" == p_name) { @@ -2644,13 +2649,13 @@ bool PhysicalBone3D::SixDOFJointData::_set(const StringName &p_name, const Varia } } else if ("angular_limit_upper" == var_name) { - axis_data[axis].angular_limit_upper = Math::deg2rad(real_t(p_value)); + axis_data[axis].angular_limit_upper = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, axis_data[axis].angular_limit_upper); } } else if ("angular_limit_lower" == var_name) { - axis_data[axis].angular_limit_lower = Math::deg2rad(real_t(p_value)); + axis_data[axis].angular_limit_lower = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, axis_data[axis].angular_limit_lower); } @@ -2760,9 +2765,9 @@ bool PhysicalBone3D::SixDOFJointData::_get(const StringName &p_name, Variant &r_ } else if ("angular_limit_enabled" == var_name) { r_ret = axis_data[axis].angular_limit_enabled; } else if ("angular_limit_upper" == var_name) { - r_ret = Math::rad2deg(axis_data[axis].angular_limit_upper); + r_ret = Math::rad_to_deg(axis_data[axis].angular_limit_upper); } else if ("angular_limit_lower" == var_name) { - r_ret = Math::rad2deg(axis_data[axis].angular_limit_lower); + r_ret = Math::rad_to_deg(axis_data[axis].angular_limit_lower); } else if ("angular_limit_softness" == var_name) { r_ret = axis_data[axis].angular_limit_softness; } else if ("angular_restitution" == var_name) { @@ -3416,7 +3421,7 @@ void PhysicalBone3D::_start_physics_simulation() { return; } reset_to_rest_position(); - set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer3D::BODY_MODE_RIGID); PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), get_collision_priority()); diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 96e1688c23..184d8b00d0 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -129,8 +129,8 @@ private: bool is_sync_to_physics_enabled() const; }; -class RigidDynamicBody3D : public PhysicsBody3D { - GDCLASS(RigidDynamicBody3D, PhysicsBody3D); +class RigidBody3D : public PhysicsBody3D { + GDCLASS(RigidBody3D, PhysicsBody3D); public: enum FreezeMode { @@ -198,7 +198,7 @@ private: tagged = false; } }; - struct RigidDynamicBody3D_RemoveAction { + struct RigidBody3D_RemoveAction { RID rid; ObjectID body_id; ShapePair pair; @@ -300,6 +300,7 @@ public: void set_max_contacts_reported(int p_amount); int get_max_contacts_reported() const; + int get_contact_count() const; void set_use_continuous_collision_detection(bool p_enable); bool is_using_continuous_collision_detection() const; @@ -326,16 +327,16 @@ public: virtual TypedArray<String> get_configuration_warnings() const override; - RigidDynamicBody3D(); - ~RigidDynamicBody3D(); + RigidBody3D(); + ~RigidBody3D(); private: void _reload_physics_characteristics(); }; -VARIANT_ENUM_CAST(RigidDynamicBody3D::FreezeMode); -VARIANT_ENUM_CAST(RigidDynamicBody3D::CenterOfMassMode); -VARIANT_ENUM_CAST(RigidDynamicBody3D::DampMode); +VARIANT_ENUM_CAST(RigidBody3D::FreezeMode); +VARIANT_ENUM_CAST(RigidBody3D::CenterOfMassMode); +VARIANT_ENUM_CAST(RigidBody3D::DampMode); class KinematicCollision3D; @@ -347,10 +348,10 @@ public: MOTION_MODE_GROUNDED, MOTION_MODE_FLOATING, }; - enum MovingPlatformApplyVelocityOnLeave { - PLATFORM_VEL_ON_LEAVE_ALWAYS, - PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY, - PLATFORM_VEL_ON_LEAVE_NEVER, + enum PlatformOnLeave { + PLATFORM_ON_LEAVE_ADD_VELOCITY, + PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY, + PLATFORM_ON_LEAVE_DO_NOTHING, }; bool move_and_slide(); @@ -382,7 +383,7 @@ public: private: real_t margin = 0.001; MotionMode motion_mode = MOTION_MODE_GROUNDED; - MovingPlatformApplyVelocityOnLeave moving_platform_apply_velocity_on_leave = PLATFORM_VEL_ON_LEAVE_ALWAYS; + PlatformOnLeave platform_on_leave = PLATFORM_ON_LEAVE_ADD_VELOCITY; union CollisionState { uint32_t state = 0; struct { @@ -410,11 +411,11 @@ private: int platform_layer = 0; RID platform_rid; ObjectID platform_object_id; - uint32_t moving_platform_floor_layers = UINT32_MAX; - uint32_t moving_platform_wall_layers = 0; + uint32_t platform_floor_layers = UINT32_MAX; + uint32_t platform_wall_layers = 0; real_t floor_snap_length = 0.1; - real_t floor_max_angle = Math::deg2rad((real_t)45.0); - real_t wall_min_slide_angle = Math::deg2rad((real_t)15.0); + real_t floor_max_angle = Math::deg_to_rad((real_t)45.0); + real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0); Vector3 up_direction = Vector3(0.0, 1.0, 0.0); Vector3 velocity; Vector3 floor_normal; @@ -456,17 +457,17 @@ private: real_t get_wall_min_slide_angle() const; void set_wall_min_slide_angle(real_t p_radians); - uint32_t get_moving_platform_floor_layers() const; - void set_moving_platform_floor_layers(const uint32_t p_exclude_layer); + uint32_t get_platform_floor_layers() const; + void set_platform_floor_layers(const uint32_t p_exclude_layer); - uint32_t get_moving_platform_wall_layers() const; - void set_moving_platform_wall_layers(const uint32_t p_exclude_layer); + uint32_t get_platform_wall_layers() const; + void set_platform_wall_layers(const uint32_t p_exclude_layer); void set_motion_mode(MotionMode p_mode); MotionMode get_motion_mode() const; - void set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_velocity); - MovingPlatformApplyVelocityOnLeave get_moving_platform_apply_velocity_on_leave() const; + void set_platform_on_leave(PlatformOnLeave p_on_leave_velocity); + PlatformOnLeave get_platform_on_leave() const; void _move_and_slide_floating(double p_delta); void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); @@ -487,7 +488,7 @@ protected: }; VARIANT_ENUM_CAST(CharacterBody3D::MotionMode); -VARIANT_ENUM_CAST(CharacterBody3D::MovingPlatformApplyVelocityOnLeave); +VARIANT_ENUM_CAST(CharacterBody3D::PlatformOnLeave); class KinematicCollision3D : public RefCounted { GDCLASS(KinematicCollision3D, RefCounted); diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 0cd7188c23..1bc138704e 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -613,42 +613,6 @@ Vector<int> Skeleton3D::get_bone_children(int p_bone) { return bones[p_bone].child_bones; } -void Skeleton3D::set_bone_children(int p_bone, Vector<int> p_children) { - const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - bones.write[p_bone].child_bones = p_children; - - process_order_dirty = true; - rest_dirty = true; - _make_dirty(); -} - -void Skeleton3D::add_bone_child(int p_bone, int p_child) { - const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - bones.write[p_bone].child_bones.push_back(p_child); - - process_order_dirty = true; - rest_dirty = true; - _make_dirty(); -} - -void Skeleton3D::remove_bone_child(int p_bone, int p_child) { - const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - - int child_idx = bones[p_bone].child_bones.find(p_child); - if (child_idx >= 0) { - bones.write[p_bone].child_bones.remove_at(child_idx); - } else { - WARN_PRINT("Cannot remove child bone: Child bone not found."); - } - - process_order_dirty = true; - rest_dirty = true; - _make_dirty(); -} - Vector<int> Skeleton3D::get_parentless_bones() { _update_process_order(); return parentless_bones; @@ -1238,9 +1202,6 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("unparent_bone_and_rest", "bone_idx"), &Skeleton3D::unparent_bone_and_rest); ClassDB::bind_method(D_METHOD("get_bone_children", "bone_idx"), &Skeleton3D::get_bone_children); - ClassDB::bind_method(D_METHOD("set_bone_children", "bone_idx", "bone_children"), &Skeleton3D::set_bone_children); - ClassDB::bind_method(D_METHOD("add_bone_child", "bone_idx", "child_bone_idx"), &Skeleton3D::add_bone_child); - ClassDB::bind_method(D_METHOD("remove_bone_child", "bone_idx", "child_bone_idx"), &Skeleton3D::remove_bone_child); ClassDB::bind_method(D_METHOD("get_parentless_bones"), &Skeleton3D::get_parentless_bones); diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 2650d62fa4..47858b372c 100644 --- a/scene/3d/soft_dynamic_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* soft_dynamic_body_3d.cpp */ +/* soft_body_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "soft_dynamic_body_3d.h" +#include "soft_body_3d.h" #include "scene/3d/physics_body_3d.h" -SoftDynamicBodyRenderingServerHandler::SoftDynamicBodyRenderingServerHandler() {} +SoftBodyRenderingServerHandler::SoftBodyRenderingServerHandler() {} -void SoftDynamicBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { +void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { clear(); ERR_FAIL_COND(!p_mesh.is_valid()); @@ -56,7 +56,7 @@ void SoftDynamicBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { offset_normal = surface_offsets[RS::ARRAY_NORMAL]; } -void SoftDynamicBodyRenderingServerHandler::clear() { +void SoftBodyRenderingServerHandler::clear() { buffer.resize(0); stride = 0; offset_vertices = 0; @@ -66,23 +66,23 @@ void SoftDynamicBodyRenderingServerHandler::clear() { mesh = RID(); } -void SoftDynamicBodyRenderingServerHandler::open() { +void SoftBodyRenderingServerHandler::open() { write_buffer = buffer.ptrw(); } -void SoftDynamicBodyRenderingServerHandler::close() { +void SoftBodyRenderingServerHandler::close() { write_buffer = nullptr; } -void SoftDynamicBodyRenderingServerHandler::commit_changes() { +void SoftBodyRenderingServerHandler::commit_changes() { RS::get_singleton()->mesh_surface_update_vertex_region(mesh, surface, 0, buffer); } -void SoftDynamicBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { +void SoftBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { memcpy(&write_buffer[p_vertex_id * stride + offset_vertices], p_vector3, sizeof(float) * 3); } -void SoftDynamicBodyRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { +void SoftBodyRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { // Store normal vector in A2B10G10R10 format. Vector3 n; memcpy(&n, p_vector3, sizeof(Vector3)); @@ -95,28 +95,28 @@ void SoftDynamicBodyRenderingServerHandler::set_normal(int p_vertex_id, const vo memcpy(&write_buffer[p_vertex_id * stride + offset_normal], &value, sizeof(uint32_t)); } -void SoftDynamicBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) { +void SoftBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) { RS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb); } -SoftDynamicBody3D::PinnedPoint::PinnedPoint() { +SoftBody3D::PinnedPoint::PinnedPoint() { } -SoftDynamicBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { +SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { point_index = obj_tocopy.point_index; spatial_attachment_path = obj_tocopy.spatial_attachment_path; spatial_attachment = obj_tocopy.spatial_attachment; offset = obj_tocopy.offset; } -void SoftDynamicBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { +void SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { point_index = obj.point_index; spatial_attachment_path = obj.spatial_attachment_path; spatial_attachment = obj.spatial_attachment; offset = obj.offset; } -void SoftDynamicBody3D::_update_pickable() { +void SoftBody3D::_update_pickable() { if (!is_inside_tree()) { return; } @@ -124,7 +124,7 @@ void SoftDynamicBody3D::_update_pickable() { PhysicsServer3D::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable); } -bool SoftDynamicBody3D::_set(const StringName &p_name, const Variant &p_value) { +bool SoftBody3D::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; String which = name.get_slicec('/', 0); @@ -141,7 +141,7 @@ bool SoftDynamicBody3D::_set(const StringName &p_name, const Variant &p_value) { return false; } -bool SoftDynamicBody3D::_get(const StringName &p_name, Variant &r_ret) const { +bool SoftBody3D::_get(const StringName &p_name, Variant &r_ret) const { String name = p_name; String which = name.get_slicec('/', 0); @@ -168,7 +168,7 @@ bool SoftDynamicBody3D::_get(const StringName &p_name, Variant &r_ret) const { return false; } -void SoftDynamicBody3D::_get_property_list(List<PropertyInfo> *p_list) const { +void SoftBody3D::_get_property_list(List<PropertyInfo> *p_list) const { const int pinned_points_indices_size = pinned_points.size(); p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, PNAME("pinned_points"))); @@ -181,7 +181,7 @@ void SoftDynamicBody3D::_get_property_list(List<PropertyInfo> *p_list) const { } } -bool SoftDynamicBody3D::_set_property_pinned_points_indices(const Array &p_indices) { +bool SoftBody3D::_set_property_pinned_points_indices(const Array &p_indices) { const int p_indices_size = p_indices.size(); { // Remove the pined points on physics server that will be removed by resize @@ -210,7 +210,7 @@ bool SoftDynamicBody3D::_set_property_pinned_points_indices(const Array &p_indic return true; } -bool SoftDynamicBody3D::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) { +bool SoftBody3D::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) { if (pinned_points.size() <= p_item) { return false; } @@ -229,7 +229,7 @@ bool SoftDynamicBody3D::_set_property_pinned_points_attachment(int p_item, const return true; } -bool SoftDynamicBody3D::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const { +bool SoftBody3D::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const { if (pinned_points.size() <= p_item) { return false; } @@ -248,7 +248,7 @@ bool SoftDynamicBody3D::_get_property_pinned_points(int p_item, const String &p_ return true; } -void SoftDynamicBody3D::_notification(int p_what) { +void SoftBody3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_WORLD: { if (Engine::get_singleton()->is_editor_hint()) { @@ -313,56 +313,56 @@ void SoftDynamicBody3D::_notification(int p_what) { } } -void SoftDynamicBody3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftDynamicBody3D::get_physics_rid); +void SoftBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftBody3D::get_physics_rid); - ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftDynamicBody3D::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftDynamicBody3D::get_collision_mask); + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody3D::get_collision_mask); - ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &SoftDynamicBody3D::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &SoftDynamicBody3D::get_collision_layer); + ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &SoftBody3D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &SoftBody3D::get_collision_layer); - ClassDB::bind_method(D_METHOD("set_collision_mask_value", "layer_number", "value"), &SoftDynamicBody3D::set_collision_mask_value); - ClassDB::bind_method(D_METHOD("get_collision_mask_value", "layer_number"), &SoftDynamicBody3D::get_collision_mask_value); + ClassDB::bind_method(D_METHOD("set_collision_mask_value", "layer_number", "value"), &SoftBody3D::set_collision_mask_value); + ClassDB::bind_method(D_METHOD("get_collision_mask_value", "layer_number"), &SoftBody3D::get_collision_mask_value); - ClassDB::bind_method(D_METHOD("set_collision_layer_value", "layer_number", "value"), &SoftDynamicBody3D::set_collision_layer_value); - ClassDB::bind_method(D_METHOD("get_collision_layer_value", "layer_number"), &SoftDynamicBody3D::get_collision_layer_value); + ClassDB::bind_method(D_METHOD("set_collision_layer_value", "layer_number", "value"), &SoftBody3D::set_collision_layer_value); + ClassDB::bind_method(D_METHOD("get_collision_layer_value", "layer_number"), &SoftBody3D::get_collision_layer_value); - ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftDynamicBody3D::set_parent_collision_ignore); - ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftDynamicBody3D::get_parent_collision_ignore); + ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody3D::set_parent_collision_ignore); + ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody3D::get_parent_collision_ignore); - ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &SoftDynamicBody3D::set_disable_mode); - ClassDB::bind_method(D_METHOD("get_disable_mode"), &SoftDynamicBody3D::get_disable_mode); + ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &SoftBody3D::set_disable_mode); + ClassDB::bind_method(D_METHOD("get_disable_mode"), &SoftBody3D::get_disable_mode); - ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftDynamicBody3D::get_collision_exceptions); - ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftDynamicBody3D::add_collision_exception_with); - ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftDynamicBody3D::remove_collision_exception_with); + ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody3D::get_collision_exceptions); + ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody3D::add_collision_exception_with); + ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody3D::remove_collision_exception_with); - ClassDB::bind_method(D_METHOD("set_simulation_precision", "simulation_precision"), &SoftDynamicBody3D::set_simulation_precision); - ClassDB::bind_method(D_METHOD("get_simulation_precision"), &SoftDynamicBody3D::get_simulation_precision); + ClassDB::bind_method(D_METHOD("set_simulation_precision", "simulation_precision"), &SoftBody3D::set_simulation_precision); + ClassDB::bind_method(D_METHOD("get_simulation_precision"), &SoftBody3D::get_simulation_precision); - ClassDB::bind_method(D_METHOD("set_total_mass", "mass"), &SoftDynamicBody3D::set_total_mass); - ClassDB::bind_method(D_METHOD("get_total_mass"), &SoftDynamicBody3D::get_total_mass); + ClassDB::bind_method(D_METHOD("set_total_mass", "mass"), &SoftBody3D::set_total_mass); + ClassDB::bind_method(D_METHOD("get_total_mass"), &SoftBody3D::get_total_mass); - ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftDynamicBody3D::set_linear_stiffness); - ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftDynamicBody3D::get_linear_stiffness); + ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody3D::set_linear_stiffness); + ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody3D::get_linear_stiffness); - ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftDynamicBody3D::set_pressure_coefficient); - ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftDynamicBody3D::get_pressure_coefficient); + ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody3D::set_pressure_coefficient); + ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody3D::get_pressure_coefficient); - ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftDynamicBody3D::set_damping_coefficient); - ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftDynamicBody3D::get_damping_coefficient); + ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody3D::set_damping_coefficient); + ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody3D::get_damping_coefficient); - ClassDB::bind_method(D_METHOD("set_drag_coefficient", "drag_coefficient"), &SoftDynamicBody3D::set_drag_coefficient); - ClassDB::bind_method(D_METHOD("get_drag_coefficient"), &SoftDynamicBody3D::get_drag_coefficient); + ClassDB::bind_method(D_METHOD("set_drag_coefficient", "drag_coefficient"), &SoftBody3D::set_drag_coefficient); + ClassDB::bind_method(D_METHOD("get_drag_coefficient"), &SoftBody3D::get_drag_coefficient); - ClassDB::bind_method(D_METHOD("get_point_transform", "point_index"), &SoftDynamicBody3D::get_point_transform); + ClassDB::bind_method(D_METHOD("get_point_transform", "point_index"), &SoftBody3D::get_point_transform); - ClassDB::bind_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path"), &SoftDynamicBody3D::pin_point, DEFVAL(NodePath())); - ClassDB::bind_method(D_METHOD("is_point_pinned", "point_index"), &SoftDynamicBody3D::is_point_pinned); + ClassDB::bind_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path"), &SoftBody3D::pin_point, DEFVAL(NodePath())); + ClassDB::bind_method(D_METHOD("is_point_pinned", "point_index"), &SoftBody3D::is_point_pinned); - ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftDynamicBody3D::set_ray_pickable); - ClassDB::bind_method(D_METHOD("is_ray_pickable"), &SoftDynamicBody3D::is_ray_pickable); + ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftBody3D::set_ray_pickable); + ClassDB::bind_method(D_METHOD("is_ray_pickable"), &SoftBody3D::is_ray_pickable); ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); @@ -384,7 +384,7 @@ void SoftDynamicBody3D::_bind_methods() { BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE); } -TypedArray<String> SoftDynamicBody3D::get_configuration_warnings() const { +TypedArray<String> SoftBody3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (mesh.is_null()) { @@ -393,13 +393,13 @@ TypedArray<String> SoftDynamicBody3D::get_configuration_warnings() const { Transform3D t = get_transform(); if ((ABS(t.basis.get_column(0).length() - 1.0) > 0.05 || ABS(t.basis.get_column(1).length() - 1.0) > 0.05 || ABS(t.basis.get_column(2).length() - 1.0) > 0.05)) { - warnings.push_back(RTR("Size changes to SoftDynamicBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); + warnings.push_back(RTR("Size changes to SoftBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } return warnings; } -void SoftDynamicBody3D::_update_physics_server() { +void SoftBody3D::_update_physics_server() { if (!simulation_started) { return; } @@ -415,7 +415,7 @@ void SoftDynamicBody3D::_update_physics_server() { } } -void SoftDynamicBody3D::_draw_soft_mesh() { +void SoftBody3D::_draw_soft_mesh() { if (mesh.is_null()) { return; } @@ -445,7 +445,7 @@ void SoftDynamicBody3D::_draw_soft_mesh() { rendering_server_handler->commit_changes(); } -void SoftDynamicBody3D::_prepare_physics_server() { +void SoftBody3D::_prepare_physics_server() { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { if (mesh.is_valid()) { @@ -465,22 +465,22 @@ void SoftDynamicBody3D::_prepare_physics_server() { mesh_rid = mesh->get_rid(); } PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid); - RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftDynamicBody3D::_draw_soft_mesh)); + RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); } else { PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, RID()); - if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftDynamicBody3D::_draw_soft_mesh))) { - RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftDynamicBody3D::_draw_soft_mesh)); + if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh))) { + RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); } } } -void SoftDynamicBody3D::_become_mesh_owner() { +void SoftBody3D::_become_mesh_owner() { Vector<Ref<Material>> copy_materials; copy_materials.append_array(surface_override_materials); ERR_FAIL_COND(!mesh->get_surface_count()); - // Get current mesh array and create new mesh array with necessary flag for SoftDynamicBody + // Get current mesh array and create new mesh array with necessary flag for SoftBody Array surface_arrays = mesh->surface_get_arrays(0); Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0); Dictionary surface_lods = mesh->surface_get_lods(0); @@ -502,25 +502,25 @@ void SoftDynamicBody3D::_become_mesh_owner() { owned_mesh = soft_mesh->get_rid(); } -void SoftDynamicBody3D::set_collision_mask(uint32_t p_mask) { +void SoftBody3D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; PhysicsServer3D::get_singleton()->soft_body_set_collision_mask(physics_rid, p_mask); } -uint32_t SoftDynamicBody3D::get_collision_mask() const { +uint32_t SoftBody3D::get_collision_mask() const { return collision_mask; } -void SoftDynamicBody3D::set_collision_layer(uint32_t p_layer) { +void SoftBody3D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; PhysicsServer3D::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer); } -uint32_t SoftDynamicBody3D::get_collision_layer() const { +uint32_t SoftBody3D::get_collision_layer() const { return collision_layer; } -void SoftDynamicBody3D::set_collision_layer_value(int p_layer_number, bool p_value) { +void SoftBody3D::set_collision_layer_value(int p_layer_number, bool p_value) { ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive."); uint32_t collision_layer = get_collision_layer(); @@ -532,13 +532,13 @@ void SoftDynamicBody3D::set_collision_layer_value(int p_layer_number, bool p_val set_collision_layer(collision_layer); } -bool SoftDynamicBody3D::get_collision_layer_value(int p_layer_number) const { +bool SoftBody3D::get_collision_layer_value(int p_layer_number) const { ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive."); return get_collision_layer() & (1 << (p_layer_number - 1)); } -void SoftDynamicBody3D::set_collision_mask_value(int p_layer_number, bool p_value) { +void SoftBody3D::set_collision_mask_value(int p_layer_number, bool p_value) { ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive."); uint32_t mask = get_collision_mask(); @@ -550,13 +550,13 @@ void SoftDynamicBody3D::set_collision_mask_value(int p_layer_number, bool p_valu set_collision_mask(mask); } -bool SoftDynamicBody3D::get_collision_mask_value(int p_layer_number) const { +bool SoftBody3D::get_collision_mask_value(int p_layer_number) const { ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive."); return get_collision_mask() & (1 << (p_layer_number - 1)); } -void SoftDynamicBody3D::set_disable_mode(DisableMode p_mode) { +void SoftBody3D::set_disable_mode(DisableMode p_mode) { if (disable_mode == p_mode) { return; } @@ -568,30 +568,30 @@ void SoftDynamicBody3D::set_disable_mode(DisableMode p_mode) { } } -SoftDynamicBody3D::DisableMode SoftDynamicBody3D::get_disable_mode() const { +SoftBody3D::DisableMode SoftBody3D::get_disable_mode() const { return disable_mode; } -void SoftDynamicBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) { +void SoftBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) { parent_collision_ignore = p_parent_collision_ignore; } -const NodePath &SoftDynamicBody3D::get_parent_collision_ignore() const { +const NodePath &SoftBody3D::get_parent_collision_ignore() const { return parent_collision_ignore; } -void SoftDynamicBody3D::set_pinned_points_indices(Vector<SoftDynamicBody3D::PinnedPoint> p_pinned_points_indices) { +void SoftBody3D::set_pinned_points_indices(Vector<SoftBody3D::PinnedPoint> p_pinned_points_indices) { pinned_points = p_pinned_points_indices; for (int i = pinned_points.size() - 1; 0 <= i; --i) { pin_point(p_pinned_points_indices[i].point_index, true); } } -Vector<SoftDynamicBody3D::PinnedPoint> SoftDynamicBody3D::get_pinned_points_indices() { +Vector<SoftBody3D::PinnedPoint> SoftBody3D::get_pinned_points_indices() { return pinned_points; } -TypedArray<PhysicsBody3D> SoftDynamicBody3D::get_collision_exceptions() { +TypedArray<PhysicsBody3D> SoftBody3D::get_collision_exceptions() { List<RID> exceptions; PhysicsServer3D::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions); TypedArray<PhysicsBody3D> ret; @@ -604,77 +604,77 @@ TypedArray<PhysicsBody3D> SoftDynamicBody3D::get_collision_exceptions() { return ret; } -void SoftDynamicBody3D::add_collision_exception_with(Node *p_node) { +void SoftBody3D::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node); ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds."); PhysicsServer3D::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid()); } -void SoftDynamicBody3D::remove_collision_exception_with(Node *p_node) { +void SoftBody3D::remove_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node); ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds."); PhysicsServer3D::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid()); } -int SoftDynamicBody3D::get_simulation_precision() { +int SoftBody3D::get_simulation_precision() { return PhysicsServer3D::get_singleton()->soft_body_get_simulation_precision(physics_rid); } -void SoftDynamicBody3D::set_simulation_precision(int p_simulation_precision) { +void SoftBody3D::set_simulation_precision(int p_simulation_precision) { PhysicsServer3D::get_singleton()->soft_body_set_simulation_precision(physics_rid, p_simulation_precision); } -real_t SoftDynamicBody3D::get_total_mass() { +real_t SoftBody3D::get_total_mass() { return PhysicsServer3D::get_singleton()->soft_body_get_total_mass(physics_rid); } -void SoftDynamicBody3D::set_total_mass(real_t p_total_mass) { +void SoftBody3D::set_total_mass(real_t p_total_mass) { PhysicsServer3D::get_singleton()->soft_body_set_total_mass(physics_rid, p_total_mass); } -void SoftDynamicBody3D::set_linear_stiffness(real_t p_linear_stiffness) { +void SoftBody3D::set_linear_stiffness(real_t p_linear_stiffness) { PhysicsServer3D::get_singleton()->soft_body_set_linear_stiffness(physics_rid, p_linear_stiffness); } -real_t SoftDynamicBody3D::get_linear_stiffness() { +real_t SoftBody3D::get_linear_stiffness() { return PhysicsServer3D::get_singleton()->soft_body_get_linear_stiffness(physics_rid); } -real_t SoftDynamicBody3D::get_pressure_coefficient() { +real_t SoftBody3D::get_pressure_coefficient() { return PhysicsServer3D::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); } -void SoftDynamicBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) { +void SoftBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) { PhysicsServer3D::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); } -real_t SoftDynamicBody3D::get_damping_coefficient() { +real_t SoftBody3D::get_damping_coefficient() { return PhysicsServer3D::get_singleton()->soft_body_get_damping_coefficient(physics_rid); } -void SoftDynamicBody3D::set_damping_coefficient(real_t p_damping_coefficient) { +void SoftBody3D::set_damping_coefficient(real_t p_damping_coefficient) { PhysicsServer3D::get_singleton()->soft_body_set_damping_coefficient(physics_rid, p_damping_coefficient); } -real_t SoftDynamicBody3D::get_drag_coefficient() { +real_t SoftBody3D::get_drag_coefficient() { return PhysicsServer3D::get_singleton()->soft_body_get_drag_coefficient(physics_rid); } -void SoftDynamicBody3D::set_drag_coefficient(real_t p_drag_coefficient) { +void SoftBody3D::set_drag_coefficient(real_t p_drag_coefficient) { PhysicsServer3D::get_singleton()->soft_body_set_drag_coefficient(physics_rid, p_drag_coefficient); } -Vector3 SoftDynamicBody3D::get_point_transform(int p_point_index) { +Vector3 SoftBody3D::get_point_transform(int p_point_index) { return PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, p_point_index); } -void SoftDynamicBody3D::pin_point_toggle(int p_point_index) { +void SoftBody3D::pin_point_toggle(int p_point_index) { pin_point(p_point_index, !(-1 != _has_pinned_point(p_point_index))); } -void SoftDynamicBody3D::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) { +void SoftBody3D::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) { _pin_point_on_physics_server(p_point_index, pin); if (pin) { _add_pinned_point(p_point_index, p_spatial_attachment_path); @@ -683,35 +683,35 @@ void SoftDynamicBody3D::pin_point(int p_point_index, bool pin, const NodePath &p } } -bool SoftDynamicBody3D::is_point_pinned(int p_point_index) const { +bool SoftBody3D::is_point_pinned(int p_point_index) const { return -1 != _has_pinned_point(p_point_index); } -void SoftDynamicBody3D::set_ray_pickable(bool p_ray_pickable) { +void SoftBody3D::set_ray_pickable(bool p_ray_pickable) { ray_pickable = p_ray_pickable; _update_pickable(); } -bool SoftDynamicBody3D::is_ray_pickable() const { +bool SoftBody3D::is_ray_pickable() const { return ray_pickable; } -SoftDynamicBody3D::SoftDynamicBody3D() : +SoftBody3D::SoftBody3D() : physics_rid(PhysicsServer3D::get_singleton()->soft_body_create()) { - rendering_server_handler = memnew(SoftDynamicBodyRenderingServerHandler); + rendering_server_handler = memnew(SoftBodyRenderingServerHandler); PhysicsServer3D::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); } -SoftDynamicBody3D::~SoftDynamicBody3D() { +SoftBody3D::~SoftBody3D() { memdelete(rendering_server_handler); PhysicsServer3D::get_singleton()->free(physics_rid); } -void SoftDynamicBody3D::_make_cache_dirty() { +void SoftBody3D::_make_cache_dirty() { pinned_points_cache_dirty = true; } -void SoftDynamicBody3D::_update_cache_pin_points_datas() { +void SoftBody3D::_update_cache_pin_points_datas() { if (!pinned_points_cache_dirty) { return; } @@ -724,17 +724,17 @@ void SoftDynamicBody3D::_update_cache_pin_points_datas() { w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(w[i].spatial_attachment_path)); } if (!w[i].spatial_attachment) { - ERR_PRINT("Node3D node not defined in the pinned point, this is undefined behavior for SoftDynamicBody3D!"); + ERR_PRINT("Node3D node not defined in the pinned point, this is undefined behavior for SoftBody3D!"); } } } -void SoftDynamicBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) { +void SoftBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) { PhysicsServer3D::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin); } -void SoftDynamicBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) { - SoftDynamicBody3D::PinnedPoint *pinned_point; +void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) { + SoftBody3D::PinnedPoint *pinned_point; if (-1 == _get_pinned_point(p_point_index, pinned_point)) { // Create new PinnedPoint pp; @@ -759,7 +759,7 @@ void SoftDynamicBody3D::_add_pinned_point(int p_point_index, const NodePath &p_s } } -void SoftDynamicBody3D::_reset_points_offsets() { +void SoftBody3D::_reset_points_offsets() { if (!Engine::get_singleton()->is_editor_hint()) { return; } @@ -781,25 +781,25 @@ void SoftDynamicBody3D::_reset_points_offsets() { } } -void SoftDynamicBody3D::_remove_pinned_point(int p_point_index) { +void SoftBody3D::_remove_pinned_point(int p_point_index) { const int id(_has_pinned_point(p_point_index)); if (-1 != id) { pinned_points.remove_at(id); } } -int SoftDynamicBody3D::_get_pinned_point(int p_point_index, SoftDynamicBody3D::PinnedPoint *&r_point) const { +int SoftBody3D::_get_pinned_point(int p_point_index, SoftBody3D::PinnedPoint *&r_point) const { const int id = _has_pinned_point(p_point_index); if (-1 == id) { r_point = nullptr; return -1; } else { - r_point = const_cast<SoftDynamicBody3D::PinnedPoint *>(&pinned_points.ptr()[id]); + r_point = const_cast<SoftBody3D::PinnedPoint *>(&pinned_points.ptr()[id]); return id; } } -int SoftDynamicBody3D::_has_pinned_point(int p_point_index) const { +int SoftBody3D::_has_pinned_point(int p_point_index) const { const PinnedPoint *r = pinned_points.ptr(); for (int i = pinned_points.size() - 1; 0 <= i; --i) { if (p_point_index == r[i].point_index) { diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_body_3d.h index 2b86fe2cae..40f3d6f1f4 100644 --- a/scene/3d/soft_dynamic_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* soft_dynamic_body_3d.h */ +/* soft_body_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,17 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SOFT_DYNAMIC_BODY_3D_H -#define SOFT_DYNAMIC_BODY_3D_H +#ifndef SOFT_BODY_3D_H +#define SOFT_BODY_3D_H #include "scene/3d/mesh_instance_3d.h" #include "servers/physics_server_3d.h" class PhysicsBody3D; -class SoftDynamicBody3D; +class SoftBody3D; -class SoftDynamicBodyRenderingServerHandler : public PhysicsServer3DRenderingServerHandler { - friend class SoftDynamicBody3D; +class SoftBodyRenderingServerHandler : public PhysicsServer3DRenderingServerHandler { + friend class SoftBody3D; RID mesh; int surface = 0; @@ -50,7 +50,7 @@ class SoftDynamicBodyRenderingServerHandler : public PhysicsServer3DRenderingSer uint8_t *write_buffer = nullptr; private: - SoftDynamicBodyRenderingServerHandler(); + SoftBodyRenderingServerHandler(); bool is_ready(RID p_mesh_rid) const { return mesh.is_valid() && mesh == p_mesh_rid; } void prepare(RID p_mesh_rid, int p_surface); void clear(); @@ -64,8 +64,8 @@ public: void set_aabb(const AABB &p_aabb) override; }; -class SoftDynamicBody3D : public MeshInstance3D { - GDCLASS(SoftDynamicBody3D, MeshInstance3D); +class SoftBody3D : public MeshInstance3D { + GDCLASS(SoftBody3D, MeshInstance3D); public: enum DisableMode { @@ -85,7 +85,7 @@ public: }; private: - SoftDynamicBodyRenderingServerHandler *rendering_server_handler = nullptr; + SoftBodyRenderingServerHandler *rendering_server_handler = nullptr; RID physics_rid; @@ -182,8 +182,8 @@ public: void set_ray_pickable(bool p_ray_pickable); bool is_ray_pickable() const; - SoftDynamicBody3D(); - ~SoftDynamicBody3D(); + SoftBody3D(); + ~SoftBody3D(); private: void _make_cache_dirty(); @@ -198,6 +198,6 @@ private: int _has_pinned_point(int p_point_index) const; }; -VARIANT_ENUM_CAST(SoftDynamicBody3D::DisableMode); +VARIANT_ENUM_CAST(SoftBody3D::DisableMode); -#endif // SOFT_DYNAMIC_BODY_3D_H +#endif // SOFT_BODY_3D_H diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 212d220ace..669c3eb7fd 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -1004,14 +1004,17 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &p_property) const { names.sort_custom<StringName::AlphCompare>(); bool current_found = false; + bool is_first_element = true; - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - if (E->prev()) { + for (const StringName &E : names) { + if (!is_first_element) { p_property.hint_string += ","; + } else { + is_first_element = false; } - p_property.hint_string += String(E->get()); - if (animation == E->get()) { + p_property.hint_string += String(E); + if (animation == E) { current_found = true; } } diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 42ed52c9f2..d61b49eaa7 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -807,7 +807,7 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) { } void VehicleBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { - RigidDynamicBody3D::_body_state_changed(p_state); + RigidBody3D::_body_state_changed(p_state); real_t step = p_state->get_step(); diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h index 2f3a37af2a..5c4f4beaea 100644 --- a/scene/3d/vehicle_body_3d.h +++ b/scene/3d/vehicle_body_3d.h @@ -152,8 +152,8 @@ public: VehicleWheel3D(); }; -class VehicleBody3D : public RigidDynamicBody3D { - GDCLASS(VehicleBody3D, RigidDynamicBody3D); +class VehicleBody3D : public RigidBody3D { + GDCLASS(VehicleBody3D, RigidBody3D); real_t engine_force = 0.0; real_t brake = 0.0; diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 4b3d7fd0a6..afb52de307 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -403,7 +403,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s bool do_start = (p_seek && p_time == 0) || play_start || current == StringName(); if (do_start) { - if (p_state_machine->start_node != StringName() && p_seek && p_time == 0) { + if (p_state_machine->start_node != StringName() && p_seek && p_time == 0 && current == StringName()) { current = p_state_machine->start_node; } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 48626ccc1b..0e2598cbc7 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -1151,7 +1151,7 @@ void AnimationPlayer::_animation_update_transforms() { } #endif - static_cast<Node2D *>(pa->object)->set_rotation(Math::deg2rad((double)pa->value_accum)); + static_cast<Node2D *>(pa->object)->set_rotation(Math::deg_to_rad((double)pa->value_accum)); } break; case SP_NODE2D_SCALE: { #ifdef DEBUG_ENABLED diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 7dbe892299..d06324f0aa 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -602,6 +602,8 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_value->object = child; } + track_value->is_using_angle = anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; + track_value->subpath = leftover_path; track_value->object_id = track_value->object->get_instance_id(); @@ -804,6 +806,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { default: { } } + } else if (track_cache_type == Animation::TYPE_VALUE) { + // If it has at least one angle interpolation, it also uses angle interpolation for blending. + TrackCacheValue *track_value = memnew(TrackCacheValue); + track_value->is_using_angle |= anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; } track->setup_pass = setup_pass; @@ -1353,8 +1359,28 @@ void AnimationTree::_process_graph(double p_delta) { t->value = t->init_value; } - Variant::sub(value, t->init_value, value); - Variant::blend(t->value, value, blend, t->value); + // Special case for angle interpolation. + if (t->is_using_angle) { + // For blending consistency, it prevents rotation of more than 180 degrees from init_value. + // This is the same as for Quaternion blends. + float rot_a = t->value; + float rot_b = value; + float rot_init = t->init_value; + rot_a = Math::fposmod(rot_a, (float)Math_TAU); + rot_b = Math::fposmod(rot_b, (float)Math_TAU); + rot_init = Math::fposmod(rot_init, (float)Math_TAU); + if (rot_init < Math_PI) { + rot_a = rot_a > rot_init + Math_PI ? rot_a - Math_TAU : rot_a; + rot_b = rot_b > rot_init + Math_PI ? rot_b - Math_TAU : rot_b; + } else { + rot_a = rot_a < rot_init - Math_PI ? rot_a + Math_TAU : rot_a; + rot_b = rot_b < rot_init - Math_PI ? rot_b + Math_TAU : rot_b; + } + t->value = Math::fposmod(rot_a + (rot_b - rot_init) * (float)blend, (float)Math_TAU); + } else { + Variant::sub(value, t->init_value, value); + Variant::blend(t->value, value, blend, t->value); + } } else { if (blend < CMP_EPSILON) { continue; //nothing to blend @@ -1528,7 +1554,7 @@ void AnimationTree::_process_graph(double p_delta) { } } - real_t db = Math::linear2db(MAX(blend, 0.00001)); + real_t db = Math::linear_to_db(MAX(blend, 0.00001)); if (t->object->has_method(SNAME("set_unit_db"))) { t->object->call(SNAME("set_unit_db"), db); } else { diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index ee51a54557..ee0c0303dc 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -233,6 +233,7 @@ private: Variant init_value; Variant value; Vector<StringName> subpath; + bool is_using_angle = false; TrackCacheValue() { type = Animation::TYPE_VALUE; } }; diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index 7c85b650bf..04feb0dc6f 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -256,7 +256,7 @@ Vector<AudioFrame> AudioStreamPlayer::_get_volume_vector() { channel_volume_db = AudioFrame(0, 0); } - float volume_linear = Math::db2linear(volume_db); + float volume_linear = Math::db_to_linear(volume_db); // Set the volume vector up according to the speaker mode and mix target. // TODO do we need to scale the volume down when we output to more channels? diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 66cb41ee65..9b6a19c50a 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -252,36 +252,36 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { if (name.begins_with("theme_override_icons/")) { String dname = name.get_slicec('/', 1); if (data.icon_override.has(dname)) { - data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.icon_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_styles/")) { String dname = name.get_slicec('/', 1); if (data.style_override.has(dname)) { - data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.style_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_fonts/")) { String dname = name.get_slicec('/', 1); if (data.font_override.has(dname)) { - data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.font_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_font_sizes/")) { String dname = name.get_slicec('/', 1); data.font_size_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_colors/")) { String dname = name.get_slicec('/', 1); data.color_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_constants/")) { String dname = name.get_slicec('/', 1); data.constant_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else { return false; } @@ -2260,62 +2260,62 @@ bool Control::is_clipping_contents() { // Theming. -void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) { +void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_notify, bool p_assign) { Control *c = Object::cast_to<Control>(p_at); - - if (c && c != p_owner && c->data.theme.is_valid()) { // has a theme, this can't be propagated - return; - } - Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr; - if (w && w != p_owner_window && w->theme.is_valid()) { // has a theme, this can't be propagated + if (!c && !w) { + // Theme inheritance chains are broken by nodes that aren't Control or Window. return; } - for (int i = 0; i < p_at->get_child_count(); i++) { - CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i)); - if (child) { - _propagate_theme_changed(child, p_owner, p_owner_window, p_assign); - } else { - Window *window = Object::cast_to<Window>(p_at->get_child(i)); - if (window) { - _propagate_theme_changed(window, p_owner, p_owner_window, p_assign); - } + bool assign = p_assign; + if (c) { + if (c != p_owner && c->data.theme.is_valid()) { + // Has a theme, so we don't want to change the theme owner, + // but we still want to propagate in case this child has theme items + // it inherits from the theme this node uses. + // See https://github.com/godotengine/godot/issues/62844. + assign = false; } - } - if (c) { - if (p_assign) { + if (assign) { c->data.theme_owner = p_owner; c->data.theme_owner_window = p_owner_window; } - c->notification(Control::NOTIFICATION_THEME_CHANGED); - c->emit_signal(SceneStringNames::get_singleton()->theme_changed); - } - if (w) { - if (p_assign) { + if (p_notify) { + c->notification(Control::NOTIFICATION_THEME_CHANGED); + } + } else if (w) { + if (w != p_owner_window && w->theme.is_valid()) { + // Same as above. + assign = false; + } + + if (assign) { w->theme_owner = p_owner; w->theme_owner_window = p_owner_window; } - w->notification(Window::NOTIFICATION_THEME_CHANGED); - w->emit_signal(SceneStringNames::get_singleton()->theme_changed); + + if (p_notify) { + w->notification(Window::NOTIFICATION_THEME_CHANGED); + } } -} -void Control::_theme_changed() { - _propagate_theme_changed(this, this, nullptr, false); + for (int i = 0; i < p_at->get_child_count(); i++) { + _propagate_theme_changed(p_at->get_child(i), p_owner, p_owner_window, p_notify, assign); + } } -void Control::_theme_property_override_changed() { - notification(NOTIFICATION_THEME_CHANGED); - emit_signal(SceneStringNames::get_singleton()->theme_changed); - update_minimum_size(); // Overrides are likely to affect minimum size. +void Control::_theme_changed() { + if (is_inside_tree()) { + _propagate_theme_changed(this, this, nullptr, true, false); + } } -void Control::_notify_theme_changed() { - if (!data.bulk_theme_override) { +void Control::_notify_theme_override_changed() { + if (!data.bulk_theme_override && is_inside_tree()) { notification(NOTIFICATION_THEME_CHANGED); } } @@ -2339,28 +2339,25 @@ void Control::set_theme(const Ref<Theme> &p_theme) { } data.theme = p_theme; - if (!p_theme.is_null()) { - data.theme_owner = this; - data.theme_owner_window = nullptr; - _propagate_theme_changed(this, this, nullptr); - } else { - Control *parent_c = Object::cast_to<Control>(get_parent()); + if (data.theme.is_valid()) { + _propagate_theme_changed(this, this, nullptr, is_inside_tree(), true); + data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), CONNECT_DEFERRED); + return; + } - if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); - } else { - Window *parent_w = cast_to<Window>(get_parent()); - if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); - } else { - Control::_propagate_theme_changed(this, nullptr, nullptr); - } - } + Control *parent_c = Object::cast_to<Control>(get_parent()); + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + _propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window, is_inside_tree(), true); + return; } - if (data.theme.is_valid()) { - data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), CONNECT_DEFERRED); + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + _propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window, is_inside_tree(), true); + return; } + + _propagate_theme_changed(this, nullptr, nullptr, is_inside_tree(), true); } Ref<Theme> Control::get_theme() const { @@ -2372,7 +2369,9 @@ void Control::set_theme_type_variation(const StringName &p_theme_type) { return; } data.theme_type_variation = p_theme_type; - _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window); + if (is_inside_tree()) { + notification(NOTIFICATION_THEME_CHANGED); + } } StringName Control::get_theme_type_variation() const { @@ -2697,93 +2696,93 @@ void Control::add_theme_icon_override(const StringName &p_name, const Ref<Textur ERR_FAIL_COND(!p_icon.is_valid()); if (data.icon_override.has(p_name)) { - data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.icon_override[p_name] = p_icon; - data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); + data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); } void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { ERR_FAIL_COND(!p_style.is_valid()); if (data.style_override.has(p_name)) { - data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.style_override[p_name] = p_style; - data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); + data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); } void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) { ERR_FAIL_COND(!p_font.is_valid()); if (data.font_override.has(p_name)) { - data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.font_override[p_name] = p_font; - data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); + data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); } void Control::add_theme_font_size_override(const StringName &p_name, int p_font_size) { data.font_size_override[p_name] = p_font_size; - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) { data.color_override[p_name] = p_color; - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::add_theme_constant_override(const StringName &p_name, int p_constant) { data.constant_override[p_name] = p_constant; - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_icon_override(const StringName &p_name) { if (data.icon_override.has(p_name)) { - data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.icon_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_style_override(const StringName &p_name) { if (data.style_override.has(p_name)) { - data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.style_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_font_override(const StringName &p_name) { if (data.font_override.has(p_name)) { - data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.font_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_font_size_override(const StringName &p_name) { data.font_size_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_color_override(const StringName &p_name) { data.color_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_constant_override(const StringName &p_name) { data.constant_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } bool Control::has_theme_icon_override(const StringName &p_name) const { @@ -2981,7 +2980,7 @@ void Control::end_bulk_theme_override() { ERR_FAIL_COND(!data.bulk_theme_override); data.bulk_theme_override = false; - _notify_theme_changed(); + _notify_theme_override_changed(); } // Internationalization. @@ -3087,37 +3086,26 @@ Control *Control::make_custom_tooltip(const String &p_text) const { // Base object overrides. void Control::add_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) { - _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff - } - - Window *child_w = Object::cast_to<Window>(p_child); - - if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) { - _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff + // We propagate when this node uses a custom theme, so it can pass it on to its children. + if (data.theme_owner || data.theme_owner_window) { + // `p_notify` is false here as `NOTIFICATION_THEME_CHANGED` will be handled by `NOTIFICATION_ENTER_TREE`. + _propagate_theme_changed(p_child, data.theme_owner, data.theme_owner_window, false, true); } } void Control::remove_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { - _propagate_theme_changed(child_c, nullptr, nullptr); - } - - Window *child_w = Object::cast_to<Window>(p_child); - - if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { - _propagate_theme_changed(child_w, nullptr, nullptr); + // If the removed child isn't inheriting any theme items through this node, then there's no need to propagate. + if (data.theme_owner || data.theme_owner_window) { + _propagate_theme_changed(p_child, nullptr, nullptr, false, true); } } void Control::_notification(int p_notification) { switch (p_notification) { case NOTIFICATION_ENTER_TREE: { - _invalidate_theme_cache(); + // Need to defer here, because theme owner information might be set in + // add_child_notify, which doesn't get called until right after this. + call_deferred(SNAME("notification"), NOTIFICATION_THEME_CHANGED); } break; case NOTIFICATION_POST_ENTER_TREE: { @@ -3142,18 +3130,6 @@ void Control::_notification(int p_notification) { data.parent_window = Object::cast_to<Window>(get_parent()); data.is_rtl_dirty = true; - if (data.theme.is_null()) { - if (data.parent && (data.parent->data.theme_owner || data.parent->data.theme_owner_window)) { - data.theme_owner = data.parent->data.theme_owner; - data.theme_owner_window = data.parent->data.theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } else if (data.parent_window && (data.parent_window->theme_owner || data.parent_window->theme_owner_window)) { - data.theme_owner = data.parent_window->theme_owner; - data.theme_owner_window = data.parent_window->theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } - } - CanvasItem *node = this; bool has_parent_control = false; @@ -3257,6 +3233,7 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_THEME_CHANGED: { + emit_signal(SceneStringNames::get_singleton()->theme_changed); _invalidate_theme_cache(); update_minimum_size(); update(); @@ -3622,3 +3599,24 @@ void Control::_bind_methods() { GDVIRTUAL_BIND(_gui_input, "event"); } + +Control::~Control() { + // Resources need to be disconnected. + for (KeyValue<StringName, Ref<Texture2D>> &E : data.icon_override) { + E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); + } + for (KeyValue<StringName, Ref<StyleBox>> &E : data.style_override) { + E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); + } + for (KeyValue<StringName, Ref<Font>> &E : data.font_override) { + E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); + } + + // Then override maps can be simply cleared. + data.icon_override.clear(); + data.style_override.clear(); + data.font_override.clear(); + data.font_size_override.clear(); + data.color_override.clear(); + data.constant_override.clear(); +} diff --git a/scene/gui/control.h b/scene/gui/control.h index d7e120260c..82d3d8d24a 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -300,11 +300,10 @@ private: // Theming. void _theme_changed(); - void _theme_property_override_changed(); - void _notify_theme_changed(); + void _notify_theme_override_changed(); void _invalidate_theme_cache(); - static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true); + static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_notify, bool p_assign); template <class T> static T get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types); @@ -610,6 +609,7 @@ public: virtual Control *make_custom_tooltip(const String &p_text) const; Control() {} + ~Control(); }; VARIANT_ENUM_CAST(Control::FocusMode); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 22ad7850ad..b07d401e6b 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -32,9 +32,7 @@ #include "core/string/translation.h" -#ifdef TOOLS_ENABLED #include "graph_edit.h" -#endif struct _MinSizeCache { int min_size; @@ -445,6 +443,7 @@ void GraphNode::_edit_set_position(const Point2 &p_position) { } set_position(p_position); } +#endif void GraphNode::_validate_property(PropertyInfo &p_property) const { GraphEdit *graph = Object::cast_to<GraphEdit>(get_parent()); @@ -454,7 +453,6 @@ void GraphNode::_validate_property(PropertyInfo &p_property) const { } } } -#endif void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right, bool p_draw_stylebox) { ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set slot with p_idx (%d) lesser than zero.", p_idx)); diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index c02eb30696..9c8f926403 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -103,7 +103,6 @@ private: #ifdef TOOLS_ENABLED void _edit_set_position(const Point2 &p_position) override; - void _validate_property(PropertyInfo &p_property) const; #endif protected: @@ -114,6 +113,7 @@ protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; + void _validate_property(PropertyInfo &p_property) const; public: bool has_point(const Point2 &p_point) const override; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 7a88afaa3b..b15578f222 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -279,8 +279,8 @@ void Label::_notification(int p_what) { return; // Nothing new. } xl_text = new_text; - if (percent_visible < 1) { - visible_chars = get_total_character_count() * percent_visible; + if (visible_ratio < 1) { + visible_chars = get_total_character_count() * visible_ratio; } dirty = true; @@ -348,7 +348,7 @@ void Label::_notification(int p_what) { total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; total_glyphs += TS->shaped_text_get_glyph_count(lines_rid[i]) + TS->shaped_text_get_ellipsis_glyph_count(lines_rid[i]); } - int visible_glyphs = total_glyphs * percent_visible; + int visible_glyphs = total_glyphs * visible_ratio; int processed_glyphs = 0; total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); @@ -652,8 +652,8 @@ void Label::set_text(const String &p_string) { text = p_string; xl_text = atr(p_string); dirty = true; - if (percent_visible < 1) { - visible_chars = get_total_character_count() * percent_visible; + if (visible_ratio < 1) { + visible_chars = get_total_character_count() * visible_ratio; } update(); update_minimum_size(); @@ -771,9 +771,9 @@ void Label::set_visible_characters(int p_amount) { if (visible_chars != p_amount) { visible_chars = p_amount; if (get_total_character_count() > 0) { - percent_visible = (float)p_amount / (float)get_total_character_count(); + visible_ratio = (float)p_amount / (float)get_total_character_count(); } else { - percent_visible = 1.0; + visible_ratio = 1.0; } if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { dirty = true; @@ -786,17 +786,17 @@ int Label::get_visible_characters() const { return visible_chars; } -void Label::set_percent_visible(float p_percent) { - if (percent_visible != p_percent) { - if (percent_visible >= 1.0) { +void Label::set_visible_ratio(float p_ratio) { + if (visible_ratio != p_ratio) { + if (visible_ratio >= 1.0) { visible_chars = -1; - percent_visible = 1.0; - } else if (percent_visible < 0.0) { + visible_ratio = 1.0; + } else if (visible_ratio < 0.0) { visible_chars = 0; - percent_visible = 0.0; + visible_ratio = 0.0; } else { - visible_chars = get_total_character_count() * p_percent; - percent_visible = p_percent; + visible_chars = get_total_character_count() * p_ratio; + visible_ratio = p_ratio; } if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { @@ -806,8 +806,8 @@ void Label::set_percent_visible(float p_percent) { } } -float Label::get_percent_visible() const { - return percent_visible; +float Label::get_visible_ratio() const { + return visible_ratio; } TextServer::VisibleCharactersBehavior Label::get_visible_characters_behavior() const { @@ -889,8 +889,8 @@ void Label::_bind_methods() { ClassDB::bind_method(D_METHOD("get_visible_characters"), &Label::get_visible_characters); ClassDB::bind_method(D_METHOD("get_visible_characters_behavior"), &Label::get_visible_characters_behavior); ClassDB::bind_method(D_METHOD("set_visible_characters_behavior", "behavior"), &Label::set_visible_characters_behavior); - ClassDB::bind_method(D_METHOD("set_percent_visible", "percent_visible"), &Label::set_percent_visible); - ClassDB::bind_method(D_METHOD("get_percent_visible"), &Label::get_percent_visible); + ClassDB::bind_method(D_METHOD("set_visible_ratio", "ratio"), &Label::set_visible_ratio); + ClassDB::bind_method(D_METHOD("get_visible_ratio"), &Label::get_visible_ratio); ClassDB::bind_method(D_METHOD("set_lines_skipped", "lines_skipped"), &Label::set_lines_skipped); ClassDB::bind_method(D_METHOD("get_lines_skipped"), &Label::get_lines_skipped); ClassDB::bind_method(D_METHOD("set_max_lines_visible", "lines_visible"), &Label::set_max_lines_visible); @@ -911,10 +911,10 @@ void Label::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE, "-1,999,1"), "set_max_lines_visible", "get_max_lines_visible"); - // Note: "visible_characters" and "percent_visible" should be set after "text" to be correctly applied. + // Note: "visible_characters" and "visible_ratio" should be set after "text" to be correctly applied. ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visible_ratio", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_visible_ratio", "get_visible_ratio"); ADD_GROUP("BiDi", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); diff --git a/scene/gui/label.h b/scene/gui/label.h index cab5b36d68..65831cab6e 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -59,10 +59,9 @@ private: TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; Array st_args; - float percent_visible = 1.0; - TextServer::VisibleCharactersBehavior visible_chars_behavior = TextServer::VC_CHARS_BEFORE_SHAPING; int visible_chars = -1; + float visible_ratio = 1.0; int lines_skipped = 0; int max_lines_visible = -1; @@ -110,22 +109,22 @@ public: void set_uppercase(bool p_uppercase); bool is_uppercase() const; - TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const; void set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior); + TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const; void set_visible_characters(int p_amount); int get_visible_characters() const; int get_total_character_count() const; + void set_visible_ratio(float p_ratio); + float get_visible_ratio() const; + void set_clip_text(bool p_clip); bool is_clipping_text() const; void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior); TextServer::OverrunBehavior get_text_overrun_behavior() const; - void set_percent_visible(float p_percent); - float get_percent_visible() const; - void set_lines_skipped(int p_lines); int get_lines_skipped() const; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index cc39b0e57a..34a60b907c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -718,7 +718,7 @@ void LineEdit::_notification(int p_what) { case NOTIFICATION_RESIZED: { _fit_to_width(); - scroll_offset = 0; + scroll_offset = 0.0; set_caret_column(get_caret_column()); } break; @@ -801,7 +801,7 @@ void LineEdit::_notification(int p_what) { } } break; case HORIZONTAL_ALIGNMENT_CENTER: { - if (scroll_offset != 0) { + if (!Math::is_zero_approx(scroll_offset)) { x_ofs = style->get_offset().x; } else { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(size.width - (text_width)) / 2); @@ -846,7 +846,7 @@ void LineEdit::_notification(int p_what) { r_icon->draw(ci, Point2(width - r_icon->get_width() - style->get_margin(SIDE_RIGHT), height / 2 - r_icon->get_height() / 2), color_icon); if (alignment == HORIZONTAL_ALIGNMENT_CENTER) { - if (scroll_offset == 0) { + if (Math::is_zero_approx(scroll_offset)) { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(size.width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2); } } else { @@ -1208,7 +1208,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) { } } break; case HORIZONTAL_ALIGNMENT_CENTER: { - if (scroll_offset != 0) { + if (!Math::is_zero_approx(scroll_offset)) { x_ofs = style->get_offset().x; } else { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - (text_width)) / 2); @@ -1228,7 +1228,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) { if (right_icon.is_valid() || display_clear_icon) { Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon; if (alignment == HORIZONTAL_ALIGNMENT_CENTER) { - if (scroll_offset == 0) { + if (Math::is_zero_approx(scroll_offset)) { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2); } } else { @@ -1236,11 +1236,11 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) { } } - int ofs = TS->shaped_text_hit_test_position(text_rid, p_x - x_ofs - scroll_offset); + int ofs = ceil(TS->shaped_text_hit_test_position(text_rid, p_x - x_ofs - scroll_offset)); set_caret_column(ofs); } -Vector2i LineEdit::get_caret_pixel_pos() { +Vector2 LineEdit::get_caret_pixel_pos() { Ref<StyleBox> style = get_theme_stylebox(SNAME("normal")); bool rtl = is_layout_rtl(); @@ -1256,7 +1256,7 @@ Vector2i LineEdit::get_caret_pixel_pos() { } } break; case HORIZONTAL_ALIGNMENT_CENTER: { - if (scroll_offset != 0) { + if (!Math::is_zero_approx(scroll_offset)) { x_ofs = style->get_offset().x; } else { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - (text_width)) / 2); @@ -1276,7 +1276,7 @@ Vector2i LineEdit::get_caret_pixel_pos() { if (right_icon.is_valid() || display_clear_icon) { Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon; if (alignment == HORIZONTAL_ALIGNMENT_CENTER) { - if (scroll_offset == 0) { + if (Math::is_zero_approx(scroll_offset)) { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2); } } else { @@ -1284,7 +1284,7 @@ Vector2i LineEdit::get_caret_pixel_pos() { } } - Vector2i ret; + Vector2 ret; CaretInfo caret; // Get position of the start of caret. if (ime_text.length() != 0 && ime_selection.x != 0) { @@ -1427,7 +1427,7 @@ void LineEdit::set_text(String p_text) { update(); caret_column = 0; - scroll_offset = 0; + scroll_offset = 0.0; } void LineEdit::set_text_direction(Control::TextDirection p_text_direction) { @@ -1555,7 +1555,7 @@ void LineEdit::set_caret_column(int p_column) { // Fit to window. if (!is_inside_tree()) { - scroll_offset = 0; + scroll_offset = 0.0; return; } @@ -1574,7 +1574,7 @@ void LineEdit::set_caret_column(int p_column) { } } break; case HORIZONTAL_ALIGNMENT_CENTER: { - if (scroll_offset != 0) { + if (!Math::is_zero_approx(scroll_offset)) { x_ofs = style->get_offset().x; } else { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - (text_width)) / 2); @@ -1595,7 +1595,7 @@ void LineEdit::set_caret_column(int p_column) { if (right_icon.is_valid() || display_clear_icon) { Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon; if (alignment == HORIZONTAL_ALIGNMENT_CENTER) { - if (scroll_offset == 0) { + if (Math::is_zero_approx(scroll_offset)) { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2); } } else { @@ -1605,12 +1605,12 @@ void LineEdit::set_caret_column(int p_column) { } // Note: Use two coordinates to fit IME input range. - Vector2i primary_catret_offset = get_caret_pixel_pos(); + Vector2 primary_caret_offset = get_caret_pixel_pos(); - if (MIN(primary_catret_offset.x, primary_catret_offset.y) <= x_ofs) { - scroll_offset += (x_ofs - MIN(primary_catret_offset.x, primary_catret_offset.y)); - } else if (MAX(primary_catret_offset.x, primary_catret_offset.y) >= ofs_max) { - scroll_offset += (ofs_max - MAX(primary_catret_offset.x, primary_catret_offset.y)); + if (MIN(primary_caret_offset.x, primary_caret_offset.y) <= x_ofs) { + scroll_offset += x_ofs - MIN(primary_caret_offset.x, primary_caret_offset.y); + } else if (MAX(primary_caret_offset.x, primary_caret_offset.y) >= ofs_max) { + scroll_offset += ofs_max - MAX(primary_caret_offset.x, primary_caret_offset.y); } scroll_offset = MIN(0, scroll_offset); @@ -1621,14 +1621,14 @@ int LineEdit::get_caret_column() const { return caret_column; } -void LineEdit::set_scroll_offset(int p_pos) { +void LineEdit::set_scroll_offset(float p_pos) { scroll_offset = p_pos; - if (scroll_offset < 0) { - scroll_offset = 0; + if (scroll_offset < 0.0) { + scroll_offset = 0.0; } } -int LineEdit::get_scroll_offset() const { +float LineEdit::get_scroll_offset() const { return scroll_offset; } @@ -1656,7 +1656,7 @@ void LineEdit::clear_internal() { deselect(); _clear_undo_stack(); caret_column = 0; - scroll_offset = 0; + scroll_offset = 0.0; undo_text = ""; text = ""; _shape(); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 254f842b66..dabdaa3395 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -113,7 +113,7 @@ private: bool caret_mid_grapheme_enabled = true; int caret_column = 0; - int scroll_offset = 0; + float scroll_offset = 0.0; int max_length = 0; // 0 for no maximum. String language; @@ -153,8 +153,7 @@ private: struct TextOperation { int caret_column = 0; - int scroll_offset = 0; - int cached_width = 0; + float scroll_offset = 0.0; String text; }; List<TextOperation> undo_stack; @@ -192,11 +191,11 @@ private: void shift_selection_check_post(bool); void selection_fill_at_caret(); - void set_scroll_offset(int p_pos); - int get_scroll_offset() const; + void set_scroll_offset(float p_pos); + float get_scroll_offset() const; void set_caret_at_pixel_pos(int p_x); - Vector2i get_caret_pixel_pos(); + Vector2 get_caret_pixel_pos(); void _reset_caret_blink_timer(); void _toggle_draw_caret(); diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp index f450222130..9eba2feaf7 100644 --- a/scene/gui/menu_bar.cpp +++ b/scene/gui/menu_bar.cpp @@ -276,10 +276,7 @@ void MenuBar::_update_submenu(const String &p_menu_name, PopupMenu *p_child) { } bool MenuBar::is_native_menu() const { - if (!is_visible_in_tree()) { - return false; - } - if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root()->is_ancestor_of(this) || get_tree()->get_edited_scene_root() == this)) { + if (Engine::get_singleton()->is_editor_hint() && is_inside_tree() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root()->is_ancestor_of(this) || get_tree()->get_edited_scene_root() == this)) { return false; } @@ -308,7 +305,7 @@ void MenuBar::_clear_menu() { void MenuBar::_update_menu() { _clear_menu(); - if (!is_inside_tree()) { + if (!is_visible_in_tree()) { return; } diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index a03db82332..e6e17cc881 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -86,6 +86,11 @@ void MenuButton::_popup_visibility_changed(bool p_visible) { } void MenuButton::pressed() { + if (popup->is_visible()) { + popup->hide(); + return; + } + emit_signal(SNAME("about_to_popup")); Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); @@ -103,11 +108,7 @@ void MenuButton::pressed() { popup->set_current_index(0); } - if (popup->is_visible()) { - popup->hide(); - } else { - popup->popup(); - } + popup->popup(); } void MenuButton::gui_input(const Ref<InputEvent> &p_event) { diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 931dffe3bb..881acdbf3a 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -198,6 +198,11 @@ void OptionButton::_selected(int p_which) { } void OptionButton::pressed() { + if (popup->is_visible()) { + popup->hide(); + return; + } + Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); popup->set_size(Size2(size.width, 0)); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 6ab3cdcb69..3f1f16cd51 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -742,7 +742,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o bool trim_glyphs_ltr = (visible_characters >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_LTR) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && !lrtl)); bool trim_glyphs_rtl = (visible_characters >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_RTL) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && lrtl)); int total_glyphs = (trim_glyphs_ltr || trim_glyphs_rtl) ? get_total_glyph_count() : 0; - int visible_glyphs = total_glyphs * percent_visible; + int visible_glyphs = total_glyphs * visible_ratio; Vector<int> list_index; Vector<ItemList *> list_items; @@ -4940,19 +4940,19 @@ TextServer::AutowrapMode RichTextLabel::get_autowrap_mode() const { return autowrap_mode; } -void RichTextLabel::set_percent_visible(float p_percent) { - if (percent_visible != p_percent) { +void RichTextLabel::set_visible_ratio(float p_ratio) { + if (visible_ratio != p_ratio) { _stop_thread(); - if (percent_visible >= 1.0) { + if (visible_ratio >= 1.0) { visible_characters = -1; - percent_visible = 1.0; - } else if (percent_visible < 0.0) { + visible_ratio = 1.0; + } else if (visible_ratio < 0.0) { visible_characters = 0; - percent_visible = 0.0; + visible_ratio = 0.0; } else { - visible_characters = get_total_character_count() * p_percent; - percent_visible = p_percent; + visible_characters = get_total_character_count() * p_ratio; + visible_ratio = p_ratio; } if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { @@ -4963,8 +4963,8 @@ void RichTextLabel::set_percent_visible(float p_percent) { } } -float RichTextLabel::get_percent_visible() const { - return percent_visible; +float RichTextLabel::get_visible_ratio() const { + return visible_ratio; } void RichTextLabel::set_effects(Array p_effects) { @@ -5139,8 +5139,8 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_visible_characters_behavior"), &RichTextLabel::get_visible_characters_behavior); ClassDB::bind_method(D_METHOD("set_visible_characters_behavior", "behavior"), &RichTextLabel::set_visible_characters_behavior); - ClassDB::bind_method(D_METHOD("set_percent_visible", "percent_visible"), &RichTextLabel::set_percent_visible); - ClassDB::bind_method(D_METHOD("get_percent_visible"), &RichTextLabel::get_percent_visible); + ClassDB::bind_method(D_METHOD("set_visible_ratio", "ratio"), &RichTextLabel::set_visible_ratio); + ClassDB::bind_method(D_METHOD("get_visible_ratio"), &RichTextLabel::get_visible_ratio); ClassDB::bind_method(D_METHOD("get_character_line", "character"), &RichTextLabel::get_character_line); ClassDB::bind_method(D_METHOD("get_character_paragraph", "character"), &RichTextLabel::get_character_paragraph); @@ -5189,10 +5189,10 @@ void RichTextLabel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hint_underlined"), "set_hint_underline", "is_hint_underlined"); ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); - // Note: "visible_characters" and "percent_visible" should be set after "text" to be correctly applied. + // Note: "visible_characters" and "visible_ratio" should be set after "text" to be correctly applied. ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visible_ratio", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_visible_ratio", "get_visible_ratio"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled"); @@ -5264,11 +5264,11 @@ void RichTextLabel::set_visible_characters(int p_visible) { visible_characters = p_visible; if (p_visible == -1) { - percent_visible = 1; + visible_ratio = 1; } else { int total_char_count = get_total_character_count(); if (total_char_count > 0) { - percent_visible = (float)p_visible / (float)total_char_count; + visible_ratio = (float)p_visible / (float)total_char_count; } } if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 95e55bf1a1..79f9c62539 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -440,7 +440,7 @@ private: void _menu_option(int p_option); int visible_characters = -1; - float percent_visible = 1.0; + float visible_ratio = 1.0; TextServer::VisibleCharactersBehavior visible_chars_behavior = TextServer::VC_CHARS_BEFORE_SHAPING; bool _is_click_inside_selection() const; @@ -660,8 +660,8 @@ public: int get_total_character_count() const; int get_total_glyph_count() const; - void set_percent_visible(float p_percent); - float get_percent_visible() const; + void set_visible_ratio(float p_ratio); + float get_visible_ratio() const; TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const; void set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior); diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 517c83545c..65c4a09c84 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -41,12 +41,16 @@ Size2 SpinBox::get_minimum_size() const { void SpinBox::_value_changed(double p_value) { String value = TS->format_number(String::num(get_value(), Math::range_step_decimals(get_step()))); - if (!prefix.is_empty()) { - value = prefix + " " + value; - } - if (!suffix.is_empty()) { - value += " " + suffix; + + if (!line_edit->has_focus()) { + if (!prefix.is_empty()) { + value = prefix + " " + value; + } + if (!suffix.is_empty()) { + value += " " + suffix; + } } + line_edit->set_text(value); Range::_value_changed(p_value); } @@ -105,8 +109,9 @@ void SpinBox::_range_click_timeout() { void SpinBox::_release_mouse() { if (drag.enabled) { drag.enabled = false; - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_HIDDEN); warp_mouse(drag.capture_pos); + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); } } @@ -181,8 +186,14 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { } } +void SpinBox::_line_edit_focus_enter() { + int col = line_edit->get_caret_column(); + _value_changed(0); // Update the LineEdit's text. + line_edit->set_caret_column(col); +} + void SpinBox::_line_edit_focus_exit() { - // discontinue because the focus_exit was caused by right-click context menu + // Discontinue because the focus_exit was caused by right-click context menu. if (line_edit->is_menu_visible()) { return; } @@ -346,6 +357,7 @@ SpinBox::SpinBox() { line_edit->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT); line_edit->connect("text_submitted", callable_mp(this, &SpinBox::_text_submitted), CONNECT_DEFERRED); + line_edit->connect("focus_entered", callable_mp(this, &SpinBox::_line_edit_focus_enter), CONNECT_DEFERRED); line_edit->connect("focus_exited", callable_mp(this, &SpinBox::_line_edit_focus_exit), CONNECT_DEFERRED); line_edit->connect("gui_input", callable_mp(this, &SpinBox::_line_edit_input)); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 0aae9efe78..3fcb85ac99 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -64,6 +64,7 @@ class SpinBox : public Range { double diff_y = 0.0; } drag; + void _line_edit_focus_enter(); void _line_edit_focus_exit(); inline void _adjust_width_for_icon(const Ref<Texture2D> &icon); diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index b6073ce265..3e60db0846 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -97,16 +97,12 @@ void SplitContainer::_resort() { // Compute the final middle separation. middle_sep = no_offset_middle_sep; - if (prev_no_offset_middle_sep != INT_MAX) { - split_offset -= middle_sep - prev_no_offset_middle_sep; - } - prev_no_offset_middle_sep = middle_sep; - if (!collapsed) { int clamped_split_offset = CLAMP(split_offset, ms_first[axis] - no_offset_middle_sep, (get_size()[axis] - ms_second[axis] - sep) - no_offset_middle_sep); middle_sep += clamped_split_offset; if (should_clamp_split_offset) { split_offset = clamped_split_offset; + should_clamp_split_offset = false; } } diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index dd15362199..a69ffe4de9 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -47,7 +47,6 @@ private: bool should_clamp_split_offset = false; int split_offset = 0; int middle_sep = 0; - int prev_no_offset_middle_sep = INT_MAX; bool vertical = false; bool dragging = false; int drag_from = 0; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 4a3a35383e..2b19ee4d0b 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -3718,12 +3718,17 @@ bool Tree::edit_selected() { } else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE) { Rect2 popup_rect; - Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2); + Vector2 ofs(0, Math::floor((text_editor->get_size().height - rect.size.height) / 2)); // "floor()" centers vertically. Point2i textedpos = get_screen_position() + rect.position - ofs; cache.text_editor_position = textedpos; popup_rect.position = textedpos; popup_rect.size = rect.size; + + // Account for icon. + popup_rect.position.x += c.get_icon_size().x; + popup_rect.size.x -= c.get_icon_size().x; + text_editor->clear(); text_editor->set_text(c.mode == TreeItem::CELL_MODE_STRING ? c.text : String::num(c.val, Math::range_step_decimals(c.step))); text_editor->select_all(); diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 7baa4d44aa..4024d4c80e 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -362,7 +362,7 @@ void VideoStreamPlayer::set_volume_db(float p_db) { if (p_db < -79) { set_volume(0); } else { - set_volume(Math::db2linear(p_db)); + set_volume(Math::db_to_linear(p_db)); } } @@ -370,7 +370,7 @@ float VideoStreamPlayer::get_volume_db() const { if (volume == 0) { return -80; } else { - return Math::linear2db(volume); + return Math::linear_to_db(volume); } } diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index dcf506aafa..515f4d88a6 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -587,6 +587,12 @@ void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range); } +void CanvasItem::draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate) { + ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL_COND(p_texture.is_null()); + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate); +} + void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -919,6 +925,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0)); + ClassDB::bind_method(D_METHOD("draw_lcd_texture_rect_region", "texture", "rect", "src_rect", "modulate"), &CanvasItem::draw_lcd_texture_rect_region, DEFVAL(Color(1, 1, 1, 1))); ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box); ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>())); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 38e0be1683..1e0d4552ce 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -226,6 +226,7 @@ public: void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0); + void draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)); void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect); void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), real_t p_width = 1); void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>()); diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 8f40f257f9..4890db995a 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -335,7 +335,7 @@ void CanvasLayer::_bind_methods() { ADD_GROUP("", ""); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport"); ADD_GROUP("Follow Viewport", "follow_viewport"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_viewport_enable"), "set_follow_viewport", "is_following_viewport"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_viewport_enabled"), "set_follow_viewport", "is_following_viewport"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "follow_viewport_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001,or_greater,or_lesser"), "set_follow_viewport_scale", "get_follow_viewport_scale"); ADD_SIGNAL(MethodInfo("visibility_changed")); diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp index 95574042a8..2d2103f031 100644 --- a/scene/main/multiplayer_api.cpp +++ b/scene/main/multiplayer_api.cpp @@ -59,18 +59,18 @@ Ref<MultiplayerAPI> MultiplayerAPI::create_default_interface() { // The variant is compressed and encoded; The first byte contains all the meta // information and the format is: -// - The first LSB 5 bits are used for the variant type. +// - The first LSB 6 bits are used for the variant type. // - The next two bits are used to store the encoding mode. -// - The most significant is used to store the boolean value. -#define VARIANT_META_TYPE_MASK 0x1F -#define VARIANT_META_EMODE_MASK 0x60 +// - Boolean values uses the encoding mode to store the value. +#define VARIANT_META_TYPE_MASK 0x3F +#define VARIANT_META_EMODE_MASK 0xC0 #define VARIANT_META_BOOL_MASK 0x80 -#define ENCODE_8 0 << 5 -#define ENCODE_16 1 << 5 -#define ENCODE_32 2 << 5 -#define ENCODE_64 3 << 5 +#define ENCODE_8 0 << 6 +#define ENCODE_16 1 << 6 +#define ENCODE_32 2 << 6 +#define ENCODE_64 3 << 6 Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) { - // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31 + // Unreachable because `VARIANT_MAX` == 38 and `ENCODE_VARIANT_MASK` == 77 CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK); uint8_t *buf = r_buffer; @@ -80,9 +80,9 @@ Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint switch (p_variant.get_type()) { case Variant::BOOL: { if (buf) { - // We still have 1 free bit in the meta, so let's use it. + // We don't use encode_mode for booleans, so we can use it to store the value. buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0; - buf[0] |= encode_mode | p_variant.get_type(); + buf[0] |= p_variant.get_type(); } r_len += 1; } break; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 9773218574..cc3d14e5be 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -948,6 +948,21 @@ String Node::validate_child_name(Node *p_child) { } #endif +String Node::adjust_name_casing(const String &p_name) { + switch (GLOBAL_GET("editor/node_naming/name_casing").operator int()) { + case NAME_CASING_PASCAL_CASE: + return p_name.capitalize().replace(" ", ""); + case NAME_CASING_CAMEL_CASE: { + String name = p_name.capitalize().replace(" ", ""); + name[0] = name.to_lower()[0]; + return name; + } + case NAME_CASING_SNAKE_CASE: + return p_name.capitalize().replace(" ", "_").to_lower(); + } + return p_name; +} + void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) { /* Make sure the name is unique */ @@ -1021,19 +1036,8 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co //no name and a new name is needed, create one. name = p_child->get_class(); - // Adjust casing according to project setting. The current type name is expected to be in PascalCase. - switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_casing").operator int()) { - case NAME_CASING_PASCAL_CASE: - break; - case NAME_CASING_CAMEL_CASE: { - String n = name; - n[0] = n.to_lower()[0]; - name = n; - } break; - case NAME_CASING_SNAKE_CASE: - name = String(name).camelcase_to_underscore(true); - break; - } + // Adjust casing according to project setting. + name = adjust_name_casing(name); } //quickly test if proposed name exists diff --git a/scene/main/node.h b/scene/main/node.h index 52ccf3d825..703c580d3f 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -459,6 +459,7 @@ public: #ifdef TOOLS_ENABLED String validate_child_name(Node *p_child); #endif + static String adjust_name_casing(const String &p_name); void queue_delete(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 764fc60bc1..a5a4e29186 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -798,6 +798,7 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, RS::get_singleton()->viewport_set_size(viewport, 0, 0); } _update_global_transform(); + update_configuration_warnings(); update_canvas_items(); @@ -1103,7 +1104,7 @@ Vector2 Viewport::get_mouse_position() const { void Viewport::warp_mouse(const Vector2 &p_position) { Transform2D xform = get_screen_transform(); - Vector2 gpos = xform.xform(p_position).round(); + Vector2 gpos = xform.xform(p_position); Input::get_singleton()->warp_mouse(gpos); } @@ -1708,15 +1709,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { is_tooltip_shown = true; } } else { - Variant t = gui.tooltip_popup->call("get_tooltip_text"); - - if (t.get_type() == Variant::STRING) { - if (tooltip == String(t)) { - is_tooltip_shown = true; - } - } else { - is_tooltip_shown = true; // Nothing to compare against, likely using custom control, so if it changes there is nothing we can do. - } + is_tooltip_shown = true; // Nothing to compare against, likely using custom control, so if it changes there is nothing we can do. } } else { _gui_cancel_tooltip(); @@ -2853,8 +2846,8 @@ Variant Viewport::gui_get_drag_data() const { TypedArray<String> Viewport::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); - if (size.x == 0 || size.y == 0) { - warnings.push_back(RTR("Viewport size must be greater than 0 to render anything.")); + if (size.x <= 1 || size.y <= 1) { + warnings.push_back(RTR("The Viewport size must be greater than or equal to 2 pixels on both dimensions to render anything.")); } return warnings; } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index a0ec2d54dd..83083cd65a 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -563,7 +563,7 @@ public: bool is_input_disabled() const; Vector2 get_mouse_position() const; - void warp_mouse(const Vector2 &p_position); + virtual void warp_mouse(const Vector2 &p_position); void set_physics_object_picking(bool p_enable); bool get_physics_object_picking(); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index bf50ca0956..1b7aa787e7 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -848,21 +848,13 @@ void Window::_notification(int p_what) { RS::get_singleton()->viewport_set_active(get_viewport_rid(), true); } - if (theme.is_null()) { - Control *parent_c = cast_to<Control>(get_parent()); - if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { - theme_owner = parent_c->data.theme_owner; - theme_owner_window = parent_c->data.theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } else { - Window *parent_w = cast_to<Window>(get_parent()); - if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { - theme_owner = parent_w->theme_owner; - theme_owner_window = parent_w->theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } - } - } + // Need to defer here, because theme owner information might be set in + // add_child_notify, which doesn't get called until right after this. + call_deferred(SNAME("notification"), NOTIFICATION_THEME_CHANGED); + } break; + + case NOTIFICATION_THEME_CHANGED: { + emit_signal(SceneStringNames::get_singleton()->theme_changed); } break; case NOTIFICATION_READY: { @@ -974,6 +966,18 @@ DisplayServer::WindowID Window::get_window_id() const { return window_id; } +void Window::warp_mouse(const Vector2 &p_position) { + Transform2D xform = get_screen_transform(); + Vector2 gpos = xform.xform(p_position); + + if (transient_parent && !transient_parent->is_embedding_subwindows()) { + Transform2D window_trans = Transform2D().translated(get_position() + (transient_parent->get_visible_rect().size - transient_parent->get_real_size())); + gpos = window_trans.xform(gpos); + } + + Input::get_singleton()->warp_mouse(gpos); +} + void Window::set_wrap_controls(bool p_enable) { wrap_controls = p_enable; if (wrap_controls) { @@ -1250,16 +1254,10 @@ Rect2i Window::get_usable_parent_rect() const { } void Window::add_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && child_c->data.theme.is_null() && (theme_owner || theme_owner_window)) { - Control::_propagate_theme_changed(child_c, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff - } - - Window *child_w = Object::cast_to<Window>(p_child); - - if (child_w && child_w->theme.is_null() && (theme_owner || theme_owner_window)) { - Control::_propagate_theme_changed(child_w, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff + // We propagate when this node uses a custom theme, so it can pass it on to its children. + if (theme_owner || theme_owner_window) { + // `p_notify` is false here as `NOTIFICATION_THEME_CHANGED` will be handled by `NOTIFICATION_ENTER_TREE`. + Control::_propagate_theme_changed(this, theme_owner, theme_owner_window, false, true); } if (is_inside_tree() && wrap_controls) { @@ -1268,16 +1266,9 @@ void Window::add_child_notify(Node *p_child) { } void Window::remove_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { - Control::_propagate_theme_changed(child_c, nullptr, nullptr); - } - - Window *child_w = Object::cast_to<Window>(p_child); - - if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { - Control::_propagate_theme_changed(child_w, nullptr, nullptr); + // If the removed child isn't inheriting any theme items through this node, then there's no need to propagate. + if (theme_owner || theme_owner_window) { + Control::_propagate_theme_changed(this, nullptr, nullptr, false, true); } if (is_inside_tree() && wrap_controls) { @@ -1290,34 +1281,47 @@ void Window::set_theme(const Ref<Theme> &p_theme) { return; } + if (theme.is_valid()) { + theme->disconnect("changed", callable_mp(this, &Window::_theme_changed)); + } + theme = p_theme; + if (theme.is_valid()) { + Control::_propagate_theme_changed(this, nullptr, this, is_inside_tree(), true); + theme->connect("changed", callable_mp(this, &Window::_theme_changed), CONNECT_DEFERRED); + return; + } - if (!p_theme.is_null()) { - theme_owner = nullptr; - theme_owner_window = this; - Control::_propagate_theme_changed(this, nullptr, this); - } else { - Control *parent_c = cast_to<Control>(get_parent()); - if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); - } else { - Window *parent_w = cast_to<Window>(get_parent()); - if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); - } else { - Control::_propagate_theme_changed(this, nullptr, nullptr); - } - } + Control *parent_c = Object::cast_to<Control>(get_parent()); + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window, is_inside_tree(), true); + return; } + + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window, is_inside_tree(), true); + return; + } + + Control::_propagate_theme_changed(this, nullptr, nullptr, is_inside_tree(), true); } Ref<Theme> Window::get_theme() const { return theme; } +void Window::_theme_changed() { + if (is_inside_tree()) { + Control::_propagate_theme_changed(this, nullptr, this, true, false); + } +} + void Window::set_theme_type_variation(const StringName &p_theme_type) { theme_type_variation = p_theme_type; - Control::_propagate_theme_changed(this, theme_owner, theme_owner_window); + if (is_inside_tree()) { + notification(NOTIFICATION_THEME_CHANGED); + } } StringName Window::get_theme_type_variation() const { @@ -1681,6 +1685,7 @@ void Window::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_flag", "get_flag", FLAG_TRANSPARENT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unfocusable"), "set_flag", "get_flag", FLAG_NO_FOCUS); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "popup_window"), "set_flag", "get_flag", FLAG_POPUP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "extend_to_title"), "set_flag", "get_flag", FLAG_EXTEND_TO_TITLE); ADD_GROUP("Limits", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "min_size", PROPERTY_HINT_NONE, "suffix:px"), "set_min_size", "get_min_size"); @@ -1712,6 +1717,7 @@ void Window::_bind_methods() { ADD_SIGNAL(MethodInfo("theme_changed")); BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); + BIND_CONSTANT(NOTIFICATION_THEME_CHANGED); BIND_ENUM_CONSTANT(MODE_WINDOWED); BIND_ENUM_CONSTANT(MODE_MINIMIZED); @@ -1725,6 +1731,7 @@ void Window::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_TRANSPARENT); BIND_ENUM_CONSTANT(FLAG_NO_FOCUS); BIND_ENUM_CONSTANT(FLAG_POPUP); + BIND_ENUM_CONSTANT(FLAG_EXTEND_TO_TITLE); BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED); diff --git a/scene/main/window.h b/scene/main/window.h index aa32edbb04..a5b6b26104 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -56,6 +56,7 @@ public: FLAG_TRANSPARENT = DisplayServer::WINDOW_FLAG_TRANSPARENT, FLAG_NO_FOCUS = DisplayServer::WINDOW_FLAG_NO_FOCUS, FLAG_POPUP = DisplayServer::WINDOW_FLAG_POPUP, + FLAG_EXTEND_TO_TITLE = DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE, FLAG_MAX = DisplayServer::WINDOW_FLAG_MAX, }; @@ -239,6 +240,8 @@ public: void set_use_font_oversampling(bool p_oversampling); bool is_using_font_oversampling() const; + void warp_mouse(const Vector2 &p_position) override; + void set_wrap_controls(bool p_enable); bool is_wrapping_controls() const; void child_controls_changed(); @@ -253,6 +256,7 @@ public: void set_theme(const Ref<Theme> &p_theme); Ref<Theme> get_theme() const; + void _theme_changed(); void set_theme_type_variation(const StringName &p_theme_type); StringName get_theme_type_variation() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index dbe7742ee4..8b43f778e5 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -162,7 +162,7 @@ #include "scene/resources/multimesh.h" #include "scene/resources/navigation_mesh.h" #include "scene/resources/packed_scene.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" #include "scene/resources/physics_material.h" #include "scene/resources/polygon_path_finder.h" #include "scene/resources/primitive_meshes.h" @@ -248,7 +248,7 @@ #include "scene/3d/shape_cast_3d.h" #include "scene/3d/skeleton_3d.h" #include "scene/3d/skeleton_ik_3d.h" -#include "scene/3d/soft_dynamic_body_3d.h" +#include "scene/3d/soft_body_3d.h" #include "scene/3d/spring_arm_3d.h" #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body_3d.h" @@ -533,13 +533,13 @@ void register_scene_types() { GDREGISTER_ABSTRACT_CLASS(PhysicsBody3D); GDREGISTER_CLASS(StaticBody3D); GDREGISTER_CLASS(AnimatableBody3D); - GDREGISTER_CLASS(RigidDynamicBody3D); + GDREGISTER_CLASS(RigidBody3D); GDREGISTER_CLASS(KinematicCollision3D); GDREGISTER_CLASS(CharacterBody3D); GDREGISTER_CLASS(SpringArm3D); GDREGISTER_CLASS(PhysicalBone3D); - GDREGISTER_CLASS(SoftDynamicBody3D); + GDREGISTER_CLASS(SoftBody3D); GDREGISTER_CLASS(SkeletonIK3D); GDREGISTER_CLASS(BoneAttachment3D); @@ -704,7 +704,7 @@ void register_scene_types() { GDREGISTER_ABSTRACT_CLASS(PhysicsBody2D); GDREGISTER_CLASS(StaticBody2D); GDREGISTER_CLASS(AnimatableBody2D); - GDREGISTER_CLASS(RigidDynamicBody2D); + GDREGISTER_CLASS(RigidBody2D); GDREGISTER_CLASS(CharacterBody2D); GDREGISTER_CLASS(KinematicCollision2D); GDREGISTER_CLASS(Area2D); @@ -761,9 +761,9 @@ void register_scene_types() { /* REGISTER RESOURCES */ GDREGISTER_ABSTRACT_CLASS(Shader); - GDREGISTER_CLASS(ParticlesMaterial); - SceneTree::add_idle_callback(ParticlesMaterial::flush_changes); - ParticlesMaterial::init_shaders(); + GDREGISTER_CLASS(ParticleProcessMaterial); + SceneTree::add_idle_callback(ParticleProcessMaterial::flush_changes); + ParticleProcessMaterial::init_shaders(); GDREGISTER_VIRTUAL_CLASS(Mesh); GDREGISTER_CLASS(ArrayMesh); @@ -780,7 +780,6 @@ void register_scene_types() { GDREGISTER_CLASS(CylinderMesh); GDREGISTER_CLASS(PlaneMesh); GDREGISTER_CLASS(PrismMesh); - GDREGISTER_CLASS(QuadMesh); GDREGISTER_CLASS(SphereMesh); GDREGISTER_CLASS(TextMesh); GDREGISTER_CLASS(TorusMesh); @@ -943,6 +942,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("Navigation3D", "Node3D"); ClassDB::add_compatibility_class("Navigation2D", "Node2D"); ClassDB::add_compatibility_class("OpenSimplexNoise", "FastNoiseLite"); + ClassDB::add_compatibility_class("QuadMesh", "PlaneMesh"); ClassDB::add_compatibility_class("ToolButton", "Button"); ClassDB::add_compatibility_class("YSort", "Node2D"); // Portal and room occlusion was replaced by raster occlusion (OccluderInstance3D node). @@ -1019,6 +1019,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("PanoramaSky", "Sky"); ClassDB::add_compatibility_class("Particles", "GPUParticles3D"); ClassDB::add_compatibility_class("Particles2D", "GPUParticles2D"); + ClassDB::add_compatibility_class("ParticlesMaterial", "ParticleProcessMaterial"); ClassDB::add_compatibility_class("Path", "Path3D"); ClassDB::add_compatibility_class("PathFollow", "PathFollow3D"); ClassDB::add_compatibility_class("PhysicalBone", "PhysicalBone3D"); @@ -1041,14 +1042,16 @@ void register_scene_types() { ClassDB::add_compatibility_class("RayShape", "SeparationRayShape3D"); ClassDB::add_compatibility_class("RayShape2D", "SeparationRayShape2D"); ClassDB::add_compatibility_class("RemoteTransform", "RemoteTransform3D"); - ClassDB::add_compatibility_class("RigidBody", "RigidDynamicBody3D"); - ClassDB::add_compatibility_class("RigidBody2D", "RigidDynamicBody2D"); + ClassDB::add_compatibility_class("RigidBody", "RigidBody3D"); + ClassDB::add_compatibility_class("RigidDynamicBody2D", "RigidBody2D"); + ClassDB::add_compatibility_class("RigidDynamicBody3D", "RigidBody3D"); ClassDB::add_compatibility_class("Shape", "Shape3D"); ClassDB::add_compatibility_class("ShortCut", "Shortcut"); ClassDB::add_compatibility_class("Skeleton", "Skeleton3D"); ClassDB::add_compatibility_class("SkeletonIK", "SkeletonIK3D"); ClassDB::add_compatibility_class("SliderJoint", "SliderJoint3D"); - ClassDB::add_compatibility_class("SoftBody", "SoftDynamicBody3D"); + ClassDB::add_compatibility_class("SoftBody", "SoftBody3D"); + ClassDB::add_compatibility_class("SoftDynamicBody3D", "SoftBody3D"); ClassDB::add_compatibility_class("Spatial", "Node3D"); ClassDB::add_compatibility_class("SpatialGizmo", "Node3DGizmo"); ClassDB::add_compatibility_class("SpatialMaterial", "StandardMaterial3D"); @@ -1132,8 +1135,8 @@ void initialize_theme() { String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", ""); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); - bool font_antialiased = (bool)GLOBAL_DEF_RST("gui/theme/default_font_antialiased", true); - ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiased", PropertyInfo(Variant::BOOL, "gui/theme/default_font_antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)GLOBAL_DEF_RST("gui/theme/default_font_antialiasing", 1); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiasing", PropertyInfo(Variant::INT, "gui/theme/default_font_antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); TextServer::Hinting font_hinting = (TextServer::Hinting)(int)GLOBAL_DEF_RST("gui/theme/default_font_hinting", TextServer::HINTING_LIGHT); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_hinting", PropertyInfo(Variant::INT, "gui/theme/default_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); @@ -1144,6 +1147,10 @@ void initialize_theme() { const bool font_msdf = GLOBAL_DEF_RST("gui/theme/default_font_multichannel_signed_distance_field", false); const bool font_generate_mipmaps = GLOBAL_DEF_RST("gui/theme/default_font_generate_mipmaps", false); + GLOBAL_DEF_RST("gui/theme/lcd_subpixel_layout", 1); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/lcd_subpixel_layout", PropertyInfo(Variant::INT, "gui/theme/lcd_subpixel_layout", PROPERTY_HINT_ENUM, "Disabled,Horizontal RGB,Horizontal BGR,Vertical RGB,Vertical BGR")); + ProjectSettings::get_singleton()->set_restart_if_changed("gui/theme/lcd_subpixel_layout", false); + Ref<Font> font; if (!font_path.is_empty()) { font = ResourceLoader::load(font_path); @@ -1154,7 +1161,7 @@ void initialize_theme() { // Always make the default theme to avoid invalid default font/icon/style in the given theme. if (RenderingServer::get_singleton()) { - make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased, font_msdf, font_generate_mipmaps); + make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiasing, font_msdf, font_generate_mipmaps); } if (!theme_path.is_empty()) { @@ -1209,7 +1216,7 @@ void unregister_scene_types() { ProceduralSkyMaterial::cleanup_shader(); #endif // _3D_DISABLED - ParticlesMaterial::finish_shaders(); + ParticleProcessMaterial::finish_shaders(); CanvasItemMaterial::finish_shaders(); ColorPicker::finish_shaders(); SceneStringNames::free(); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index da59c4dbd1..4197251d7e 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2323,100 +2323,23 @@ Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, real_t p } real_t Animation::_interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const { - return p_a * (1.0 - p_c) + p_b * p_c; + return Math::lerp(p_a, p_b, p_c); } -// Cubic interpolation for anytype. - -Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c) const { - return p_a.cubic_interpolate(p_b, p_pre_a, p_post_b, p_c); -} - -Quaternion Animation::_cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const { - return p_a.spherical_cubic_interpolate(p_b, p_pre_a, p_post_b, p_c); -} - -Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const { +Variant Animation::_interpolate_angle(const Variant &p_a, const Variant &p_b, real_t p_c) const { Variant::Type type_a = p_a.get_type(); Variant::Type type_b = p_b.get_type(); - Variant::Type type_pa = p_pre_a.get_type(); - Variant::Type type_pb = p_post_b.get_type(); - - //make int and real play along - uint32_t vformat = 1 << type_a; vformat |= 1 << type_b; - vformat |= 1 << type_pa; - vformat |= 1 << type_pb; - if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) { - //mix of real and int real_t a = p_a; real_t b = p_b; - real_t pa = p_pre_a; - real_t pb = p_post_b; - - return Math::cubic_interpolate(a, b, pa, pb, p_c); - } else if ((vformat & (vformat - 1))) { - return p_a; //can't interpolate, mix of types + return Math::fposmod((float)Math::lerp_angle(a, b, p_c), (float)Math_TAU); } - - switch (type_a) { - case Variant::VECTOR2: { - Vector2 a = p_a; - Vector2 b = p_b; - Vector2 pa = p_pre_a; - Vector2 pb = p_post_b; - - return a.cubic_interpolate(b, pa, pb, p_c); - } - case Variant::RECT2: { - Rect2 a = p_a; - Rect2 b = p_b; - Rect2 pa = p_pre_a; - Rect2 pb = p_post_b; - - return Rect2( - a.position.cubic_interpolate(b.position, pa.position, pb.position, p_c), - a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); - } - case Variant::VECTOR3: { - Vector3 a = p_a; - Vector3 b = p_b; - Vector3 pa = p_pre_a; - Vector3 pb = p_post_b; - - return a.cubic_interpolate(b, pa, pb, p_c); - } - case Variant::QUATERNION: { - Quaternion a = p_a; - Quaternion b = p_b; - Quaternion pa = p_pre_a; - Quaternion pb = p_post_b; - - return a.spherical_cubic_interpolate(b, pa, pb, p_c); - } - case Variant::AABB: { - AABB a = p_a; - AABB b = p_b; - AABB pa = p_pre_a; - AABB pb = p_post_b; - - return AABB( - a.position.cubic_interpolate(b.position, pa.position, pb.position, p_c), - a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); - } - default: { - return _interpolate(p_a, p_b, p_c); - } - } -} - -real_t Animation::_cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const { return _interpolate(p_a, p_b, p_c); } -// Cubic interpolation in time for anytype. +// Cubic interpolation for anytype. Vector3 Animation::_cubic_interpolate_in_time(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { return p_a.cubic_interpolate_in_time(p_b, p_pre_a, p_post_b, p_c, p_b_t, p_pre_a_t, p_post_b_t); @@ -2503,6 +2426,25 @@ Variant Animation::_cubic_interpolate_in_time(const Variant &p_pre_a, const Vari } real_t Animation::_cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { + return Math::cubic_interpolate_in_time(p_a, p_b, p_pre_a, p_post_b, p_c, p_b_t, p_pre_a_t, p_post_b_t); +} + +Variant Animation::_cubic_interpolate_angle_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { + Variant::Type type_a = p_a.get_type(); + Variant::Type type_b = p_b.get_type(); + Variant::Type type_pa = p_pre_a.get_type(); + Variant::Type type_pb = p_post_b.get_type(); + uint32_t vformat = 1 << type_a; + vformat |= 1 << type_b; + vformat |= 1 << type_pa; + vformat |= 1 << type_pb; + if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) { + real_t a = p_a; + real_t b = p_b; + real_t pa = p_pre_a; + real_t pb = p_post_b; + return Math::fposmod((float)Math::cubic_interpolate_angle_in_time(a, b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t), (float)Math_TAU); + } return _interpolate(p_a, p_b, p_c); } @@ -2685,8 +2627,11 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol case INTERPOLATION_LINEAR: { return _interpolate(p_keys[idx].value, p_keys[next].value, c); } break; + case INTERPOLATION_LINEAR_ANGLE: { + return _interpolate_angle(p_keys[idx].value, p_keys[next].value, c); + } break; case INTERPOLATION_CUBIC: - case INTERPOLATION_CUBIC_IN_TIME: { + case INTERPOLATION_CUBIC_ANGLE: { int pre = 0; int post = 0; if (!p_backward) { @@ -2725,25 +2670,27 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol } } + real_t pre_t = 0.0; + real_t to_t = 0.0; + real_t post_t = 0.0; if (loop_mode == LOOP_LINEAR && p_loop_wrap) { - if (p_interp == INTERPOLATION_CUBIC) { - return _cubic_interpolate(p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c); - } - return _cubic_interpolate_in_time( - p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c, - pre > idx ? -length + p_keys[pre].time - p_keys[idx].time : p_keys[pre].time - p_keys[idx].time, - next < idx ? length + p_keys[next].time - p_keys[idx].time : p_keys[next].time - p_keys[idx].time, - next < idx || post <= idx ? length + p_keys[post].time - p_keys[idx].time : p_keys[post].time - p_keys[idx].time); + pre_t = pre > idx ? -length + p_keys[pre].time - p_keys[idx].time : p_keys[pre].time - p_keys[idx].time; + to_t = next < idx ? length + p_keys[next].time - p_keys[idx].time : p_keys[next].time - p_keys[idx].time; + post_t = next < idx || post <= idx ? length + p_keys[post].time - p_keys[idx].time : p_keys[post].time - p_keys[idx].time; + } else { + pre_t = p_keys[pre].time - p_keys[idx].time; + to_t = p_keys[next].time - p_keys[idx].time; + post_t = p_keys[post].time - p_keys[idx].time; } - if (p_interp == INTERPOLATION_CUBIC) { - return _cubic_interpolate(p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c); + if (p_interp == INTERPOLATION_CUBIC_ANGLE) { + return _cubic_interpolate_angle_in_time( + p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c, + pre_t, to_t, post_t); } return _cubic_interpolate_in_time( p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c, - p_keys[pre].time - p_keys[idx].time, - p_keys[next].time - p_keys[idx].time, - p_keys[post].time - p_keys[idx].time); + pre_t, to_t, post_t); } break; default: return p_keys[idx].value; @@ -4073,7 +4020,8 @@ void Animation::_bind_methods() { BIND_ENUM_CONSTANT(INTERPOLATION_NEAREST); BIND_ENUM_CONSTANT(INTERPOLATION_LINEAR); BIND_ENUM_CONSTANT(INTERPOLATION_CUBIC); - BIND_ENUM_CONSTANT(INTERPOLATION_CUBIC_IN_TIME); + BIND_ENUM_CONSTANT(INTERPOLATION_LINEAR_ANGLE); + BIND_ENUM_CONSTANT(INTERPOLATION_CUBIC_ANGLE); BIND_ENUM_CONSTANT(UPDATE_CONTINUOUS); BIND_ENUM_CONSTANT(UPDATE_DISCRETE); diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 5e88980397..8fa0275230 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -57,7 +57,8 @@ public: INTERPOLATION_NEAREST, INTERPOLATION_LINEAR, INTERPOLATION_CUBIC, - INTERPOLATION_CUBIC_IN_TIME, + INTERPOLATION_LINEAR_ANGLE, + INTERPOLATION_CUBIC_ANGLE, }; enum UpdateMode { @@ -237,16 +238,13 @@ private: _FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, real_t p_c) const; _FORCE_INLINE_ Variant _interpolate(const Variant &p_a, const Variant &p_b, real_t p_c) const; _FORCE_INLINE_ real_t _interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const; - - _FORCE_INLINE_ Vector3 _cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c) const; - _FORCE_INLINE_ Quaternion _cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const; - _FORCE_INLINE_ Variant _cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const; - _FORCE_INLINE_ real_t _cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const; + _FORCE_INLINE_ Variant _interpolate_angle(const Variant &p_a, const Variant &p_b, real_t p_c) const; _FORCE_INLINE_ Vector3 _cubic_interpolate_in_time(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; _FORCE_INLINE_ Quaternion _cubic_interpolate_in_time(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; _FORCE_INLINE_ Variant _cubic_interpolate_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; _FORCE_INLINE_ real_t _cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; + _FORCE_INLINE_ Variant _cubic_interpolate_angle_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; template <class T> _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const; diff --git a/scene/resources/capsule_shape_3d.cpp b/scene/resources/capsule_shape_3d.cpp index 214004824f..b0454004a0 100644 --- a/scene/resources/capsule_shape_3d.cpp +++ b/scene/resources/capsule_shape_3d.cpp @@ -40,8 +40,8 @@ Vector<Vector3> CapsuleShape3D::get_debug_mesh_lines() const { Vector3 d(0, height * 0.5 - radius, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 1835604285..ee53578517 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -763,7 +763,7 @@ void Curve2D::_bake_segment2d(RBMap<real_t, Vector2> &r_bake, real_t p_begin, re Vector2 nb = (end - mid).normalized(); real_t dp = na.dot(nb); - if (dp < Math::cos(Math::deg2rad(p_tol))) { + if (dp < Math::cos(Math::deg_to_rad(p_tol))) { r_bake[mp] = mid; } @@ -1352,7 +1352,7 @@ void Curve3D::_bake_segment3d(RBMap<real_t, Vector3> &r_bake, real_t p_begin, re Vector3 nb = (end - mid).normalized(); real_t dp = na.dot(nb); - if (dp < Math::cos(Math::deg2rad(p_tol))) { + if (dp < Math::cos(Math::deg_to_rad(p_tol))) { r_bake[mp] = mid; } if (p_depth < p_max_depth) { diff --git a/scene/resources/cylinder_shape_3d.cpp b/scene/resources/cylinder_shape_3d.cpp index 345df5ffed..a5951db8ea 100644 --- a/scene/resources/cylinder_shape_3d.cpp +++ b/scene/resources/cylinder_shape_3d.cpp @@ -40,8 +40,8 @@ Vector<Vector3> CylinderShape3D::get_debug_mesh_lines() const { Vector3 d(0, height * 0.5, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 6d99073fa4..5bfa1adfe5 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -1053,7 +1053,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2); } -void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel, TextServer::Hinting p_font_hinting, bool p_font_antialiased, bool p_font_msdf, bool p_font_generate_mipmaps) { +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel, TextServer::Hinting p_font_hinting, TextServer::FontAntialiasing p_font_antialiasing, bool p_font_msdf, bool p_font_generate_mipmaps) { Ref<Theme> t; t.instantiate(); @@ -1077,7 +1077,7 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos dynamic_font->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size); dynamic_font->set_subpixel_positioning(p_font_subpixel); dynamic_font->set_hinting(p_font_hinting); - dynamic_font->set_antialiased(p_font_antialiased); + dynamic_font->set_antialiasing(p_font_antialiasing); dynamic_font->set_multichannel_signed_distance_field(p_font_msdf); dynamic_font->set_generate_mipmaps(p_font_generate_mipmaps); diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index 9b070a90cc..15be5e676f 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -36,7 +36,7 @@ const int default_font_size = 16; 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_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, bool p_font_antialiased = true, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, TextServer::FontAntialiasing p_font_antialiased = TextServer::FONT_ANTIALIASING_GRAY, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); void clear_default_theme(); #endif // DEFAULT_THEME_H diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index f8651fecd6..be57d9c965 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -576,7 +576,7 @@ _FORCE_INLINE_ void FontFile::_ensure_rid(int p_cache_index) const { if (unlikely(!cache[p_cache_index].is_valid())) { cache.write[p_cache_index] = TS->create_font(); TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size); - TS->font_set_antialiased(cache[p_cache_index], antialiased); + TS->font_set_antialiasing(cache[p_cache_index], antialiasing); TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps); TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf); TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range); @@ -875,8 +875,8 @@ void FontFile::_bind_methods() { ClassDB::bind_method(D_METHOD("set_font_style_name", "name"), &FontFile::set_font_style_name); ClassDB::bind_method(D_METHOD("set_font_style", "style"), &FontFile::set_font_style); - ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontFile::set_antialiased); - ClassDB::bind_method(D_METHOD("is_antialiased"), &FontFile::is_antialiased); + ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &FontFile::set_antialiasing); + ClassDB::bind_method(D_METHOD("get_antialiasing"), &FontFile::get_antialiasing); ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontFile::set_generate_mipmaps); ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontFile::get_generate_mipmaps); @@ -996,7 +996,7 @@ void FontFile::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name"); 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_FLAGS, "Bold,Italic,Fixed Size", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style"); @@ -1318,7 +1318,7 @@ void FontFile::reset_state() { data_size = 0; cache.clear(); - antialiased = true; + antialiasing = TextServer::FONT_ANTIALIASING_GRAY; mipmaps = false; msdf = false; force_autohinter = false; @@ -1337,7 +1337,7 @@ void FontFile::reset_state() { Error FontFile::load_bitmap_font(const String &p_path) { reset_state(); - antialiased = false; + antialiasing = TextServer::FONT_ANTIALIASING_NONE; mipmaps = false; msdf = false; force_autohinter = false; @@ -1817,11 +1817,9 @@ void FontFile::set_data_ptr(const uint8_t *p_data, size_t p_size) { data_ptr = p_data; data_size = p_size; - if (data_ptr != nullptr) { - for (int i = 0; i < cache.size(); i++) { - if (cache[i].is_valid()) { - TS->font_set_data_ptr(cache[i], data_ptr, data_size); - } + for (int i = 0; i < cache.size(); i++) { + if (cache[i].is_valid()) { + TS->font_set_data_ptr(cache[i], data_ptr, data_size); } } } @@ -1831,11 +1829,9 @@ void FontFile::set_data(const PackedByteArray &p_data) { data_ptr = data.ptr(); data_size = data.size(); - if (data_ptr != nullptr) { - for (int i = 0; i < cache.size(); i++) { - if (cache[i].is_valid()) { - TS->font_set_data_ptr(cache[i], data_ptr, data_size); - } + for (int i = 0; i < cache.size(); i++) { + if (cache[i].is_valid()) { + TS->font_set_data_ptr(cache[i], data_ptr, data_size); } } } @@ -1864,19 +1860,19 @@ void FontFile::set_font_style(BitField<TextServer::FontStyle> p_style) { TS->font_set_style(cache[0], p_style); } -void FontFile::set_antialiased(bool p_antialiased) { - if (antialiased != p_antialiased) { - antialiased = p_antialiased; +void FontFile::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) { + if (antialiasing != p_antialiasing) { + antialiasing = p_antialiasing; for (int i = 0; i < cache.size(); i++) { _ensure_rid(i); - TS->font_set_antialiased(cache[i], antialiased); + TS->font_set_antialiasing(cache[i], antialiasing); } emit_changed(); } } -bool FontFile::is_antialiased() const { - return antialiased; +TextServer::FontAntialiasing FontFile::get_antialiasing() const { + return antialiasing; } void FontFile::set_generate_mipmaps(bool p_generate_mipmaps) { @@ -2699,8 +2695,8 @@ FontVariation::~FontVariation() { /*************************************************************************/ void SystemFont::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &SystemFont::set_antialiased); - ClassDB::bind_method(D_METHOD("is_antialiased"), &SystemFont::is_antialiased); + ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &SystemFont::set_antialiasing); + ClassDB::bind_method(D_METHOD("get_antialiasing"), &SystemFont::get_antialiasing); ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &SystemFont::set_generate_mipmaps); ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &SystemFont::get_generate_mipmaps); @@ -2727,7 +2723,7 @@ void SystemFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "font_names"), "set_font_names", "get_font_names"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic"), "set_font_style", "get_font_style"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "is_antialiased"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting"); @@ -2804,7 +2800,7 @@ void SystemFont::_update_base_font() { } // Apply font rendering settings. - file->set_antialiased(antialiased); + file->set_antialiasing(antialiasing); file->set_generate_mipmaps(mipmaps); file->set_force_autohinter(force_autohinter); file->set_hinting(hinting); @@ -2841,7 +2837,7 @@ void SystemFont::reset_state() { ftr_weight = 0; ftr_italic = 0; style = 0; - antialiased = true; + antialiasing = TextServer::FONT_ANTIALIASING_GRAY; mipmaps = false; force_autohinter = false; hinting = TextServer::HINTING_LIGHT; @@ -2907,18 +2903,18 @@ Ref<Font> SystemFont::_get_base_font_or_default() const { return Ref<Font>(); } -void SystemFont::set_antialiased(bool p_antialiased) { - if (antialiased != p_antialiased) { - antialiased = p_antialiased; +void SystemFont::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) { + if (antialiasing != p_antialiasing) { + antialiasing = p_antialiasing; if (base_font.is_valid()) { - base_font->set_antialiased(antialiased); + base_font->set_antialiasing(antialiasing); } emit_changed(); } } -bool SystemFont::is_antialiased() const { - return antialiased; +TextServer::FontAntialiasing SystemFont::get_antialiasing() const { + return antialiasing; } void SystemFont::set_generate_mipmaps(bool p_generate_mipmaps) { diff --git a/scene/resources/font.h b/scene/resources/font.h index decbcfbb69..5cf596b41d 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -141,7 +141,7 @@ class FontFile : public Font { size_t data_size = 0; PackedByteArray data; - bool antialiased = true; + TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY; bool mipmaps = false; bool msdf = false; int msdf_pixel_range = 16; @@ -192,8 +192,8 @@ public: virtual void set_font_style_name(const String &p_name); virtual void set_font_style(BitField<TextServer::FontStyle> p_style); - virtual void set_antialiased(bool p_antialiased); - virtual bool is_antialiased() const; + virtual void set_antialiasing(TextServer::FontAntialiasing p_antialiasing); + virtual TextServer::FontAntialiasing get_antialiasing() const; virtual void set_generate_mipmaps(bool p_generate_mipmaps); virtual bool get_generate_mipmaps() const; @@ -398,7 +398,7 @@ class SystemFont : public Font { int ftr_weight = 0; int ftr_italic = 0; - bool antialiased = true; + TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY; bool mipmaps = false; bool force_autohinter = false; TextServer::Hinting hinting = TextServer::HINTING_LIGHT; @@ -417,8 +417,8 @@ protected: public: virtual Ref<Font> _get_base_font_or_default() const; - virtual void set_antialiased(bool p_antialiased); - virtual bool is_antialiased() const; + virtual void set_antialiasing(TextServer::FontAntialiasing p_antialiasing); + virtual TextServer::FontAntialiasing get_antialiasing() const; virtual void set_generate_mipmaps(bool p_generate_mipmaps); virtual bool get_generate_mipmaps() const; diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index 293fdd6f05..3638d1862c 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -301,9 +301,9 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } - float normal_merge_threshold = Math::cos(Math::deg2rad(p_normal_merge_angle)); - float normal_pre_split_threshold = Math::cos(Math::deg2rad(MIN(180.0f, p_normal_split_angle * 2.0f))); - float normal_split_threshold = Math::cos(Math::deg2rad(p_normal_split_angle)); + float normal_merge_threshold = Math::cos(Math::deg_to_rad(p_normal_merge_angle)); + float normal_pre_split_threshold = Math::cos(Math::deg_to_rad(MIN(180.0f, p_normal_split_angle * 2.0f))); + float normal_split_threshold = Math::cos(Math::deg_to_rad(p_normal_split_angle)); const Vector3 *normals_ptr = normals.ptr(); HashMap<Vector3, LocalVector<Pair<int, int>>> unique_vertices; diff --git a/scene/resources/particles_material.cpp b/scene/resources/particle_process_material.cpp index 0fe5c8f2db..ed19101de4 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particle_process_material.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* particles_material.cpp */ +/* particle_process_material.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,17 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "particles_material.h" +#include "particle_process_material.h" #include "core/version.h" -Mutex ParticlesMaterial::material_mutex; -SelfList<ParticlesMaterial>::List *ParticlesMaterial::dirty_materials = nullptr; -HashMap<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData, ParticlesMaterial::MaterialKey> ParticlesMaterial::shader_map; -ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = nullptr; +Mutex ParticleProcessMaterial::material_mutex; +SelfList<ParticleProcessMaterial>::List *ParticleProcessMaterial::dirty_materials = nullptr; +HashMap<ParticleProcessMaterial::MaterialKey, ParticleProcessMaterial::ShaderData, ParticleProcessMaterial::MaterialKey> ParticleProcessMaterial::shader_map; +ParticleProcessMaterial::ShaderNames *ParticleProcessMaterial::shader_names = nullptr; -void ParticlesMaterial::init_shaders() { - dirty_materials = memnew(SelfList<ParticlesMaterial>::List); +void ParticleProcessMaterial::init_shaders() { + dirty_materials = memnew(SelfList<ParticleProcessMaterial>::List); shader_names = memnew(ShaderNames); @@ -121,14 +121,14 @@ void ParticlesMaterial::init_shaders() { shader_names->collision_bounce = "collision_bounce"; } -void ParticlesMaterial::finish_shaders() { +void ParticleProcessMaterial::finish_shaders() { memdelete(dirty_materials); dirty_materials = nullptr; memdelete(shader_names); } -void ParticlesMaterial::_update_shader() { +void ParticleProcessMaterial::_update_shader() { dirty_materials->remove(&element); MaterialKey mk = _compute_key(); @@ -155,7 +155,7 @@ void ParticlesMaterial::_update_shader() { //must create a shader! // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). - String code = "// NOTE: Shader automatically converted from " VERSION_NAME " " VERSION_FULL_CONFIG "'s ParticlesMaterial.\n\n"; + String code = "// NOTE: Shader automatically converted from " VERSION_NAME " " VERSION_FULL_CONFIG "'s ParticleProcessMaterial.\n\n"; code += "shader_type particles;\n"; @@ -287,7 +287,7 @@ void ParticlesMaterial::_update_shader() { code += "uniform sampler2D anim_offset_texture : repeat_disable;\n"; } - if (collision_enabled) { + if (collision_mode == COLLISION_RIGID) { code += "uniform float collision_friction;\n"; code += "uniform float collision_bounce;\n"; } @@ -695,8 +695,10 @@ void ParticlesMaterial::_update_shader() { } code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n"; // If collision happened, turbulence is no longer applied. + // We don't need this check when the collision mode is "hide on contact", + // as the particle will be hidden anyway. String extra_tab = ""; - if (collision_enabled) { + if (collision_mode != COLLISION_RIGID) { code += " if (!COLLIDED) {\n"; extra_tab = " "; } @@ -704,7 +706,7 @@ void ParticlesMaterial::_update_shader() { code += extra_tab + " float vel_mag = length(VELOCITY);\n"; code += extra_tab + " float vel_infl = clamp(mix(turbulence_influence_min, turbulence_influence_max, rand_from_seed(alt_seed)) * turbulence_influence, 0.0, 1.0);\n"; code += extra_tab + " VELOCITY = mix(VELOCITY, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n"; - if (collision_enabled) { + if (collision_mode != COLLISION_RIGID) { code += " }"; } } @@ -828,7 +830,7 @@ void ParticlesMaterial::_update_shader() { code += " TRANSFORM[3].z = 0.0;\n"; } - if (collision_enabled) { + if (collision_mode == COLLISION_RIGID) { code += " if (COLLIDED) {\n"; code += " if (length(VELOCITY) > 3.0) {\n"; code += " TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;\n"; @@ -851,6 +853,18 @@ void ParticlesMaterial::_update_shader() { code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n"; code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n"; + if (collision_mode == COLLISION_RIGID) { + code += " if (COLLIDED) {\n"; + code += " TRANSFORM[3].xyz+=COLLISION_NORMAL * COLLISION_DEPTH;\n"; + code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n"; + code += " VELOCITY = mix(VELOCITY,vec3(0.0),collision_friction * DELTA * 100.0);\n"; + code += " }\n"; + } else if (collision_mode == COLLISION_HIDE_ON_CONTACT) { + code += " if (COLLIDED) {\n"; + code += " ACTIVE = false;\n"; + code += " }\n"; + } + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { code += " int emit_count = 0;\n"; switch (sub_emitter_mode) { @@ -894,7 +908,7 @@ void ParticlesMaterial::_update_shader() { RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -void ParticlesMaterial::flush_changes() { +void ParticleProcessMaterial::flush_changes() { MutexLock lock(material_mutex); while (dirty_materials->first()) { @@ -902,7 +916,7 @@ void ParticlesMaterial::flush_changes() { } } -void ParticlesMaterial::_queue_shader_change() { +void ParticleProcessMaterial::_queue_shader_change() { MutexLock lock(material_mutex); if (is_initialized && !element.in_list()) { @@ -910,40 +924,40 @@ void ParticlesMaterial::_queue_shader_change() { } } -bool ParticlesMaterial::_is_shader_dirty() const { +bool ParticleProcessMaterial::_is_shader_dirty() const { MutexLock lock(material_mutex); return element.in_list(); } -void ParticlesMaterial::set_direction(Vector3 p_direction) { +void ParticleProcessMaterial::set_direction(Vector3 p_direction) { direction = p_direction; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->direction, direction); } -Vector3 ParticlesMaterial::get_direction() const { +Vector3 ParticleProcessMaterial::get_direction() const { return direction; } -void ParticlesMaterial::set_spread(float p_spread) { +void ParticleProcessMaterial::set_spread(float p_spread) { spread = p_spread; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); } -float ParticlesMaterial::get_spread() const { +float ParticleProcessMaterial::get_spread() const { return spread; } -void ParticlesMaterial::set_flatness(float p_flatness) { +void ParticleProcessMaterial::set_flatness(float p_flatness) { flatness = p_flatness; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); } -float ParticlesMaterial::get_flatness() const { +float ParticleProcessMaterial::get_flatness() const { return flatness; } -void ParticlesMaterial::set_param_min(Parameter p_param, float p_value) { +void ParticleProcessMaterial::set_param_min(Parameter p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params_min[p_param] = p_value; @@ -1002,13 +1016,13 @@ void ParticlesMaterial::set_param_min(Parameter p_param, float p_value) { } } -float ParticlesMaterial::get_param_min(Parameter p_param) const { +float ParticleProcessMaterial::get_param_min(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); return params_min[p_param]; } -void ParticlesMaterial::set_param_max(Parameter p_param, float p_value) { +void ParticleProcessMaterial::set_param_max(Parameter p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params_max[p_param] = p_value; @@ -1067,7 +1081,7 @@ void ParticlesMaterial::set_param_max(Parameter p_param, float p_value) { } } -float ParticlesMaterial::get_param_max(Parameter p_param) const { +float ParticleProcessMaterial::get_param_max(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); return params_max[p_param]; @@ -1082,7 +1096,7 @@ static void _adjust_curve_range(const Ref<Texture2D> &p_texture, float p_min, fl curve_tex->ensure_default_setup(p_min, p_max); } -void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D> &p_texture) { +void ParticleProcessMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D> &p_texture) { ERR_FAIL_INDEX(p_param, PARAM_MAX); tex_parameters[p_param] = p_texture; @@ -1153,22 +1167,22 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D _queue_shader_change(); } -Ref<Texture2D> ParticlesMaterial::get_param_texture(Parameter p_param) const { +Ref<Texture2D> ParticleProcessMaterial::get_param_texture(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Texture2D>()); return tex_parameters[p_param]; } -void ParticlesMaterial::set_color(const Color &p_color) { +void ParticleProcessMaterial::set_color(const Color &p_color) { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); color = p_color; } -Color ParticlesMaterial::get_color() const { +Color ParticleProcessMaterial::get_color() const { return color; } -void ParticlesMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) { +void ParticleProcessMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) { color_ramp = p_texture; RID tex_rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, tex_rid); @@ -1176,11 +1190,11 @@ void ParticlesMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) { notify_property_list_changed(); } -Ref<Texture2D> ParticlesMaterial::get_color_ramp() const { +Ref<Texture2D> ParticleProcessMaterial::get_color_ramp() const { return color_ramp; } -void ParticlesMaterial::set_color_initial_ramp(const Ref<Texture2D> &p_texture) { +void ParticleProcessMaterial::set_color_initial_ramp(const Ref<Texture2D> &p_texture) { color_initial_ramp = p_texture; RID tex_rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_initial_ramp, tex_rid); @@ -1188,11 +1202,11 @@ void ParticlesMaterial::set_color_initial_ramp(const Ref<Texture2D> &p_texture) notify_property_list_changed(); } -Ref<Texture2D> ParticlesMaterial::get_color_initial_ramp() const { +Ref<Texture2D> ParticleProcessMaterial::get_color_initial_ramp() const { return color_initial_ramp; } -void ParticlesMaterial::set_particle_flag(ParticleFlags p_particle_flag, bool p_enable) { +void ParticleProcessMaterial::set_particle_flag(ParticleFlags p_particle_flag, bool p_enable) { ERR_FAIL_INDEX(p_particle_flag, PARTICLE_FLAG_MAX); particle_flags[p_particle_flag] = p_enable; _queue_shader_change(); @@ -1201,165 +1215,165 @@ void ParticlesMaterial::set_particle_flag(ParticleFlags p_particle_flag, bool p_ } } -bool ParticlesMaterial::get_particle_flag(ParticleFlags p_particle_flag) const { +bool ParticleProcessMaterial::get_particle_flag(ParticleFlags p_particle_flag) const { ERR_FAIL_INDEX_V(p_particle_flag, PARTICLE_FLAG_MAX, false); return particle_flags[p_particle_flag]; } -void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { +void ParticleProcessMaterial::set_emission_shape(EmissionShape p_shape) { ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX); emission_shape = p_shape; notify_property_list_changed(); _queue_shader_change(); } -void ParticlesMaterial::set_emission_sphere_radius(real_t p_radius) { +void ParticleProcessMaterial::set_emission_sphere_radius(real_t p_radius) { emission_sphere_radius = p_radius; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); } -void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) { +void ParticleProcessMaterial::set_emission_box_extents(Vector3 p_extents) { emission_box_extents = p_extents; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); } -void ParticlesMaterial::set_emission_point_texture(const Ref<Texture2D> &p_points) { +void ParticleProcessMaterial::set_emission_point_texture(const Ref<Texture2D> &p_points) { emission_point_texture = p_points; RID tex_rid = p_points.is_valid() ? p_points->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, tex_rid); } -void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture2D> &p_normals) { +void ParticleProcessMaterial::set_emission_normal_texture(const Ref<Texture2D> &p_normals) { emission_normal_texture = p_normals; RID tex_rid = p_normals.is_valid() ? p_normals->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, tex_rid); } -void ParticlesMaterial::set_emission_color_texture(const Ref<Texture2D> &p_colors) { +void ParticleProcessMaterial::set_emission_color_texture(const Ref<Texture2D> &p_colors) { emission_color_texture = p_colors; RID tex_rid = p_colors.is_valid() ? p_colors->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, tex_rid); _queue_shader_change(); } -void ParticlesMaterial::set_emission_point_count(int p_count) { +void ParticleProcessMaterial::set_emission_point_count(int p_count) { emission_point_count = p_count; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); } -void ParticlesMaterial::set_emission_ring_axis(Vector3 p_axis) { +void ParticleProcessMaterial::set_emission_ring_axis(Vector3 p_axis) { emission_ring_axis = p_axis; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_axis, p_axis); } -void ParticlesMaterial::set_emission_ring_height(real_t p_height) { +void ParticleProcessMaterial::set_emission_ring_height(real_t p_height) { emission_ring_height = p_height; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_height, p_height); } -void ParticlesMaterial::set_emission_ring_radius(real_t p_radius) { +void ParticleProcessMaterial::set_emission_ring_radius(real_t p_radius) { emission_ring_radius = p_radius; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_radius, p_radius); } -void ParticlesMaterial::set_emission_ring_inner_radius(real_t p_radius) { +void ParticleProcessMaterial::set_emission_ring_inner_radius(real_t p_radius) { emission_ring_inner_radius = p_radius; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_inner_radius, p_radius); } -ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { +ParticleProcessMaterial::EmissionShape ParticleProcessMaterial::get_emission_shape() const { return emission_shape; } -real_t ParticlesMaterial::get_emission_sphere_radius() const { +real_t ParticleProcessMaterial::get_emission_sphere_radius() const { return emission_sphere_radius; } -Vector3 ParticlesMaterial::get_emission_box_extents() const { +Vector3 ParticleProcessMaterial::get_emission_box_extents() const { return emission_box_extents; } -Ref<Texture2D> ParticlesMaterial::get_emission_point_texture() const { +Ref<Texture2D> ParticleProcessMaterial::get_emission_point_texture() const { return emission_point_texture; } -Ref<Texture2D> ParticlesMaterial::get_emission_normal_texture() const { +Ref<Texture2D> ParticleProcessMaterial::get_emission_normal_texture() const { return emission_normal_texture; } -Ref<Texture2D> ParticlesMaterial::get_emission_color_texture() const { +Ref<Texture2D> ParticleProcessMaterial::get_emission_color_texture() const { return emission_color_texture; } -int ParticlesMaterial::get_emission_point_count() const { +int ParticleProcessMaterial::get_emission_point_count() const { return emission_point_count; } -Vector3 ParticlesMaterial::get_emission_ring_axis() const { +Vector3 ParticleProcessMaterial::get_emission_ring_axis() const { return emission_ring_axis; } -real_t ParticlesMaterial::get_emission_ring_height() const { +real_t ParticleProcessMaterial::get_emission_ring_height() const { return emission_ring_height; } -real_t ParticlesMaterial::get_emission_ring_radius() const { +real_t ParticleProcessMaterial::get_emission_ring_radius() const { return emission_ring_radius; } -real_t ParticlesMaterial::get_emission_ring_inner_radius() const { +real_t ParticleProcessMaterial::get_emission_ring_inner_radius() const { return emission_ring_inner_radius; } -void ParticlesMaterial::set_turbulence_enabled(const bool p_turbulence_enabled) { +void ParticleProcessMaterial::set_turbulence_enabled(const bool p_turbulence_enabled) { turbulence_enabled = p_turbulence_enabled; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_enabled, turbulence_enabled); _queue_shader_change(); notify_property_list_changed(); } -bool ParticlesMaterial::get_turbulence_enabled() const { +bool ParticleProcessMaterial::get_turbulence_enabled() const { return turbulence_enabled; } -void ParticlesMaterial::set_turbulence_noise_strength(float p_turbulence_noise_strength) { +void ParticleProcessMaterial::set_turbulence_noise_strength(float p_turbulence_noise_strength) { turbulence_noise_strength = p_turbulence_noise_strength; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_strength, p_turbulence_noise_strength); } -float ParticlesMaterial::get_turbulence_noise_strength() const { +float ParticleProcessMaterial::get_turbulence_noise_strength() const { return turbulence_noise_strength; } -void ParticlesMaterial::set_turbulence_noise_scale(float p_turbulence_noise_scale) { +void ParticleProcessMaterial::set_turbulence_noise_scale(float p_turbulence_noise_scale) { turbulence_noise_scale = p_turbulence_noise_scale; float shader_turbulence_noise_scale = (pow(p_turbulence_noise_scale, 0.25) * 5.6234 / 10.0) * 4.0 - 3.0; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_scale, shader_turbulence_noise_scale); } -float ParticlesMaterial::get_turbulence_noise_scale() const { +float ParticleProcessMaterial::get_turbulence_noise_scale() const { return turbulence_noise_scale; } -void ParticlesMaterial::set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random) { +void ParticleProcessMaterial::set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random) { turbulence_noise_speed_random = p_turbulence_noise_speed_random; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed_random, p_turbulence_noise_speed_random); } -float ParticlesMaterial::get_turbulence_noise_speed_random() const { +float ParticleProcessMaterial::get_turbulence_noise_speed_random() const { return turbulence_noise_speed_random; } -void ParticlesMaterial::set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed) { +void ParticleProcessMaterial::set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed) { turbulence_noise_speed = p_turbulence_noise_speed; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed, turbulence_noise_speed); } -Vector3 ParticlesMaterial::get_turbulence_noise_speed() const { +Vector3 ParticleProcessMaterial::get_turbulence_noise_speed() const { return turbulence_noise_speed; } -void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { +void ParticleProcessMaterial::set_gravity(const Vector3 &p_gravity) { gravity = p_gravity; Vector3 gset = gravity; if (gset == Vector3()) { @@ -1368,25 +1382,25 @@ void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); } -Vector3 ParticlesMaterial::get_gravity() const { +Vector3 ParticleProcessMaterial::get_gravity() const { return gravity; } -void ParticlesMaterial::set_lifetime_randomness(double p_lifetime) { +void ParticleProcessMaterial::set_lifetime_randomness(double p_lifetime) { lifetime_randomness = p_lifetime; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->lifetime_randomness, lifetime_randomness); } -double ParticlesMaterial::get_lifetime_randomness() const { +double ParticleProcessMaterial::get_lifetime_randomness() const { return lifetime_randomness; } -RID ParticlesMaterial::get_shader_rid() const { +RID ParticleProcessMaterial::get_shader_rid() const { ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); return shader_map[current_key].shader; } -void ParticlesMaterial::_validate_property(PropertyInfo &p_property) const { +void ParticleProcessMaterial::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE)) { p_property.usage = PROPERTY_USAGE_NONE; } @@ -1436,204 +1450,213 @@ void ParticlesMaterial::_validate_property(PropertyInfo &p_property) const { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } + + if (p_property.name == "collision_friction" && collision_mode != COLLISION_RIGID) { + p_property.usage = PROPERTY_USAGE_NONE; + } + + if (p_property.name == "collision_bounce" && collision_mode != COLLISION_RIGID) { + p_property.usage = PROPERTY_USAGE_NONE; + } } -void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { +void ParticleProcessMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { sub_emitter_mode = p_sub_emitter_mode; _queue_shader_change(); notify_property_list_changed(); } -ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() const { +ParticleProcessMaterial::SubEmitterMode ParticleProcessMaterial::get_sub_emitter_mode() const { return sub_emitter_mode; } -void ParticlesMaterial::set_sub_emitter_frequency(double p_frequency) { +void ParticleProcessMaterial::set_sub_emitter_frequency(double p_frequency) { sub_emitter_frequency = p_frequency; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pass delta instead of frequency, since its easier to compute } -double ParticlesMaterial::get_sub_emitter_frequency() const { +double ParticleProcessMaterial::get_sub_emitter_frequency() const { return sub_emitter_frequency; } -void ParticlesMaterial::set_sub_emitter_amount_at_end(int p_amount) { +void ParticleProcessMaterial::set_sub_emitter_amount_at_end(int p_amount) { sub_emitter_amount_at_end = p_amount; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_amount_at_end, p_amount); } -int ParticlesMaterial::get_sub_emitter_amount_at_end() const { +int ParticleProcessMaterial::get_sub_emitter_amount_at_end() const { return sub_emitter_amount_at_end; } -void ParticlesMaterial::set_sub_emitter_keep_velocity(bool p_enable) { +void ParticleProcessMaterial::set_sub_emitter_keep_velocity(bool p_enable) { sub_emitter_keep_velocity = p_enable; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_keep_velocity, p_enable); } -bool ParticlesMaterial::get_sub_emitter_keep_velocity() const { +bool ParticleProcessMaterial::get_sub_emitter_keep_velocity() const { return sub_emitter_keep_velocity; } -void ParticlesMaterial::set_attractor_interaction_enabled(bool p_enable) { +void ParticleProcessMaterial::set_attractor_interaction_enabled(bool p_enable) { attractor_interaction_enabled = p_enable; _queue_shader_change(); } -bool ParticlesMaterial::is_attractor_interaction_enabled() const { +bool ParticleProcessMaterial::is_attractor_interaction_enabled() const { return attractor_interaction_enabled; } -void ParticlesMaterial::set_collision_enabled(bool p_enabled) { - collision_enabled = p_enabled; +void ParticleProcessMaterial::set_collision_mode(CollisionMode p_collision_mode) { + collision_mode = p_collision_mode; _queue_shader_change(); + notify_property_list_changed(); } -bool ParticlesMaterial::is_collision_enabled() const { - return collision_enabled; +ParticleProcessMaterial::CollisionMode ParticleProcessMaterial::get_collision_mode() const { + return collision_mode; } -void ParticlesMaterial::set_collision_use_scale(bool p_scale) { +void ParticleProcessMaterial::set_collision_use_scale(bool p_scale) { collision_scale = p_scale; _queue_shader_change(); } -bool ParticlesMaterial::is_collision_using_scale() const { +bool ParticleProcessMaterial::is_collision_using_scale() const { return collision_scale; } -void ParticlesMaterial::set_collision_friction(float p_friction) { +void ParticleProcessMaterial::set_collision_friction(float p_friction) { collision_friction = p_friction; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->collision_friction, p_friction); } -float ParticlesMaterial::get_collision_friction() const { +float ParticleProcessMaterial::get_collision_friction() const { return collision_friction; } -void ParticlesMaterial::set_collision_bounce(float p_bounce) { +void ParticleProcessMaterial::set_collision_bounce(float p_bounce) { collision_bounce = p_bounce; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->collision_bounce, p_bounce); } -float ParticlesMaterial::get_collision_bounce() const { +float ParticleProcessMaterial::get_collision_bounce() const { return collision_bounce; } -Shader::Mode ParticlesMaterial::get_shader_mode() const { +Shader::Mode ParticleProcessMaterial::get_shader_mode() const { return Shader::MODE_PARTICLES; } -void ParticlesMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_direction", "degrees"), &ParticlesMaterial::set_direction); - ClassDB::bind_method(D_METHOD("get_direction"), &ParticlesMaterial::get_direction); +void ParticleProcessMaterial::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_direction", "degrees"), &ParticleProcessMaterial::set_direction); + ClassDB::bind_method(D_METHOD("get_direction"), &ParticleProcessMaterial::get_direction); - ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &ParticlesMaterial::set_spread); - ClassDB::bind_method(D_METHOD("get_spread"), &ParticlesMaterial::get_spread); + ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &ParticleProcessMaterial::set_spread); + ClassDB::bind_method(D_METHOD("get_spread"), &ParticleProcessMaterial::get_spread); - ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &ParticlesMaterial::set_flatness); - ClassDB::bind_method(D_METHOD("get_flatness"), &ParticlesMaterial::get_flatness); + ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &ParticleProcessMaterial::set_flatness); + ClassDB::bind_method(D_METHOD("get_flatness"), &ParticleProcessMaterial::get_flatness); - ClassDB::bind_method(D_METHOD("set_param_min", "param", "value"), &ParticlesMaterial::set_param_min); - ClassDB::bind_method(D_METHOD("get_param_min", "param"), &ParticlesMaterial::get_param_min); + ClassDB::bind_method(D_METHOD("set_param_min", "param", "value"), &ParticleProcessMaterial::set_param_min); + ClassDB::bind_method(D_METHOD("get_param_min", "param"), &ParticleProcessMaterial::get_param_min); - ClassDB::bind_method(D_METHOD("set_param_max", "param", "value"), &ParticlesMaterial::set_param_max); - ClassDB::bind_method(D_METHOD("get_param_max", "param"), &ParticlesMaterial::get_param_max); + ClassDB::bind_method(D_METHOD("set_param_max", "param", "value"), &ParticleProcessMaterial::set_param_max); + ClassDB::bind_method(D_METHOD("get_param_max", "param"), &ParticleProcessMaterial::get_param_max); - ClassDB::bind_method(D_METHOD("set_param_texture", "param", "texture"), &ParticlesMaterial::set_param_texture); - ClassDB::bind_method(D_METHOD("get_param_texture", "param"), &ParticlesMaterial::get_param_texture); + ClassDB::bind_method(D_METHOD("set_param_texture", "param", "texture"), &ParticleProcessMaterial::set_param_texture); + ClassDB::bind_method(D_METHOD("get_param_texture", "param"), &ParticleProcessMaterial::get_param_texture); - ClassDB::bind_method(D_METHOD("set_color", "color"), &ParticlesMaterial::set_color); - ClassDB::bind_method(D_METHOD("get_color"), &ParticlesMaterial::get_color); + ClassDB::bind_method(D_METHOD("set_color", "color"), &ParticleProcessMaterial::set_color); + ClassDB::bind_method(D_METHOD("get_color"), &ParticleProcessMaterial::get_color); - ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &ParticlesMaterial::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp"), &ParticlesMaterial::get_color_ramp); + ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &ParticleProcessMaterial::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &ParticleProcessMaterial::get_color_ramp); - ClassDB::bind_method(D_METHOD("set_color_initial_ramp", "ramp"), &ParticlesMaterial::set_color_initial_ramp); - ClassDB::bind_method(D_METHOD("get_color_initial_ramp"), &ParticlesMaterial::get_color_initial_ramp); + ClassDB::bind_method(D_METHOD("set_color_initial_ramp", "ramp"), &ParticleProcessMaterial::set_color_initial_ramp); + ClassDB::bind_method(D_METHOD("get_color_initial_ramp"), &ParticleProcessMaterial::get_color_initial_ramp); - ClassDB::bind_method(D_METHOD("set_particle_flag", "particle_flag", "enable"), &ParticlesMaterial::set_particle_flag); - ClassDB::bind_method(D_METHOD("get_particle_flag", "particle_flag"), &ParticlesMaterial::get_particle_flag); + ClassDB::bind_method(D_METHOD("set_particle_flag", "particle_flag", "enable"), &ParticleProcessMaterial::set_particle_flag); + ClassDB::bind_method(D_METHOD("get_particle_flag", "particle_flag"), &ParticleProcessMaterial::get_particle_flag); - ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &ParticlesMaterial::set_emission_shape); - ClassDB::bind_method(D_METHOD("get_emission_shape"), &ParticlesMaterial::get_emission_shape); + ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &ParticleProcessMaterial::set_emission_shape); + ClassDB::bind_method(D_METHOD("get_emission_shape"), &ParticleProcessMaterial::get_emission_shape); - ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &ParticlesMaterial::set_emission_sphere_radius); - ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &ParticlesMaterial::get_emission_sphere_radius); + ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &ParticleProcessMaterial::set_emission_sphere_radius); + ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &ParticleProcessMaterial::get_emission_sphere_radius); - ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &ParticlesMaterial::set_emission_box_extents); - ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &ParticlesMaterial::get_emission_box_extents); + ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &ParticleProcessMaterial::set_emission_box_extents); + ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &ParticleProcessMaterial::get_emission_box_extents); - ClassDB::bind_method(D_METHOD("set_emission_point_texture", "texture"), &ParticlesMaterial::set_emission_point_texture); - ClassDB::bind_method(D_METHOD("get_emission_point_texture"), &ParticlesMaterial::get_emission_point_texture); + ClassDB::bind_method(D_METHOD("set_emission_point_texture", "texture"), &ParticleProcessMaterial::set_emission_point_texture); + ClassDB::bind_method(D_METHOD("get_emission_point_texture"), &ParticleProcessMaterial::get_emission_point_texture); - ClassDB::bind_method(D_METHOD("set_emission_normal_texture", "texture"), &ParticlesMaterial::set_emission_normal_texture); - ClassDB::bind_method(D_METHOD("get_emission_normal_texture"), &ParticlesMaterial::get_emission_normal_texture); + ClassDB::bind_method(D_METHOD("set_emission_normal_texture", "texture"), &ParticleProcessMaterial::set_emission_normal_texture); + ClassDB::bind_method(D_METHOD("get_emission_normal_texture"), &ParticleProcessMaterial::get_emission_normal_texture); - ClassDB::bind_method(D_METHOD("set_emission_color_texture", "texture"), &ParticlesMaterial::set_emission_color_texture); - ClassDB::bind_method(D_METHOD("get_emission_color_texture"), &ParticlesMaterial::get_emission_color_texture); + ClassDB::bind_method(D_METHOD("set_emission_color_texture", "texture"), &ParticleProcessMaterial::set_emission_color_texture); + ClassDB::bind_method(D_METHOD("get_emission_color_texture"), &ParticleProcessMaterial::get_emission_color_texture); - ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); - ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); + ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticleProcessMaterial::set_emission_point_count); + ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticleProcessMaterial::get_emission_point_count); - ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &ParticlesMaterial::set_emission_ring_axis); - ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &ParticlesMaterial::get_emission_ring_axis); + ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &ParticleProcessMaterial::set_emission_ring_axis); + ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &ParticleProcessMaterial::get_emission_ring_axis); - ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &ParticlesMaterial::set_emission_ring_height); - ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &ParticlesMaterial::get_emission_ring_height); + ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &ParticleProcessMaterial::set_emission_ring_height); + ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &ParticleProcessMaterial::get_emission_ring_height); - ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &ParticlesMaterial::set_emission_ring_radius); - ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &ParticlesMaterial::get_emission_ring_radius); + ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &ParticleProcessMaterial::set_emission_ring_radius); + ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &ParticleProcessMaterial::get_emission_ring_radius); - ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &ParticlesMaterial::set_emission_ring_inner_radius); - ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticlesMaterial::get_emission_ring_inner_radius); + ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &ParticleProcessMaterial::set_emission_ring_inner_radius); + ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticleProcessMaterial::get_emission_ring_inner_radius); - ClassDB::bind_method(D_METHOD("get_turbulence_enabled"), &ParticlesMaterial::get_turbulence_enabled); - ClassDB::bind_method(D_METHOD("set_turbulence_enabled", "turbulence_enabled"), &ParticlesMaterial::set_turbulence_enabled); + ClassDB::bind_method(D_METHOD("get_turbulence_enabled"), &ParticleProcessMaterial::get_turbulence_enabled); + ClassDB::bind_method(D_METHOD("set_turbulence_enabled", "turbulence_enabled"), &ParticleProcessMaterial::set_turbulence_enabled); - ClassDB::bind_method(D_METHOD("get_turbulence_noise_strength"), &ParticlesMaterial::get_turbulence_noise_strength); - ClassDB::bind_method(D_METHOD("set_turbulence_noise_strength", "turbulence_noise_strength"), &ParticlesMaterial::set_turbulence_noise_strength); + ClassDB::bind_method(D_METHOD("get_turbulence_noise_strength"), &ParticleProcessMaterial::get_turbulence_noise_strength); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_strength", "turbulence_noise_strength"), &ParticleProcessMaterial::set_turbulence_noise_strength); - ClassDB::bind_method(D_METHOD("get_turbulence_noise_scale"), &ParticlesMaterial::get_turbulence_noise_scale); - ClassDB::bind_method(D_METHOD("set_turbulence_noise_scale", "turbulence_noise_scale"), &ParticlesMaterial::set_turbulence_noise_scale); + ClassDB::bind_method(D_METHOD("get_turbulence_noise_scale"), &ParticleProcessMaterial::get_turbulence_noise_scale); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_scale", "turbulence_noise_scale"), &ParticleProcessMaterial::set_turbulence_noise_scale); - ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed_random"), &ParticlesMaterial::get_turbulence_noise_speed_random); - ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed_random", "turbulence_noise_speed_random"), &ParticlesMaterial::set_turbulence_noise_speed_random); + ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed_random"), &ParticleProcessMaterial::get_turbulence_noise_speed_random); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed_random", "turbulence_noise_speed_random"), &ParticleProcessMaterial::set_turbulence_noise_speed_random); - ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed"), &ParticlesMaterial::get_turbulence_noise_speed); - ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed", "turbulence_noise_speed"), &ParticlesMaterial::set_turbulence_noise_speed); + ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed"), &ParticleProcessMaterial::get_turbulence_noise_speed); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed", "turbulence_noise_speed"), &ParticleProcessMaterial::set_turbulence_noise_speed); - ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); - ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); + ClassDB::bind_method(D_METHOD("get_gravity"), &ParticleProcessMaterial::get_gravity); + ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticleProcessMaterial::set_gravity); - ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "randomness"), &ParticlesMaterial::set_lifetime_randomness); - ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &ParticlesMaterial::get_lifetime_randomness); + ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "randomness"), &ParticleProcessMaterial::set_lifetime_randomness); + ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &ParticleProcessMaterial::get_lifetime_randomness); - ClassDB::bind_method(D_METHOD("get_sub_emitter_mode"), &ParticlesMaterial::get_sub_emitter_mode); - ClassDB::bind_method(D_METHOD("set_sub_emitter_mode", "mode"), &ParticlesMaterial::set_sub_emitter_mode); + ClassDB::bind_method(D_METHOD("get_sub_emitter_mode"), &ParticleProcessMaterial::get_sub_emitter_mode); + ClassDB::bind_method(D_METHOD("set_sub_emitter_mode", "mode"), &ParticleProcessMaterial::set_sub_emitter_mode); - ClassDB::bind_method(D_METHOD("get_sub_emitter_frequency"), &ParticlesMaterial::get_sub_emitter_frequency); - ClassDB::bind_method(D_METHOD("set_sub_emitter_frequency", "hz"), &ParticlesMaterial::set_sub_emitter_frequency); + ClassDB::bind_method(D_METHOD("get_sub_emitter_frequency"), &ParticleProcessMaterial::get_sub_emitter_frequency); + ClassDB::bind_method(D_METHOD("set_sub_emitter_frequency", "hz"), &ParticleProcessMaterial::set_sub_emitter_frequency); - ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_end"), &ParticlesMaterial::get_sub_emitter_amount_at_end); - ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_end", "amount"), &ParticlesMaterial::set_sub_emitter_amount_at_end); + ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_end"), &ParticleProcessMaterial::get_sub_emitter_amount_at_end); + ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_end", "amount"), &ParticleProcessMaterial::set_sub_emitter_amount_at_end); - ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticlesMaterial::get_sub_emitter_keep_velocity); - ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticlesMaterial::set_sub_emitter_keep_velocity); + ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticleProcessMaterial::get_sub_emitter_keep_velocity); + ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticleProcessMaterial::set_sub_emitter_keep_velocity); - ClassDB::bind_method(D_METHOD("set_attractor_interaction_enabled", "enabled"), &ParticlesMaterial::set_attractor_interaction_enabled); - ClassDB::bind_method(D_METHOD("is_attractor_interaction_enabled"), &ParticlesMaterial::is_attractor_interaction_enabled); + ClassDB::bind_method(D_METHOD("set_attractor_interaction_enabled", "enabled"), &ParticleProcessMaterial::set_attractor_interaction_enabled); + ClassDB::bind_method(D_METHOD("is_attractor_interaction_enabled"), &ParticleProcessMaterial::is_attractor_interaction_enabled); - ClassDB::bind_method(D_METHOD("set_collision_enabled", "enabled"), &ParticlesMaterial::set_collision_enabled); - ClassDB::bind_method(D_METHOD("is_collision_enabled"), &ParticlesMaterial::is_collision_enabled); + ClassDB::bind_method(D_METHOD("set_collision_mode", "mode"), &ParticleProcessMaterial::set_collision_mode); + ClassDB::bind_method(D_METHOD("get_collision_mode"), &ParticleProcessMaterial::get_collision_mode); - ClassDB::bind_method(D_METHOD("set_collision_use_scale", "radius"), &ParticlesMaterial::set_collision_use_scale); - ClassDB::bind_method(D_METHOD("is_collision_using_scale"), &ParticlesMaterial::is_collision_using_scale); + ClassDB::bind_method(D_METHOD("set_collision_use_scale", "radius"), &ParticleProcessMaterial::set_collision_use_scale); + ClassDB::bind_method(D_METHOD("is_collision_using_scale"), &ParticleProcessMaterial::is_collision_using_scale); - ClassDB::bind_method(D_METHOD("set_collision_friction", "friction"), &ParticlesMaterial::set_collision_friction); - ClassDB::bind_method(D_METHOD("get_collision_friction"), &ParticlesMaterial::get_collision_friction); + ClassDB::bind_method(D_METHOD("set_collision_friction", "friction"), &ParticleProcessMaterial::set_collision_friction); + ClassDB::bind_method(D_METHOD("get_collision_friction"), &ParticleProcessMaterial::get_collision_friction); - ClassDB::bind_method(D_METHOD("set_collision_bounce", "bounce"), &ParticlesMaterial::set_collision_bounce); - ClassDB::bind_method(D_METHOD("get_collision_bounce"), &ParticlesMaterial::get_collision_bounce); + ClassDB::bind_method(D_METHOD("set_collision_bounce", "bounce"), &ParticleProcessMaterial::set_collision_bounce); + ClassDB::bind_method(D_METHOD("get_collision_bounce"), &ParticleProcessMaterial::get_collision_bounce); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); @@ -1734,7 +1757,7 @@ void ParticlesMaterial::_bind_methods() { ADD_GROUP("Attractor Interaction", "attractor_interaction_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "attractor_interaction_enabled"), "set_attractor_interaction_enabled", "is_attractor_interaction_enabled"); ADD_GROUP("Collision", "collision_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_enabled"), "set_collision_enabled", "is_collision_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mode", PROPERTY_HINT_ENUM, "Disabled,Rigid,Hide On Contact"), "set_collision_mode", "get_collision_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_friction", "get_collision_friction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_scale"), "set_collision_use_scale", "is_collision_using_scale"); @@ -1776,9 +1799,14 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END); BIND_ENUM_CONSTANT(SUB_EMITTER_AT_COLLISION); BIND_ENUM_CONSTANT(SUB_EMITTER_MAX); + + BIND_ENUM_CONSTANT(COLLISION_DISABLED); + BIND_ENUM_CONSTANT(COLLISION_RIGID); + BIND_ENUM_CONSTANT(COLLISION_HIDE_ON_CONTACT); + BIND_ENUM_CONSTANT(COLLISION_MAX); } -ParticlesMaterial::ParticlesMaterial() : +ParticleProcessMaterial::ParticleProcessMaterial() : element(this) { set_direction(Vector3(1, 0, 0)); set_spread(45); @@ -1834,7 +1862,7 @@ ParticlesMaterial::ParticlesMaterial() : set_sub_emitter_keep_velocity(false); set_attractor_interaction_enabled(true); - set_collision_enabled(false); + set_collision_mode(COLLISION_DISABLED); set_collision_bounce(0.0); set_collision_friction(0.0); set_collision_use_scale(false); @@ -1851,7 +1879,7 @@ ParticlesMaterial::ParticlesMaterial() : _queue_shader_change(); } -ParticlesMaterial::~ParticlesMaterial() { +ParticleProcessMaterial::~ParticleProcessMaterial() { MutexLock lock(material_mutex); if (shader_map.has(current_key)) { diff --git a/scene/resources/particles_material.h b/scene/resources/particle_process_material.h index 116d8b7d06..fe4741d6e5 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particle_process_material.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* particles_material.h */ +/* particle_process_material.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,8 +31,8 @@ #include "core/templates/rid.h" #include "scene/resources/material.h" -#ifndef PARTICLES_MATERIAL_H -#define PARTICLES_MATERIAL_H +#ifndef PARTICLE_PROCESS_MATERIAL_H +#define PARTICLE_PROCESS_MATERIAL_H /* TODO: @@ -41,8 +41,8 @@ -Proper trails */ -class ParticlesMaterial : public Material { - GDCLASS(ParticlesMaterial, Material); +class ParticleProcessMaterial : public Material { + GDCLASS(ParticleProcessMaterial, Material); public: enum Parameter { @@ -93,6 +93,14 @@ public: SUB_EMITTER_MAX }; + // When extending, make sure not to overflow the size of the MaterialKey below. + enum CollisionMode { + COLLISION_DISABLED, + COLLISION_RIGID, + COLLISION_HIDE_ON_CONTACT, + COLLISION_MAX + }; + private: union MaterialKey { // The bit size of the struct must be kept below or equal to 32 bits. @@ -106,7 +114,7 @@ private: uint32_t has_emission_color : 1; uint32_t sub_emitter : 2; uint32_t attractor_enabled : 1; - uint32_t collision_enabled : 1; + uint32_t collision_mode : 2; uint32_t collision_scale : 1; uint32_t turbulence_enabled : 1; }; @@ -153,7 +161,7 @@ private: mk.emission_shape = emission_shape; mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); mk.sub_emitter = sub_emitter_mode; - mk.collision_enabled = collision_enabled; + mk.collision_mode = collision_mode; mk.attractor_enabled = attractor_interaction_enabled; mk.collision_scale = collision_scale; mk.turbulence_enabled = turbulence_enabled; @@ -162,7 +170,7 @@ private: } static Mutex material_mutex; - static SelfList<ParticlesMaterial>::List *dirty_materials; + static SelfList<ParticleProcessMaterial>::List *dirty_materials; struct ShaderNames { StringName direction; @@ -246,7 +254,7 @@ private: static ShaderNames *shader_names; - SelfList<ParticlesMaterial> element; + SelfList<ParticleProcessMaterial> element; void _update_shader(); _FORCE_INLINE_ void _queue_shader_change(); @@ -300,7 +308,7 @@ private: //do not save emission points here bool attractor_interaction_enabled = false; - bool collision_enabled = false; + CollisionMode collision_mode; bool collision_scale = false; float collision_friction = 0.0f; float collision_bounce = 0.0f; @@ -385,8 +393,8 @@ public: void set_attractor_interaction_enabled(bool p_enable); bool is_attractor_interaction_enabled() const; - void set_collision_enabled(bool p_enabled); - bool is_collision_enabled() const; + void set_collision_mode(CollisionMode p_collision_mode); + CollisionMode get_collision_mode() const; void set_collision_use_scale(bool p_scale); bool is_collision_using_scale() const; @@ -417,13 +425,14 @@ public: virtual Shader::Mode get_shader_mode() const override; - ParticlesMaterial(); - ~ParticlesMaterial(); + ParticleProcessMaterial(); + ~ParticleProcessMaterial(); }; -VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) -VARIANT_ENUM_CAST(ParticlesMaterial::ParticleFlags) -VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) -VARIANT_ENUM_CAST(ParticlesMaterial::SubEmitterMode) +VARIANT_ENUM_CAST(ParticleProcessMaterial::Parameter) +VARIANT_ENUM_CAST(ParticleProcessMaterial::ParticleFlags) +VARIANT_ENUM_CAST(ParticleProcessMaterial::EmissionShape) +VARIANT_ENUM_CAST(ParticleProcessMaterial::SubEmitterMode) +VARIANT_ENUM_CAST(ParticleProcessMaterial::CollisionMode) -#endif // PARTICLES_MATERIAL_H +#endif // PARTICLE_PROCESS_MATERIAL_H diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index ec0212a727..e993936350 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -990,6 +990,13 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const { Size2 start_pos = size * -0.5; + Vector3 normal = Vector3(0.0, 1.0, 0.0); + if (orientation == FACE_X) { + normal = Vector3(1.0, 0.0, 0.0); + } else if (orientation == FACE_Z) { + normal = Vector3(0.0, 0.0, 1.0); + } + Vector<Vector3> points; Vector<Vector3> normals; Vector<float> tangents; @@ -1015,8 +1022,14 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const { u /= (subdivide_w + 1.0); v /= (subdivide_d + 1.0); - points.push_back(Vector3(-x, 0.0, -z) + center_offset); - normals.push_back(Vector3(0.0, 1.0, 0.0)); + if (orientation == FACE_X) { + points.push_back(Vector3(0.0, z, x) + center_offset); + } else if (orientation == FACE_Y) { + points.push_back(Vector3(-x, 0.0, -z) + center_offset); + } else if (orientation == FACE_Z) { + points.push_back(Vector3(-x, z, 0.0) + center_offset); + } + normals.push_back(normal); ADD_TANGENT(1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */ point++; @@ -1053,13 +1066,22 @@ void PlaneMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width); ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth); ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth); + ClassDB::bind_method(D_METHOD("set_center_offset", "offset"), &PlaneMesh::set_center_offset); ClassDB::bind_method(D_METHOD("get_center_offset"), &PlaneMesh::get_center_offset); + ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &PlaneMesh::set_orientation); + ClassDB::bind_method(D_METHOD("get_orientation"), &PlaneMesh::get_orientation); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "orientation", PROPERTY_HINT_ENUM, "Face X, Face Y, Face Z"), "set_orientation", "get_orientation"); + + BIND_ENUM_CONSTANT(FACE_X) + BIND_ENUM_CONSTANT(FACE_Y) + BIND_ENUM_CONSTANT(FACE_Z) } void PlaneMesh::set_size(const Size2 &p_size) { @@ -1098,6 +1120,15 @@ Vector3 PlaneMesh::get_center_offset() const { return center_offset; } +void PlaneMesh::set_orientation(const Orientation p_orientation) { + orientation = p_orientation; + _request_update(); +} + +PlaneMesh::Orientation PlaneMesh::get_orientation() const { + return orientation; +} + PlaneMesh::PlaneMesh() {} /** @@ -1381,98 +1412,6 @@ int PrismMesh::get_subdivide_depth() const { PrismMesh::PrismMesh() {} /** - QuadMesh -*/ - -void QuadMesh::_create_mesh_array(Array &p_arr) const { - Vector<Vector3> faces; - Vector<Vector3> normals; - Vector<float> tangents; - Vector<Vector2> uvs; - - faces.resize(6); - normals.resize(6); - tangents.resize(6 * 4); - uvs.resize(6); - - Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f); - - Vector3 quad_faces[4] = { - Vector3(-_size.x, -_size.y, 0) + center_offset, - Vector3(-_size.x, _size.y, 0) + center_offset, - Vector3(_size.x, _size.y, 0) + center_offset, - Vector3(_size.x, -_size.y, 0) + center_offset, - }; - - static const int indices[6] = { - 0, 1, 2, - 0, 2, 3 - }; - - for (int i = 0; i < 6; i++) { - int j = indices[i]; - faces.set(i, quad_faces[j]); - normals.set(i, Vector3(0, 0, 1)); - tangents.set(i * 4 + 0, 1.0); - tangents.set(i * 4 + 1, 0.0); - tangents.set(i * 4 + 2, 0.0); - tangents.set(i * 4 + 3, 1.0); - - static const Vector2 quad_uv[4] = { - Vector2(0, 1), - Vector2(0, 0), - Vector2(1, 0), - Vector2(1, 1), - }; - - uvs.set(i, quad_uv[j]); - } - - p_arr[RS::ARRAY_VERTEX] = faces; - p_arr[RS::ARRAY_NORMAL] = normals; - p_arr[RS::ARRAY_TANGENT] = tangents; - p_arr[RS::ARRAY_TEX_UV] = uvs; -} - -void QuadMesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadMesh::set_size); - ClassDB::bind_method(D_METHOD("get_size"), &QuadMesh::get_size); - ClassDB::bind_method(D_METHOD("set_center_offset", "center_offset"), &QuadMesh::set_center_offset); - ClassDB::bind_method(D_METHOD("get_center_offset"), &QuadMesh::get_center_offset); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset"); -} - -uint32_t QuadMesh::surface_get_format(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, 1, 0); - - return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV; -} - -QuadMesh::QuadMesh() { - primitive_type = PRIMITIVE_TRIANGLES; -} - -void QuadMesh::set_size(const Size2 &p_size) { - size = p_size; - _request_update(); -} - -Size2 QuadMesh::get_size() const { - return size; -} - -void QuadMesh::set_center_offset(Vector3 p_center_offset) { - center_offset = p_center_offset; - _request_update(); -} - -Vector3 QuadMesh::get_center_offset() const { - return center_offset; -} - -/** SphereMesh */ @@ -2519,9 +2458,7 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { dirty_text = false; dirty_font = false; - if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - TS->shaped_text_fit_to_width(text_rid, width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); - } + dirty_lines = true; } else if (dirty_font) { int spans = TS->shaped_get_span_count(text_rid); for (int i = 0; i < spans; i++) { @@ -2532,81 +2469,138 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { } dirty_font = false; + dirty_lines = true; + } + + if (dirty_lines) { + for (int i = 0; i < lines_rid.size(); i++) { + TS->free_rid(lines_rid[i]); + } + lines_rid.clear(); + + BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; + switch (autowrap_mode) { + case TextServer::AUTOWRAP_WORD_SMART: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_WORD: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_ARBITRARY: + autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_OFF: + break; + } + PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); + + float max_line_w = 0.0; + for (int i = 0; i < line_breaks.size(); i = i + 2) { + RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); + max_line_w = MAX(max_line_w, TS->shaped_text_get_width(line)); + lines_rid.push_back(line); + } + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - TS->shaped_text_fit_to_width(text_rid, width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); + for (int i = 0; i < lines_rid.size() - 1; i++) { + TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); + } } + dirty_lines = false; } - Vector2 offset; - const Glyph *glyphs = TS->shaped_text_get_glyphs(text_rid); - int gl_size = TS->shaped_text_get_glyph_count(text_rid); - float line_width = TS->shaped_text_get_width(text_rid) * pixel_size; - - switch (horizontal_alignment) { - case HORIZONTAL_ALIGNMENT_LEFT: - offset.x = 0.0; - break; - case HORIZONTAL_ALIGNMENT_FILL: - case HORIZONTAL_ALIGNMENT_CENTER: { - offset.x = -line_width / 2.0; + float total_h = 0.0; + for (int i = 0; i < lines_rid.size(); i++) { + total_h += (TS->shaped_text_get_size(lines_rid[i]).y + line_spacing) * pixel_size; + } + + float vbegin = 0.0; + switch (vertical_alignment) { + case VERTICAL_ALIGNMENT_FILL: + case VERTICAL_ALIGNMENT_TOP: { + // Nothing. + } break; + case VERTICAL_ALIGNMENT_CENTER: { + vbegin = (total_h - line_spacing * pixel_size) / 2.0; } break; - case HORIZONTAL_ALIGNMENT_RIGHT: { - offset.x = -line_width; + case VERTICAL_ALIGNMENT_BOTTOM: { + vbegin = (total_h - line_spacing * pixel_size); } break; } - bool has_depth = !Math::is_zero_approx(depth); - - // Generate glyph data, precalculate size of the arrays and mesh bounds for UV. - int64_t p_size = 0; - int64_t i_size = 0; + Vector<Vector3> vertices; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int32_t> indices; Vector2 min_p = Vector2(INFINITY, INFINITY); Vector2 max_p = Vector2(-INFINITY, -INFINITY); - Vector2 offset_pre = offset; - for (int i = 0; i < gl_size; i++) { - if (glyphs[i].index == 0) { - offset.x += glyphs[i].advance * pixel_size * glyphs[i].repeat; - continue; + int32_t p_size = 0; + int32_t i_size = 0; + + Vector2 offset = Vector2(0, vbegin + lbl_offset.y * pixel_size); + for (int i = 0; i < lines_rid.size(); i++) { + const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); + int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]); + float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size; + + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_LEFT: + offset.x = 0.0; + break; + case HORIZONTAL_ALIGNMENT_FILL: + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = -line_width / 2.0; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + offset.x = -line_width; + } break; } - if (glyphs[i].font_rid != RID()) { - GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index); - _generate_glyph_mesh_data(key, glyphs[i]); - GlyphMeshData &gl_data = cache[key]; - - p_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); - i_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); - - if (has_depth) { - for (int j = 0; j < gl_data.contours.size(); j++) { - p_size += glyphs[i].repeat * gl_data.contours[j].size() * 4; - i_size += glyphs[i].repeat * gl_data.contours[j].size() * 6; - } - } + offset.x += lbl_offset.x * pixel_size; + offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size; - for (int j = 0; j < glyphs[i].repeat; j++) { - min_p.x = MIN(gl_data.min_p.x + offset_pre.x, min_p.x); - min_p.y = MIN(gl_data.min_p.y + offset_pre.y, min_p.y); - max_p.x = MAX(gl_data.max_p.x + offset_pre.x, max_p.x); - max_p.y = MAX(gl_data.max_p.y + offset_pre.y, max_p.y); + bool has_depth = !Math::is_zero_approx(depth); - offset_pre.x += glyphs[i].advance * pixel_size; + for (int j = 0; j < gl_size; j++) { + if (glyphs[j].index == 0) { + offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat; + continue; } - } else { - p_size += glyphs[i].repeat * 4; - i_size += glyphs[i].repeat * 6; + if (glyphs[j].font_rid != RID()) { + GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index); + _generate_glyph_mesh_data(key, glyphs[j]); + GlyphMeshData &gl_data = cache[key]; + + p_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); + i_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); - offset_pre.x += glyphs[i].advance * pixel_size * glyphs[i].repeat; + if (has_depth) { + for (int k = 0; k < gl_data.contours.size(); k++) { + p_size += glyphs[j].repeat * gl_data.contours[k].size() * 4; + i_size += glyphs[j].repeat * gl_data.contours[k].size() * 6; + } + } + + for (int r = 0; r < glyphs[j].repeat; r++) { + min_p.x = MIN(gl_data.min_p.x + offset.x, min_p.x); + min_p.y = MIN(gl_data.min_p.y - offset.y, min_p.y); + max_p.x = MAX(gl_data.max_p.x + offset.x, max_p.x); + max_p.y = MAX(gl_data.max_p.y - offset.y, max_p.y); + + offset.x += glyphs[j].advance * pixel_size; + } + } else { + p_size += glyphs[j].repeat * 4; + i_size += glyphs[j].repeat * 6; + + offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat; + } } + offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size; } - Vector<Vector3> vertices; - Vector<Vector3> normals; - Vector<float> tangents; - Vector<Vector2> uvs; - Vector<int32_t> indices; - vertices.resize(p_size); normals.resize(p_size); uvs.resize(p_size); @@ -2622,149 +2616,176 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { // Generate mesh. int32_t p_idx = 0; int32_t i_idx = 0; - for (int i = 0; i < gl_size; i++) { - if (glyphs[i].index == 0) { - offset.x += glyphs[i].advance * pixel_size * glyphs[i].repeat; - continue; + + offset = Vector2(0, vbegin + lbl_offset.y * pixel_size); + for (int i = 0; i < lines_rid.size(); i++) { + const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); + int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]); + float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size; + + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_LEFT: + offset.x = 0.0; + break; + case HORIZONTAL_ALIGNMENT_FILL: + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = -line_width / 2.0; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + offset.x = -line_width; + } break; } - if (glyphs[i].font_rid != RID()) { - GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index); - _generate_glyph_mesh_data(key, glyphs[i]); - const GlyphMeshData &gl_data = cache[key]; - - int64_t ts = gl_data.triangles.size(); - const Vector2 *ts_ptr = gl_data.triangles.ptr(); - - for (int j = 0; j < glyphs[i].repeat; j++) { - for (int k = 0; k < ts; k += 3) { - // Add front face. - for (int l = 0; l < 3; l++) { - Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0); - vertices_ptr[p_idx] = point; - normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0); - if (has_depth) { - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.0), real_t(0.4))); - } else { - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.0), real_t(1.0))); - } - tangents_ptr[p_idx * 4 + 0] = 1.0; - tangents_ptr[p_idx * 4 + 1] = 0.0; - tangents_ptr[p_idx * 4 + 2] = 0.0; - tangents_ptr[p_idx * 4 + 3] = 1.0; - indices_ptr[i_idx++] = p_idx; - p_idx++; - } - if (has_depth) { - // Add back face. - for (int l = 2; l >= 0; l--) { - Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0); + offset.x += lbl_offset.x * pixel_size; + offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size; + + bool has_depth = !Math::is_zero_approx(depth); + + // Generate glyph data, precalculate size of the arrays and mesh bounds for UV. + for (int j = 0; j < gl_size; j++) { + if (glyphs[j].index == 0) { + offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat; + continue; + } + if (glyphs[j].font_rid != RID()) { + GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index); + _generate_glyph_mesh_data(key, glyphs[j]); + const GlyphMeshData &gl_data = cache[key]; + + int64_t ts = gl_data.triangles.size(); + const Vector2 *ts_ptr = gl_data.triangles.ptr(); + + for (int r = 0; r < glyphs[j].repeat; r++) { + for (int k = 0; k < ts; k += 3) { + // Add front face. + for (int l = 0; l < 3; l++) { + Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0); vertices_ptr[p_idx] = point; - normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0); - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.4), real_t(0.8))); - tangents_ptr[p_idx * 4 + 0] = -1.0; + normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0); + if (has_depth) { + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0))); + } else { + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0))); + } + tangents_ptr[p_idx * 4 + 0] = 1.0; tangents_ptr[p_idx * 4 + 1] = 0.0; tangents_ptr[p_idx * 4 + 2] = 0.0; tangents_ptr[p_idx * 4 + 3] = 1.0; indices_ptr[i_idx++] = p_idx; p_idx++; } - } - } - // Add sides. - if (has_depth) { - for (int k = 0; k < gl_data.contours.size(); k++) { - int64_t ps = gl_data.contours[k].size(); - const ContourPoint *ps_ptr = gl_data.contours[k].ptr(); - const ContourInfo &ps_info = gl_data.contours_info[k]; - real_t length = 0.0; - for (int l = 0; l < ps; l++) { - int prev = (l == 0) ? (ps - 1) : (l - 1); - int next = (l + 1 == ps) ? 0 : (l + 1); - Vector2 d1; - Vector2 d2 = (ps_ptr[next].point - ps_ptr[l].point).normalized(); - if (ps_ptr[l].sharp) { - d1 = d2; - } else { - d1 = (ps_ptr[l].point - ps_ptr[prev].point).normalized(); + if (has_depth) { + // Add back face. + for (int l = 2; l >= 0; l--) { + Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0); + vertices_ptr[p_idx] = point; + normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0); + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(0.8), real_t(0.4))); + tangents_ptr[p_idx * 4 + 0] = -1.0; + tangents_ptr[p_idx * 4 + 1] = 0.0; + tangents_ptr[p_idx * 4 + 2] = 0.0; + tangents_ptr[p_idx * 4 + 3] = 1.0; + indices_ptr[i_idx++] = p_idx; + p_idx++; } - real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length(); - - Vector3 quad_faces[4] = { - Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0), - Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0), - Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0), - Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0), - }; - for (int m = 0; m < 4; m++) { - const Vector2 &d = ((m % 2) == 0) ? d1 : d2; - real_t u_pos = ((m % 2) == 0) ? length : length + seg_len; - vertices_ptr[p_idx + m] = quad_faces[m]; - normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0); - if (m < 2) { - uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9); + } + } + // Add sides. + if (has_depth) { + for (int k = 0; k < gl_data.contours.size(); k++) { + int64_t ps = gl_data.contours[k].size(); + const ContourPoint *ps_ptr = gl_data.contours[k].ptr(); + const ContourInfo &ps_info = gl_data.contours_info[k]; + real_t length = 0.0; + for (int l = 0; l < ps; l++) { + int prev = (l == 0) ? (ps - 1) : (l - 1); + int next = (l + 1 == ps) ? 0 : (l + 1); + Vector2 d1; + Vector2 d2 = (ps_ptr[next].point - ps_ptr[l].point).normalized(); + if (ps_ptr[l].sharp) { + d1 = d2; } else { - uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0); + d1 = (ps_ptr[l].point - ps_ptr[prev].point).normalized(); + } + real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length(); + + Vector3 quad_faces[4] = { + Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0), + Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0), + Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0), + Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0), + }; + for (int m = 0; m < 4; m++) { + const Vector2 &d = ((m % 2) == 0) ? d1 : d2; + real_t u_pos = ((m % 2) == 0) ? length : length + seg_len; + vertices_ptr[p_idx + m] = quad_faces[m]; + normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0); + if (m < 2) { + uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9); + } else { + uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0); + } + tangents_ptr[(p_idx + m) * 4 + 0] = d.x; + tangents_ptr[(p_idx + m) * 4 + 1] = -d.y; + tangents_ptr[(p_idx + m) * 4 + 2] = 0.0; + tangents_ptr[(p_idx + m) * 4 + 3] = 1.0; } - tangents_ptr[(p_idx + m) * 4 + 0] = d.x; - tangents_ptr[(p_idx + m) * 4 + 1] = -d.y; - tangents_ptr[(p_idx + m) * 4 + 2] = 0.0; - tangents_ptr[(p_idx + m) * 4 + 3] = 1.0; - } - indices_ptr[i_idx++] = p_idx; - indices_ptr[i_idx++] = p_idx + 1; - indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx; + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 2; - indices_ptr[i_idx++] = p_idx + 1; - indices_ptr[i_idx++] = p_idx + 3; - indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 3; + indices_ptr[i_idx++] = p_idx + 2; - length += seg_len; - p_idx += 4; + length += seg_len; + p_idx += 4; + } } } + offset.x += glyphs[j].advance * pixel_size; } - offset.x += glyphs[i].advance * pixel_size; - } - } else { - // Add fallback quad for missing glyphs. - for (int j = 0; j < glyphs[i].repeat; j++) { - Size2 sz = TS->get_hex_code_box_size(glyphs[i].font_size, glyphs[i].index) * pixel_size; - Vector3 quad_faces[4] = { - Vector3(offset.x, offset.y, 0.0), - Vector3(offset.x, sz.y + offset.y, 0.0), - Vector3(sz.x + offset.x, sz.y + offset.y, 0.0), - Vector3(sz.x + offset.x, offset.y, 0.0), - }; - for (int k = 0; k < 4; k++) { - vertices_ptr[p_idx + k] = quad_faces[k]; - normals_ptr[p_idx + k] = Vector3(0.0, 0.0, 1.0); - if (has_depth) { - uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -min_p.y, -max_p.y, real_t(0.0), real_t(0.4))); - } else { - uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -min_p.y, -max_p.y, real_t(0.0), real_t(1.0))); + } else { + // Add fallback quad for missing glyphs. + for (int r = 0; r < glyphs[j].repeat; r++) { + Size2 sz = TS->get_hex_code_box_size(glyphs[j].font_size, glyphs[j].index) * pixel_size; + Vector3 quad_faces[4] = { + Vector3(offset.x, offset.y, 0.0), + Vector3(offset.x, sz.y + offset.y, 0.0), + Vector3(sz.x + offset.x, sz.y + offset.y, 0.0), + Vector3(sz.x + offset.x, offset.y, 0.0), + }; + for (int k = 0; k < 4; k++) { + vertices_ptr[p_idx + k] = quad_faces[k]; + normals_ptr[p_idx + k] = Vector3(0.0, 0.0, 1.0); + if (has_depth) { + uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0))); + } else { + uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0))); + } + tangents_ptr[(p_idx + k) * 4 + 0] = 1.0; + tangents_ptr[(p_idx + k) * 4 + 1] = 0.0; + tangents_ptr[(p_idx + k) * 4 + 2] = 0.0; + tangents_ptr[(p_idx + k) * 4 + 3] = 1.0; } - tangents_ptr[(p_idx + k) * 4 + 0] = 1.0; - tangents_ptr[(p_idx + k) * 4 + 1] = 0.0; - tangents_ptr[(p_idx + k) * 4 + 2] = 0.0; - tangents_ptr[(p_idx + k) * 4 + 3] = 1.0; - } - indices_ptr[i_idx++] = p_idx; - indices_ptr[i_idx++] = p_idx + 1; - indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx; + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 2; - indices_ptr[i_idx++] = p_idx + 0; - indices_ptr[i_idx++] = p_idx + 2; - indices_ptr[i_idx++] = p_idx + 3; - p_idx += 4; + indices_ptr[i_idx++] = p_idx + 0; + indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx + 3; + p_idx += 4; - offset.x += glyphs[i].advance * pixel_size; + offset.x += glyphs[j].advance * pixel_size; + } } } + offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size; } - if (p_size == 0) { + if (indices.is_empty()) { // If empty, add single triangle to suppress errors. vertices.push_back(Vector3()); normals.push_back(Vector3()); @@ -2789,6 +2810,9 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &TextMesh::set_horizontal_alignment); ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &TextMesh::get_horizontal_alignment); + ClassDB::bind_method(D_METHOD("set_vertical_alignment", "alignment"), &TextMesh::set_vertical_alignment); + ClassDB::bind_method(D_METHOD("get_vertical_alignment"), &TextMesh::get_vertical_alignment); + ClassDB::bind_method(D_METHOD("set_text", "text"), &TextMesh::set_text); ClassDB::bind_method(D_METHOD("get_text"), &TextMesh::get_text); @@ -2798,6 +2822,12 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_font_size", "font_size"), &TextMesh::set_font_size); ClassDB::bind_method(D_METHOD("get_font_size"), &TextMesh::get_font_size); + ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &TextMesh::set_line_spacing); + ClassDB::bind_method(D_METHOD("get_line_spacing"), &TextMesh::get_line_spacing); + + ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &TextMesh::set_autowrap_mode); + ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &TextMesh::get_autowrap_mode); + ClassDB::bind_method(D_METHOD("set_depth", "depth"), &TextMesh::set_depth); ClassDB::bind_method(D_METHOD("get_depth"), &TextMesh::get_depth); @@ -2807,6 +2837,9 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &TextMesh::set_pixel_size); ClassDB::bind_method(D_METHOD("get_pixel_size"), &TextMesh::get_pixel_size); + ClassDB::bind_method(D_METHOD("set_offset", "offset"), &TextMesh::set_offset); + ClassDB::bind_method(D_METHOD("get_offset"), &TextMesh::get_offset); + ClassDB::bind_method(D_METHOD("set_curve_step", "curve_step"), &TextMesh::set_curve_step); ClassDB::bind_method(D_METHOD("get_curve_step"), &TextMesh::get_curve_step); @@ -2829,17 +2862,21 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("_request_update"), &TextMesh::_request_update); ADD_GROUP("Text", ""); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); ADD_GROUP("Mesh", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1,suffix:px"), "set_curve_step", "get_curve_step"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater,suffix:m"), "set_depth", "get_depth"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:m"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset"); ADD_GROUP("BiDi", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction"); @@ -2868,6 +2905,11 @@ TextMesh::TextMesh() { } TextMesh::~TextMesh() { + for (int i = 0; i < lines_rid.size(); i++) { + TS->free_rid(lines_rid[i]); + } + lines_rid.clear(); + TS->free_rid(text_rid); } @@ -2875,7 +2917,7 @@ void TextMesh::set_horizontal_alignment(HorizontalAlignment p_alignment) { ERR_FAIL_INDEX((int)p_alignment, 4); if (horizontal_alignment != p_alignment) { if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL || p_alignment == HORIZONTAL_ALIGNMENT_FILL) { - dirty_text = true; + dirty_lines = true; } horizontal_alignment = p_alignment; _request_update(); @@ -2886,6 +2928,18 @@ HorizontalAlignment TextMesh::get_horizontal_alignment() const { return horizontal_alignment; } +void TextMesh::set_vertical_alignment(VerticalAlignment p_alignment) { + ERR_FAIL_INDEX((int)p_alignment, 4); + if (vertical_alignment != p_alignment) { + vertical_alignment = p_alignment; + _request_update(); + } +} + +VerticalAlignment TextMesh::get_vertical_alignment() const { + return vertical_alignment; +} + void TextMesh::set_text(const String &p_string) { if (text != p_string) { text = p_string; @@ -2970,6 +3024,29 @@ int TextMesh::get_font_size() const { return font_size; } +void TextMesh::set_line_spacing(float p_line_spacing) { + if (line_spacing != p_line_spacing) { + line_spacing = p_line_spacing; + _request_update(); + } +} + +float TextMesh::get_line_spacing() const { + return line_spacing; +} + +void TextMesh::set_autowrap_mode(TextServer::AutowrapMode p_mode) { + if (autowrap_mode != p_mode) { + autowrap_mode = p_mode; + dirty_lines = true; + _request_update(); + } +} + +TextServer::AutowrapMode TextMesh::get_autowrap_mode() const { + return autowrap_mode; +} + void TextMesh::set_depth(real_t p_depth) { if (depth != p_depth) { depth = MAX(p_depth, 0.0); @@ -2984,9 +3061,7 @@ real_t TextMesh::get_depth() const { void TextMesh::set_width(real_t p_width) { if (width != p_width) { width = p_width; - if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - dirty_text = true; - } + dirty_lines = true; _request_update(); } } @@ -3007,6 +3082,17 @@ real_t TextMesh::get_pixel_size() const { return pixel_size; } +void TextMesh::set_offset(const Point2 &p_offset) { + if (lbl_offset != p_offset) { + lbl_offset = p_offset; + _request_update(); + } +} + +Point2 TextMesh::get_offset() const { + return lbl_offset; +} + void TextMesh::set_curve_step(real_t p_step) { if (curve_step != p_step) { curve_step = CLAMP(p_step, 0.1, 10.0); diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index f5ed01a162..280477ebfa 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -217,17 +217,25 @@ public: CylinderMesh(); }; -/** - Similar to quadmesh but with tessellation support +/* + A flat rectangle, can be used as quad or heightmap. */ class PlaneMesh : public PrimitiveMesh { GDCLASS(PlaneMesh, PrimitiveMesh); +public: + enum Orientation { + FACE_X, + FACE_Y, + FACE_Z, + }; + private: Size2 size = Size2(2.0, 2.0); int subdivide_w = 0; int subdivide_d = 0; Vector3 center_offset; + Orientation orientation = FACE_Y; protected: static void _bind_methods(); @@ -246,9 +254,14 @@ public: void set_center_offset(const Vector3 p_offset); Vector3 get_center_offset() const; + void set_orientation(const Orientation p_orientation); + Orientation get_orientation() const; + PlaneMesh(); }; +VARIANT_ENUM_CAST(PlaneMesh::Orientation) + /** A prism shapen, handy for ramps, triangles, etc. */ @@ -286,33 +299,6 @@ public: }; /** - Our original quadmesh... -*/ - -class QuadMesh : public PrimitiveMesh { - GDCLASS(QuadMesh, PrimitiveMesh); - -private: - Size2 size = Size2(1.0, 1.0); - Vector3 center_offset; - -protected: - static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const override; - -public: - virtual uint32_t surface_get_format(int p_idx) const override; - - QuadMesh(); - - void set_size(const Size2 &p_size); - Size2 get_size() const; - - void set_center_offset(const Vector3 p_offset); - Vector3 get_center_offset() const; -}; - -/** A sphere.. */ class SphereMesh : public PrimitiveMesh { @@ -548,14 +534,21 @@ private: mutable HashMap<GlyphMeshKey, GlyphMeshData, GlyphMeshKeyHasher> cache; RID text_rid; + mutable Vector<RID> lines_rid; + String text; String xl_text; int font_size = 16; Ref<Font> font_override; + + TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF; float width = 500.0; + float line_spacing = 0.f; + Point2 lbl_offset; HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER; + VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER; bool uppercase = false; String language; TextServer::Direction text_direction = TextServer::DIRECTION_AUTO; @@ -566,6 +559,7 @@ private: real_t pixel_size = 0.01; real_t curve_step = 0.5; + mutable bool dirty_lines = true; mutable bool dirty_text = true; mutable bool dirty_font = true; mutable bool dirty_cache = true; @@ -588,6 +582,9 @@ public: void set_horizontal_alignment(HorizontalAlignment p_alignment); HorizontalAlignment get_horizontal_alignment() const; + void set_vertical_alignment(VerticalAlignment p_alignment); + VerticalAlignment get_vertical_alignment() const; + void set_text(const String &p_string); String get_text() const; @@ -598,6 +595,12 @@ public: void set_font_size(int p_size); int get_font_size() const; + void set_line_spacing(float p_size); + float get_line_spacing() const; + + void set_autowrap_mode(TextServer::AutowrapMode p_mode); + TextServer::AutowrapMode get_autowrap_mode() const; + void set_text_direction(TextServer::Direction p_text_direction); TextServer::Direction get_text_direction() const; @@ -624,6 +627,9 @@ public: void set_pixel_size(real_t p_amount); real_t get_pixel_size() const; + + void set_offset(const Point2 &p_offset); + Point2 get_offset() const; }; VARIANT_ENUM_CAST(RibbonTrailMesh::Shape) diff --git a/scene/resources/skeleton_modification_2d_ccdik.cpp b/scene/resources/skeleton_modification_2d_ccdik.cpp index 7adaf1452c..96961a1fe4 100644 --- a/scene/resources/skeleton_modification_2d_ccdik.cpp +++ b/scene/resources/skeleton_modification_2d_ccdik.cpp @@ -52,9 +52,9 @@ bool SkeletonModification2DCCDIK::_set(const StringName &p_path, const Variant & } else if (what == "enable_constraint") { set_ccdik_joint_enable_constraint(which, p_value); } else if (what == "constraint_angle_min") { - set_ccdik_joint_constraint_angle_min(which, Math::deg2rad(float(p_value))); + set_ccdik_joint_constraint_angle_min(which, Math::deg_to_rad(float(p_value))); } else if (what == "constraint_angle_max") { - set_ccdik_joint_constraint_angle_max(which, Math::deg2rad(float(p_value))); + set_ccdik_joint_constraint_angle_max(which, Math::deg_to_rad(float(p_value))); } else if (what == "constraint_angle_invert") { set_ccdik_joint_constraint_angle_invert(which, p_value); } else if (what == "constraint_in_localspace") { @@ -96,9 +96,9 @@ bool SkeletonModification2DCCDIK::_get(const StringName &p_path, Variant &r_ret) } else if (what == "enable_constraint") { r_ret = get_ccdik_joint_enable_constraint(which); } else if (what == "constraint_angle_min") { - r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_min(which)); + r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_min(which)); } else if (what == "constraint_angle_max") { - r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_max(which)); + r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_max(which)); } else if (what == "constraint_angle_invert") { r_ret = get_ccdik_joint_constraint_angle_invert(which); } else if (what == "constraint_in_localspace") { diff --git a/scene/resources/skeleton_modification_2d_lookat.cpp b/scene/resources/skeleton_modification_2d_lookat.cpp index 23e1c579dc..d3cfffb1de 100644 --- a/scene/resources/skeleton_modification_2d_lookat.cpp +++ b/scene/resources/skeleton_modification_2d_lookat.cpp @@ -41,15 +41,15 @@ bool SkeletonModification2DLookAt::_set(const StringName &p_path, const Variant if (path.begins_with("enable_constraint")) { set_enable_constraint(p_value); } else if (path.begins_with("constraint_angle_min")) { - set_constraint_angle_min(Math::deg2rad(float(p_value))); + set_constraint_angle_min(Math::deg_to_rad(float(p_value))); } else if (path.begins_with("constraint_angle_max")) { - set_constraint_angle_max(Math::deg2rad(float(p_value))); + set_constraint_angle_max(Math::deg_to_rad(float(p_value))); } else if (path.begins_with("constraint_angle_invert")) { set_constraint_angle_invert(p_value); } else if (path.begins_with("constraint_in_localspace")) { set_constraint_in_localspace(p_value); } else if (path.begins_with("additional_rotation")) { - set_additional_rotation(Math::deg2rad(float(p_value))); + set_additional_rotation(Math::deg_to_rad(float(p_value))); } #ifdef TOOLS_ENABLED @@ -67,15 +67,15 @@ bool SkeletonModification2DLookAt::_get(const StringName &p_path, Variant &r_ret if (path.begins_with("enable_constraint")) { r_ret = get_enable_constraint(); } else if (path.begins_with("constraint_angle_min")) { - r_ret = Math::rad2deg(get_constraint_angle_min()); + r_ret = Math::rad_to_deg(get_constraint_angle_min()); } else if (path.begins_with("constraint_angle_max")) { - r_ret = Math::rad2deg(get_constraint_angle_max()); + r_ret = Math::rad_to_deg(get_constraint_angle_max()); } else if (path.begins_with("constraint_angle_invert")) { r_ret = get_constraint_angle_invert(); } else if (path.begins_with("constraint_in_localspace")) { r_ret = get_constraint_in_localspace(); } else if (path.begins_with("additional_rotation")) { - r_ret = Math::rad2deg(get_additional_rotation()); + r_ret = Math::rad_to_deg(get_additional_rotation()); } #ifdef TOOLS_ENABLED diff --git a/scene/resources/skeleton_modification_3d_ccdik.cpp b/scene/resources/skeleton_modification_3d_ccdik.cpp index f19be47db2..3251ee4189 100644 --- a/scene/resources/skeleton_modification_3d_ccdik.cpp +++ b/scene/resources/skeleton_modification_3d_ccdik.cpp @@ -50,9 +50,9 @@ bool SkeletonModification3DCCDIK::_set(const StringName &p_path, const Variant & } else if (what == "enable_joint_constraint") { set_ccdik_joint_enable_constraint(which, p_value); } else if (what == "joint_constraint_angle_min") { - set_ccdik_joint_constraint_angle_min(which, Math::deg2rad(real_t(p_value))); + set_ccdik_joint_constraint_angle_min(which, Math::deg_to_rad(real_t(p_value))); } else if (what == "joint_constraint_angle_max") { - set_ccdik_joint_constraint_angle_max(which, Math::deg2rad(real_t(p_value))); + set_ccdik_joint_constraint_angle_max(which, Math::deg_to_rad(real_t(p_value))); } else if (what == "joint_constraint_angles_invert") { set_ccdik_joint_constraint_invert(which, p_value); } @@ -79,9 +79,9 @@ bool SkeletonModification3DCCDIK::_get(const StringName &p_path, Variant &r_ret) } else if (what == "enable_joint_constraint") { r_ret = get_ccdik_joint_enable_constraint(which); } else if (what == "joint_constraint_angle_min") { - r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_min(which)); + r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_min(which)); } else if (what == "joint_constraint_angle_max") { - r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_max(which)); + r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_max(which)); } else if (what == "joint_constraint_angles_invert") { r_ret = get_ccdik_joint_constraint_invert(which); } diff --git a/scene/resources/skeleton_modification_3d_fabrik.cpp b/scene/resources/skeleton_modification_3d_fabrik.cpp index b62dda3f4f..4099208f44 100644 --- a/scene/resources/skeleton_modification_3d_fabrik.cpp +++ b/scene/resources/skeleton_modification_3d_fabrik.cpp @@ -58,7 +58,7 @@ bool SkeletonModification3DFABRIK::_set(const StringName &p_path, const Variant } else if (what == "use_target_basis") { set_fabrik_joint_use_target_basis(which, p_value); } else if (what == "roll") { - set_fabrik_joint_roll(which, Math::deg2rad(real_t(p_value))); + set_fabrik_joint_roll(which, Math::deg_to_rad(real_t(p_value))); } return true; } @@ -91,7 +91,7 @@ bool SkeletonModification3DFABRIK::_get(const StringName &p_path, Variant &r_ret } else if (what == "use_target_basis") { r_ret = get_fabrik_joint_use_target_basis(which); } else if (what == "roll") { - r_ret = Math::rad2deg(get_fabrik_joint_roll(which)); + r_ret = Math::rad_to_deg(get_fabrik_joint_roll(which)); } return true; } diff --git a/scene/resources/skeleton_modification_3d_jiggle.cpp b/scene/resources/skeleton_modification_3d_jiggle.cpp index 3e36c241f7..64f26f3fda 100644 --- a/scene/resources/skeleton_modification_3d_jiggle.cpp +++ b/scene/resources/skeleton_modification_3d_jiggle.cpp @@ -58,7 +58,7 @@ bool SkeletonModification3DJiggle::_set(const StringName &p_path, const Variant } else if (what == "gravity") { set_jiggle_joint_gravity(which, p_value); } else if (what == "roll") { - set_jiggle_joint_roll(which, Math::deg2rad(real_t(p_value))); + set_jiggle_joint_roll(which, Math::deg_to_rad(real_t(p_value))); } return true; } else { @@ -98,7 +98,7 @@ bool SkeletonModification3DJiggle::_get(const StringName &p_path, Variant &r_ret } else if (what == "gravity") { r_ret = get_jiggle_joint_gravity(which); } else if (what == "roll") { - r_ret = Math::rad2deg(get_jiggle_joint_roll(which)); + r_ret = Math::rad_to_deg(get_jiggle_joint_roll(which)); } return true; } else { diff --git a/scene/resources/skeleton_modification_3d_lookat.cpp b/scene/resources/skeleton_modification_3d_lookat.cpp index 3e8c1e3a77..69167cb308 100644 --- a/scene/resources/skeleton_modification_3d_lookat.cpp +++ b/scene/resources/skeleton_modification_3d_lookat.cpp @@ -39,9 +39,9 @@ bool SkeletonModification3DLookAt::_set(const StringName &p_path, const Variant set_lock_rotation_plane(p_value); } else if (p_path == "additional_rotation") { Vector3 tmp = p_value; - tmp.x = Math::deg2rad(tmp.x); - tmp.y = Math::deg2rad(tmp.y); - tmp.z = Math::deg2rad(tmp.z); + tmp.x = Math::deg_to_rad(tmp.x); + tmp.y = Math::deg_to_rad(tmp.y); + tmp.z = Math::deg_to_rad(tmp.z); set_additional_rotation(tmp); } @@ -55,9 +55,9 @@ bool SkeletonModification3DLookAt::_get(const StringName &p_path, Variant &r_ret r_ret = get_lock_rotation_plane(); } else if (p_path == "additional_rotation") { Vector3 tmp = get_additional_rotation(); - tmp.x = Math::rad2deg(tmp.x); - tmp.y = Math::rad2deg(tmp.y); - tmp.z = Math::rad2deg(tmp.z); + tmp.x = Math::rad_to_deg(tmp.x); + tmp.y = Math::rad_to_deg(tmp.y); + tmp.z = Math::rad_to_deg(tmp.z); r_ret = tmp; } diff --git a/scene/resources/skeleton_modification_3d_twoboneik.cpp b/scene/resources/skeleton_modification_3d_twoboneik.cpp index acc5ff716c..366fcc30b7 100644 --- a/scene/resources/skeleton_modification_3d_twoboneik.cpp +++ b/scene/resources/skeleton_modification_3d_twoboneik.cpp @@ -54,13 +54,13 @@ bool SkeletonModification3DTwoBoneIK::_set(const StringName &p_path, const Varia } else if (path == "joint_one/bone_idx") { set_joint_one_bone_idx(p_value); } else if (path == "joint_one/roll") { - set_joint_one_roll(Math::deg2rad(real_t(p_value))); + set_joint_one_roll(Math::deg_to_rad(real_t(p_value))); } else if (path == "joint_two/bone_name") { set_joint_two_bone_name(p_value); } else if (path == "joint_two/bone_idx") { set_joint_two_bone_idx(p_value); } else if (path == "joint_two/roll") { - set_joint_two_roll(Math::deg2rad(real_t(p_value))); + set_joint_two_roll(Math::deg_to_rad(real_t(p_value))); } return true; @@ -88,13 +88,13 @@ bool SkeletonModification3DTwoBoneIK::_get(const StringName &p_path, Variant &r_ } else if (path == "joint_one/bone_idx") { r_ret = get_joint_one_bone_idx(); } else if (path == "joint_one/roll") { - r_ret = Math::rad2deg(get_joint_one_roll()); + r_ret = Math::rad_to_deg(get_joint_one_roll()); } else if (path == "joint_two/bone_name") { r_ret = get_joint_two_bone_name(); } else if (path == "joint_two/bone_idx") { r_ret = get_joint_two_bone_idx(); } else if (path == "joint_two/roll") { - r_ret = Math::rad2deg(get_joint_two_roll()); + r_ret = Math::rad_to_deg(get_joint_two_roll()); } return true; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index 5d1a223cc7..737c50e570 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -128,7 +128,7 @@ float ProceduralSkyMaterial::get_ground_energy() const { void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) { sun_angle_max = p_angle; - RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max)); + RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg_to_rad(sun_angle_max)); } float ProceduralSkyMaterial::get_sun_angle_max() const { diff --git a/scene/resources/sphere_shape_3d.cpp b/scene/resources/sphere_shape_3d.cpp index 92efe3ce6f..340d0fe370 100644 --- a/scene/resources/sphere_shape_3d.cpp +++ b/scene/resources/sphere_shape_3d.cpp @@ -38,8 +38,8 @@ Vector<Vector3> SphereShape3D::get_debug_mesh_lines() const { Vector<Vector3> points; for (int i = 0; i <= 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 5e02aa4dd5..90f1a1bff1 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -2214,6 +2214,12 @@ void VisualShader::_update_shader() const { case VaryingType::VARYING_TYPE_FLOAT: global_code += "float "; break; + case VaryingType::VARYING_TYPE_INT: + if (E.value.mode == VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) { + global_code += "flat "; + } + global_code += "int "; + break; case VaryingType::VARYING_TYPE_VECTOR_2D: global_code += "vec2 "; break; @@ -2223,8 +2229,11 @@ void VisualShader::_update_shader() const { case VaryingType::VARYING_TYPE_VECTOR_4D: global_code += "vec4 "; break; - case VaryingType::VARYING_TYPE_COLOR: - global_code += "vec4 "; + case VaryingType::VARYING_TYPE_BOOLEAN: + if (E.value.mode == VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) { + global_code += "flat "; + } + global_code += "bool "; break; case VaryingType::VARYING_TYPE_TRANSFORM: global_code += "mat4 "; @@ -2277,6 +2286,9 @@ void VisualShader::_update_shader() const { case VaryingType::VARYING_TYPE_FLOAT: code2 += "0.0"; break; + case VaryingType::VARYING_TYPE_INT: + code2 += "0"; + break; case VaryingType::VARYING_TYPE_VECTOR_2D: code2 += "vec2(0.0)"; break; @@ -2286,8 +2298,8 @@ void VisualShader::_update_shader() const { case VaryingType::VARYING_TYPE_VECTOR_4D: code2 += "vec4(0.0)"; break; - case VaryingType::VARYING_TYPE_COLOR: - code2 += "vec4(0.0)"; + case VaryingType::VARYING_TYPE_BOOLEAN: + code2 += "false"; break; case VaryingType::VARYING_TYPE_TRANSFORM: code2 += "mat4(1.0)"; @@ -2585,10 +2597,11 @@ void VisualShader::_bind_methods() { BIND_ENUM_CONSTANT(VARYING_MODE_MAX); BIND_ENUM_CONSTANT(VARYING_TYPE_FLOAT); + BIND_ENUM_CONSTANT(VARYING_TYPE_INT); BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_2D); BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_3D); BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_4D); - BIND_ENUM_CONSTANT(VARYING_TYPE_COLOR); + BIND_ENUM_CONSTANT(VARYING_TYPE_BOOLEAN); BIND_ENUM_CONSTANT(VARYING_TYPE_TRANSFORM); BIND_ENUM_CONSTANT(VARYING_TYPE_MAX); @@ -4632,21 +4645,23 @@ void VisualShaderNodeVarying::_bind_methods() { ClassDB::bind_method(D_METHOD("get_varying_type"), &VisualShaderNodeVarying::get_varying_type); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "varying_name"), "set_varying_name", "get_varying_name"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "varying_type", PROPERTY_HINT_ENUM, "Float,Vector,Transform"), "set_varying_type", "get_varying_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "varying_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Vector4,Boolean,Transform"), "set_varying_type", "get_varying_type"); } String VisualShaderNodeVarying::get_type_str() const { switch (varying_type) { case VisualShader::VARYING_TYPE_FLOAT: return "float"; + case VisualShader::VARYING_TYPE_INT: + return "int"; case VisualShader::VARYING_TYPE_VECTOR_2D: return "vec2"; case VisualShader::VARYING_TYPE_VECTOR_3D: return "vec3"; case VisualShader::VARYING_TYPE_VECTOR_4D: return "vec4"; - case VisualShader::VARYING_TYPE_COLOR: - return "vec4"; + case VisualShader::VARYING_TYPE_BOOLEAN: + return "bool"; case VisualShader::VARYING_TYPE_TRANSFORM: return "mat4"; default: @@ -4657,17 +4672,16 @@ String VisualShaderNodeVarying::get_type_str() const { VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type(VisualShader::VaryingType p_type, int p_port) const { switch (p_type) { + case VisualShader::VARYING_TYPE_INT: + return PORT_TYPE_SCALAR_INT; case VisualShader::VARYING_TYPE_VECTOR_2D: return PORT_TYPE_VECTOR_2D; case VisualShader::VARYING_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR_3D; case VisualShader::VARYING_TYPE_VECTOR_4D: return PORT_TYPE_VECTOR_4D; - case VisualShader::VARYING_TYPE_COLOR: - if (p_port == 1) { - break; // scalar - } - return PORT_TYPE_VECTOR_3D; + case VisualShader::VARYING_TYPE_BOOLEAN: + return PORT_TYPE_BOOLEAN; case VisualShader::VARYING_TYPE_TRANSFORM: return PORT_TYPE_TRANSFORM; default: @@ -4711,9 +4725,6 @@ String VisualShaderNodeVaryingSetter::get_caption() const { } int VisualShaderNodeVaryingSetter::get_input_port_count() const { - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - return 2; - } return 1; } @@ -4722,13 +4733,6 @@ VisualShaderNodeVaryingSetter::PortType VisualShaderNodeVaryingSetter::get_input } String VisualShaderNodeVaryingSetter::get_input_port_name(int p_port) const { - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - if (p_port == 0) { - return "color"; - } else { - return "alpha"; - } - } return ""; } @@ -4744,20 +4748,12 @@ String VisualShaderNodeVaryingSetter::get_output_port_name(int p_port) const { return ""; } -String VisualShaderNodeVaryingSetter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return vformat("varying %s %s;\n", get_type_str(), varying_name); -} - String VisualShaderNodeVaryingSetter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; if (varying_name == "[None]") { return code; } - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - code += vformat(" %s = vec4(%s, %s);\n", varying_name, p_input_vars[0], p_input_vars[1]); - } else { - code += vformat(" %s = %s;\n", varying_name, p_input_vars[0]); - } + code += vformat(" %s = %s;\n", varying_name, p_input_vars[0]); return code; } @@ -4783,9 +4779,6 @@ String VisualShaderNodeVaryingGetter::get_input_port_name(int p_port) const { } int VisualShaderNodeVaryingGetter::get_output_port_count() const { - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - return 2; - } return 1; } @@ -4794,13 +4787,6 @@ VisualShaderNodeVaryingGetter::PortType VisualShaderNodeVaryingGetter::get_outpu } String VisualShaderNodeVaryingGetter::get_output_port_name(int p_port) const { - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - if (p_port == 0) { - return "color"; - } else { - return "alpha"; - } - } return ""; } @@ -4817,6 +4803,9 @@ String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualS case VisualShader::VARYING_TYPE_FLOAT: from = "0.0"; break; + case VisualShader::VARYING_TYPE_INT: + from = "0"; + break; case VisualShader::VARYING_TYPE_VECTOR_2D: from = "vec2(0.0)"; break; @@ -4826,9 +4815,8 @@ String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualS case VisualShader::VARYING_TYPE_VECTOR_4D: from = "vec4(0.0)"; break; - case VisualShader::VARYING_TYPE_COLOR: - from = "vec3(0.0)"; - from2 = "0.0"; + case VisualShader::VARYING_TYPE_BOOLEAN: + from = "false"; break; case VisualShader::VARYING_TYPE_TRANSFORM: from = "mat4(1.0)"; @@ -4836,16 +4824,6 @@ String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualS default: break; } - } else if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - from = varying_name + ".rgb"; - from2 = varying_name + ".a"; - } - - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - String code; - code += vformat(" %s = %s;\n", p_output_vars[0], from); - code += vformat(" %s = %s;\n", p_output_vars[1], from2); - return code; } return vformat(" %s = %s;\n", p_output_vars[0], from); } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 009decd9cb..09a3917a16 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -79,10 +79,11 @@ public: enum VaryingType { VARYING_TYPE_FLOAT, + VARYING_TYPE_INT, VARYING_TYPE_VECTOR_2D, VARYING_TYPE_VECTOR_3D, VARYING_TYPE_VECTOR_4D, - VARYING_TYPE_COLOR, + VARYING_TYPE_BOOLEAN, VARYING_TYPE_TRANSFORM, VARYING_TYPE_MAX, }; @@ -828,7 +829,6 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVaryingSetter(); diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 60eb657923..729f278d4b 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -36,9 +36,8 @@ AudioDriverDummy *AudioDriverDummy::singleton = nullptr; Error AudioDriverDummy::init() { - active = false; - thread_exited = false; - exit_thread = false; + active.clear(); + exit_thread.clear(); samples_in = nullptr; if (mix_rate == -1) { @@ -60,23 +59,23 @@ void AudioDriverDummy::thread_func(void *p_udata) { uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000; - while (!ad->exit_thread) { - if (ad->active) { + while (!ad->exit_thread.is_set()) { + if (ad->active.is_set()) { ad->lock(); + ad->start_counting_ticks(); ad->audio_server_process(ad->buffer_frames, ad->samples_in); + ad->stop_counting_ticks(); ad->unlock(); }; OS::get_singleton()->delay_usec(usdelay); }; - - ad->thread_exited = true; }; void AudioDriverDummy::start() { - active = true; + active.set(); }; int AudioDriverDummy::get_mix_rate() const { @@ -113,7 +112,7 @@ uint32_t AudioDriverDummy::get_channels() const { } void AudioDriverDummy::mix_audio(int p_frames, int32_t *p_buffer) { - ERR_FAIL_COND(!active); // If not active, should not mix. + ERR_FAIL_COND(!active.is_set()); // If not active, should not mix. ERR_FAIL_COND(use_threads == true); // If using threads, this will not work well. uint32_t todo = p_frames; @@ -136,7 +135,7 @@ void AudioDriverDummy::mix_audio(int p_frames, int32_t *p_buffer) { void AudioDriverDummy::finish() { if (use_threads) { - exit_thread = true; + exit_thread.set(); thread.wait_to_finish(); } diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index 8f47e64d8b..46dd2e1439 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -35,6 +35,7 @@ #include "core/os/mutex.h" #include "core/os/thread.h" +#include "core/templates/safe_refcount.h" class AudioDriverDummy : public AudioDriver { Thread thread; @@ -50,9 +51,8 @@ class AudioDriverDummy : public AudioDriver { int channels; - bool active; - bool thread_exited; - mutable bool exit_thread; + SafeFlag active; + SafeFlag exit_thread; bool use_threads = true; diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 80485845c9..4252131161 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -782,7 +782,7 @@ void AudioStreamPlaybackRandomizer::start(float p_from_pos) { float range_to = randomizer->random_volume_offset_db; float volume_offset_db = range_from + Math::randf() * (range_to - range_from); - volume_scale = Math::db2linear(volume_offset_db); + volume_scale = Math::db_to_linear(volume_offset_db); } if (playing.is_valid()) { diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp index 87d46f8bbe..2889562173 100644 --- a/servers/audio/effects/audio_effect_amplify.cpp +++ b/servers/audio/effects/audio_effect_amplify.cpp @@ -33,8 +33,8 @@ void AudioEffectAmplifyInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { //multiply volume interpolating to avoid clicks if this changes float volume_db = base->volume_db; - float vol = Math::db2linear(mix_volume_db); - float vol_inc = (Math::db2linear(volume_db) - vol) / float(p_frame_count); + float vol = Math::db_to_linear(mix_volume_db); + float vol_inc = (Math::db_to_linear(volume_db) - vol) / float(p_frame_count); for (int i = 0; i < p_frame_count; i++) { p_dst_frames[i] = p_src_frames[i] * vol; diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp index 54c08ef644..69b416f5f7 100644 --- a/servers/audio/effects/audio_effect_chorus.cpp +++ b/servers/audio/effects/audio_effect_chorus.cpp @@ -95,7 +95,7 @@ void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames, A //vol modifier - AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db2linear(v.level); + AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db_to_linear(v.level); vol_modifier.l *= CLAMP(1.0 - v.pan, 0, 1); vol_modifier.r *= CLAMP(1.0 + v.pan, 0, 1); diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp index 0e1accba16..43b210e450 100644 --- a/servers/audio/effects/audio_effect_compressor.cpp +++ b/servers/audio/effects/audio_effect_compressor.cpp @@ -32,7 +32,7 @@ #include "servers/audio_server.h" void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { - float threshold = Math::db2linear(base->threshold); + float threshold = Math::db_to_linear(base->threshold); float sample_rate = AudioServer::get_singleton()->get_mix_rate(); float ratatcoef = exp(-1 / (0.00001f * sample_rate)); @@ -42,7 +42,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi float atcoef = exp(-1 / (attime * sample_rate)); float relcoef = exp(-1 / (reltime * sample_rate)); - float makeup = Math::db2linear(base->gain); + float makeup = Math::db_to_linear(base->gain); float mix = base->mix; float gr_meter_decay = exp(1 / (1 * sample_rate)); @@ -64,7 +64,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi float peak = MAX(s.l, s.r); - float overdb = 2.08136898f * Math::linear2db(peak / threshold); + float overdb = 2.08136898f * Math::linear_to_db(peak / threshold); if (overdb < 0.0) { //we only care about what goes over to compress overdb = 0.0; @@ -94,7 +94,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi } float gr = -overdb * (cratio - 1) / cratio; - float grv = Math::db2linear(gr); + float grv = Math::db_to_linear(gr); runmax = maxover + relcoef * (runmax - maxover); // highest peak for setting att/rel decays in reltime maxover = runmax; diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp index ae8c58f654..f71ff05b23 100644 --- a/servers/audio/effects/audio_effect_delay.cpp +++ b/servers/audio/effects/audio_effect_delay.cpp @@ -53,13 +53,13 @@ void AudioEffectDelayInstance::_process_chunk(const AudioFrame *p_src_frames, Au float mix_rate = AudioServer::get_singleton()->get_mix_rate(); - float tap_1_level_f = base->tap_1_active ? Math::db2linear(base->tap_1_level) : 0.0; + float tap_1_level_f = base->tap_1_active ? Math::db_to_linear(base->tap_1_level) : 0.0; int tap_1_delay_frames = int((base->tap_1_delay_ms / 1000.0) * mix_rate); - float tap_2_level_f = base->tap_2_active ? Math::db2linear(base->tap_2_level) : 0.0; + float tap_2_level_f = base->tap_2_active ? Math::db_to_linear(base->tap_2_level) : 0.0; int tap_2_delay_frames = int((base->tap_2_delay_ms / 1000.0) * mix_rate); - float feedback_level_f = base->feedback_active ? Math::db2linear(base->feedback_level) : 0.0; + float feedback_level_f = base->feedback_active ? Math::db_to_linear(base->feedback_level) : 0.0; unsigned int feedback_delay_frames = int((base->feedback_delay_ms / 1000.0) * mix_rate); AudioFrame tap1_vol = AudioFrame(tap_1_level_f, tap_1_level_f); diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp index 6820d796a4..5987ed7bb2 100644 --- a/servers/audio/effects/audio_effect_distortion.cpp +++ b/servers/audio/effects/audio_effect_distortion.cpp @@ -41,8 +41,8 @@ void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames, Audi float lpf_ic = 1.0 - lpf_c; float drive_f = base->drive; - float pregain_f = Math::db2linear(base->pre_gain); - float postgain_f = Math::db2linear(base->post_gain); + float pregain_f = Math::db_to_linear(base->pre_gain); + float postgain_f = Math::db_to_linear(base->post_gain); float atan_mult = pow(10, drive_f * drive_f * 3.0) - 1.0 + 0.001; float atan_div = 1.0 / (atanf(atan_mult) * (1.0 + drive_f * 8)); diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp index 500abd3a6f..14ece8d93e 100644 --- a/servers/audio/effects/audio_effect_eq.cpp +++ b/servers/audio/effects/audio_effect_eq.cpp @@ -38,7 +38,7 @@ void AudioEffectEQInstance::process(const AudioFrame *p_src_frames, AudioFrame * EQ::BandProcess *proc_r = bands[1].ptrw(); float *bgain = gains.ptrw(); for (int i = 0; i < band_count; i++) { - bgain[i] = Math::db2linear(base->gain[i]); + bgain[i] = Math::db_to_linear(base->gain[i]); } for (int i = 0; i < p_frame_count; i++) { diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp index 7bcd68d48b..99653cf5b6 100644 --- a/servers/audio/effects/audio_effect_limiter.cpp +++ b/servers/audio/effects/audio_effect_limiter.cpp @@ -32,11 +32,11 @@ void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { float threshdb = base->threshold; - float ceiling = Math::db2linear(base->ceiling); + float ceiling = Math::db_to_linear(base->ceiling); float ceildb = base->ceiling; - float makeup = Math::db2linear(ceildb - threshdb); + float makeup = Math::db_to_linear(ceildb - threshdb); float sc = -base->soft_clip; - float scv = Math::db2linear(sc); + float scv = Math::db_to_linear(sc); float peakdb = ceildb + 25; float scmult = Math::abs((ceildb - sc) / (peakdb - sc)); @@ -49,14 +49,14 @@ void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFr float sign1 = (spl1 < 0.0 ? -1.0 : 1.0); float abs0 = Math::abs(spl0); float abs1 = Math::abs(spl1); - float overdb0 = Math::linear2db(abs0) - ceildb; - float overdb1 = Math::linear2db(abs1) - ceildb; + float overdb0 = Math::linear_to_db(abs0) - ceildb; + float overdb1 = Math::linear_to_db(abs1) - ceildb; if (abs0 > scv) { - spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult)); + spl0 = sign0 * (scv + Math::db_to_linear(overdb0 * scmult)); } if (abs1 > scv) { - spl1 = sign1 * (scv + Math::db2linear(overdb1 * scmult)); + spl1 = sign1 * (scv + Math::db_to_linear(overdb1 * scmult)); } spl0 = MIN(ceiling, Math::abs(spl0)) * (spl0 < 0.0 ? -1.0 : 1.0); diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 64695557aa..1254a6740a 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -547,7 +547,7 @@ void AudioServer::_mix_step() { AudioFrame peak = AudioFrame(0, 0); - float volume = Math::db2linear(bus->volume_db); + float volume = Math::db_to_linear(bus->volume_db); if (solo_mode) { if (!bus->soloed) { @@ -573,12 +573,12 @@ void AudioServer::_mix_step() { } } - bus->channels.write[k].peak_volume = AudioFrame(Math::linear2db(peak.l + AUDIO_PEAK_OFFSET), Math::linear2db(peak.r + AUDIO_PEAK_OFFSET)); + bus->channels.write[k].peak_volume = AudioFrame(Math::linear_to_db(peak.l + AUDIO_PEAK_OFFSET), Math::linear_to_db(peak.r + AUDIO_PEAK_OFFSET)); if (!bus->channels[k].used) { //see if any audio is contained, because channel was not used - if (MAX(peak.r, peak.l) > Math::db2linear(channel_disable_threshold_db)) { + if (MAX(peak.r, peak.l) > Math::db_to_linear(channel_disable_threshold_db)) { bus->channels.write[k].last_mix_with_audio = mix_frames; } else if (mix_frames - bus->channels[k].last_mix_with_audio > channel_disable_frames) { bus->channels.write[k].active = false; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 0c05570b23..22f42ca343 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -663,6 +663,8 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("window_set_flag", "flag", "enabled", "window_id"), &DisplayServer::window_set_flag, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_get_flag", "flag", "window_id"), &DisplayServer::window_get_flag, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_get_safe_title_margins", "window_id"), &DisplayServer::window_get_safe_title_margins, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_request_attention", "window_id"), &DisplayServer::window_request_attention, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_move_to_foreground", "window_id"), &DisplayServer::window_move_to_foreground, DEFVAL(MAIN_WINDOW_ID)); @@ -677,6 +679,9 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("window_set_vsync_mode", "vsync_mode", "window_id"), &DisplayServer::window_set_vsync_mode, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_get_vsync_mode", "window_id"), &DisplayServer::window_get_vsync_mode, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_maximize_on_title_dbl_click"), &DisplayServer::window_maximize_on_title_dbl_click); + ClassDB::bind_method(D_METHOD("window_minimize_on_title_dbl_click"), &DisplayServer::window_minimize_on_title_dbl_click); + ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection); ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text); @@ -733,6 +738,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_SWAP_BUFFERS); BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD_PRIMARY); BIND_ENUM_CONSTANT(FEATURE_TEXT_TO_SPEECH); + BIND_ENUM_CONSTANT(FEATURE_EXTEND_TO_TITLE); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); @@ -792,6 +798,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(WINDOW_FLAG_TRANSPARENT); BIND_ENUM_CONSTANT(WINDOW_FLAG_NO_FOCUS); BIND_ENUM_CONSTANT(WINDOW_FLAG_POPUP); + BIND_ENUM_CONSTANT(WINDOW_FLAG_EXTEND_TO_TITLE); BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX); BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER); diff --git a/servers/display_server.h b/servers/display_server.h index 4e52c58633..0b162fe491 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -122,6 +122,7 @@ public: FEATURE_KEEP_SCREEN_ON, FEATURE_CLIPBOARD_PRIMARY, FEATURE_TEXT_TO_SPEECH, + FEATURE_EXTEND_TO_TITLE, }; virtual bool has_feature(Feature p_feature) const = 0; @@ -289,6 +290,7 @@ public: WINDOW_FLAG_TRANSPARENT, WINDOW_FLAG_NO_FOCUS, WINDOW_FLAG_POPUP, + WINDOW_FLAG_EXTEND_TO_TITLE, WINDOW_FLAG_MAX, }; @@ -300,6 +302,7 @@ public: WINDOW_FLAG_TRANSPARENT_BIT = (1 << WINDOW_FLAG_TRANSPARENT), WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS), WINDOW_FLAG_POPUP_BIT = (1 << WINDOW_FLAG_POPUP), + WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE), }; virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); @@ -371,6 +374,8 @@ public: virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) = 0; virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual Vector2i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const { return Vector2i(); }; + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const = 0; virtual bool can_any_window_draw() const = 0; @@ -378,6 +383,9 @@ public: virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID); + virtual bool window_maximize_on_title_dbl_click() const { return false; } + virtual bool window_minimize_on_title_dbl_click() const { return false; } + // necessary for GL focus, may be able to use one of the existing functions for this, not sure yet virtual void gl_window_make_current(DisplayServer::WindowID p_window_id); diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 983a6a4ef7..0f73df8894 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -237,7 +237,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map); ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map); - ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer2D::agent_set_neighbor_dist); + ClassDB::bind_method(D_METHOD("agent_set_neighbor_distance", "agent", "distance"), &NavigationServer2D::agent_set_neighbor_distance); ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer2D::agent_set_max_neighbors); ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer2D::agent_set_time_horizon); ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer2D::agent_set_radius); @@ -323,7 +323,7 @@ RID NavigationServer2D::agent_create() const { void FORWARD_2_C(agent_set_map, RID, p_agent, RID, p_map, rid_to_rid, rid_to_rid); -void FORWARD_2_C(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real); +void FORWARD_2_C(agent_set_neighbor_distance, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real); void FORWARD_2_C(agent_set_max_neighbors, RID, p_agent, int, p_count, rid_to_rid, int_to_int); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 3316e3c444..5e96466d66 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -133,7 +133,7 @@ public: /// time of the simulation. If the number is too /// low, the simulation will not be safe. /// Must be non-negative. - virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const; + virtual void agent_set_neighbor_distance(RID p_agent, real_t p_distance) const; /// The maximum number of other agents this /// agent takes into account in the navigation. diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 206698f97c..466b74bc64 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -79,7 +79,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map); ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map); - ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer3D::agent_set_neighbor_dist); + ClassDB::bind_method(D_METHOD("agent_set_neighbor_distance", "agent", "distance"), &NavigationServer3D::agent_set_neighbor_distance); ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer3D::agent_set_max_neighbors); ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer3D::agent_set_time_horizon); ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer3D::agent_set_radius); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index b419409851..3213da3d84 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -147,7 +147,7 @@ public: /// time of the simulation. If the number is too /// low, the simulation will not be safe. /// Must be non-negative. - virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const = 0; + virtual void agent_set_neighbor_distance(RID p_agent, real_t p_distance) const = 0; /// The maximum number of other agents this /// agent takes into account in the navigation. diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp index 268beb1a55..ef6a6b1ae2 100644 --- a/servers/physics_2d/godot_body_2d.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -44,7 +44,7 @@ void GodotBody2D::update_mass_properties() { //update shapes and motions switch (mode) { - case PhysicsServer2D::BODY_MODE_DYNAMIC: { + case PhysicsServer2D::BODY_MODE_RIGID: { real_t total_area = 0; for (int i = 0; i < get_shape_count(); i++) { if (is_shape_disabled(i)) { @@ -113,7 +113,7 @@ void GodotBody2D::update_mass_properties() { _inv_inertia = 0; _inv_mass = 0; } break; - case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: { + case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: { _inv_inertia = 0; _inv_mass = 1.0 / mass; @@ -160,7 +160,7 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian real_t mass_value = p_value; ERR_FAIL_COND(mass_value <= 0); mass = mass_value; - if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (mode >= PhysicsServer2D::BODY_MODE_RIGID) { _mass_properties_changed(); } } break; @@ -168,13 +168,13 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian real_t inertia_value = p_value; if (inertia_value <= 0.0) { calculate_inertia = true; - if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer2D::BODY_MODE_RIGID) { _mass_properties_changed(); } } else { calculate_inertia = false; inertia = inertia_value; - if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer2D::BODY_MODE_RIGID) { _inv_inertia = 1.0 / inertia; } } @@ -267,7 +267,7 @@ void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) { first_time_kinematic = true; } } break; - case PhysicsServer2D::BODY_MODE_DYNAMIC: { + case PhysicsServer2D::BODY_MODE_RIGID: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; if (!calculate_inertia) { _inv_inertia = 1.0 / inertia; @@ -277,7 +277,7 @@ void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) { set_active(true); } break; - case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: { + case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = 0; angular_velocity = 0; @@ -358,7 +358,7 @@ void GodotBody2D::set_state(PhysicsServer2D::BodyState p_state, const Variant &p } break; case PhysicsServer2D::BODY_STATE_CAN_SLEEP: { can_sleep = p_variant; - if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC && !active && !can_sleep) { + if (mode >= PhysicsServer2D::BODY_MODE_RIGID && !active && !can_sleep) { set_active(true); } @@ -661,7 +661,7 @@ void GodotBody2D::wakeup_neighbours() { continue; } GodotBody2D *b = n[i]; - if (b->mode < PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (b->mode < PhysicsServer2D::BODY_MODE_RIGID) { continue; } diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 4b87a69d5c..409940d4f8 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -42,7 +42,7 @@ class GodotConstraint2D; class GodotPhysicsDirectBodyState2D; class GodotBody2D : public GodotCollisionObject2D { - PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_DYNAMIC; + PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_RIGID; Vector2 biased_linear_velocity; real_t biased_angular_velocity = 0.0; diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 4166191be8..afcc5af951 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -643,7 +643,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) { const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj); - if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) { //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction Vector2 lv = b->get_linear_velocity(); //compute displacement from linear velocity @@ -948,7 +948,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) { const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj); - if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) { //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction Vector2 lv = b->get_linear_velocity(); //compute displacement from linear velocity @@ -1218,7 +1218,7 @@ GodotPhysicsDirectSpaceState2D *GodotSpace2D::get_direct_state() { GodotSpace2D::GodotSpace2D() { body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0); - body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg2rad(8.0)); + body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg_to_rad(8.0)); body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5); ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 0603458acd..46718c8819 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -42,7 +42,7 @@ void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D p_body->set_island_step(_step); if (p_body->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) { - // Only dynamic bodies are tested for activation. + // Only rigid bodies are tested for activation. p_body_island.push_back(p_body); } diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp index 4c89106839..b632f7f461 100644 --- a/servers/physics_3d/godot_body_3d.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -56,7 +56,7 @@ void GodotBody3D::update_mass_properties() { // Update shapes and motions. switch (mode) { - case PhysicsServer3D::BODY_MODE_DYNAMIC: { + case PhysicsServer3D::BODY_MODE_RIGID: { real_t total_area = 0; for (int i = 0; i < get_shape_count(); i++) { if (is_shape_disabled(i)) { @@ -154,7 +154,7 @@ void GodotBody3D::update_mass_properties() { _inv_inertia = Vector3(); _inv_mass = 0; } break; - case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: { + case PhysicsServer3D::BODY_MODE_RIGID_LINEAR: { _inv_inertia_tensor.set_zero(); _inv_mass = 1.0 / mass; @@ -201,7 +201,7 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian real_t mass_value = p_value; ERR_FAIL_COND(mass_value <= 0); mass = mass_value; - if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (mode >= PhysicsServer3D::BODY_MODE_RIGID) { _mass_properties_changed(); } } break; @@ -209,12 +209,12 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian inertia = p_value; if ((inertia.x <= 0.0) || (inertia.y <= 0.0) || (inertia.z <= 0.0)) { calculate_inertia = true; - if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer3D::BODY_MODE_RIGID) { _mass_properties_changed(); } } else { calculate_inertia = false; - if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer3D::BODY_MODE_RIGID) { principal_inertia_axes_local = Basis(); _inv_inertia = inertia.inverse(); _update_transform_dependent(); @@ -263,7 +263,7 @@ Variant GodotBody3D::get_param(PhysicsServer3D::BodyParameter p_param) const { return mass; } break; case PhysicsServer3D::BODY_PARAM_INERTIA: { - if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer3D::BODY_MODE_RIGID) { return _inv_inertia.inverse(); } else { return Vector3(); @@ -315,7 +315,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) { _update_transform_dependent(); } break; - case PhysicsServer3D::BODY_MODE_DYNAMIC: { + case PhysicsServer3D::BODY_MODE_RIGID: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; if (!calculate_inertia) { principal_inertia_axes_local = Basis(); @@ -327,7 +327,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) { set_active(true); } break; - case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: { + case PhysicsServer3D::BODY_MODE_RIGID_LINEAR: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = Vector3(); angular_velocity = Vector3(); @@ -407,7 +407,7 @@ void GodotBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p } break; case PhysicsServer3D::BODY_STATE_CAN_SLEEP: { can_sleep = p_variant; - if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC && !active && !can_sleep) { + if (mode >= PhysicsServer3D::BODY_MODE_RIGID && !active && !can_sleep) { set_active(true); } @@ -744,7 +744,7 @@ void GodotBody3D::wakeup_neighbours() { continue; } GodotBody3D *b = n[i]; - if (b->mode < PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (b->mode < PhysicsServer3D::BODY_MODE_RIGID) { continue; } diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index 93bd5a0071..2153ca4e91 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -40,7 +40,7 @@ class GodotConstraint3D; class GodotPhysicsDirectBodyState3D; class GodotBody3D : public GodotCollisionObject3D { - PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_DYNAMIC; + PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_RIGID; Vector3 linear_velocity; Vector3 angular_velocity; diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 074232dd66..76d59202c9 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -1249,7 +1249,7 @@ GodotPhysicsDirectSpaceState3D *GodotSpace3D::get_direct_state() { GodotSpace3D::GodotSpace3D() { body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1); - body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg2rad(8.0)); + body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg_to_rad(8.0)); body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index f384c829a4..bfedcd29c0 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -44,7 +44,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D p_body->set_island_step(_step); if (p_body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) { - // Only dynamic bodies are tested for activation. + // Only rigid bodies are tested for activation. p_body_island.push_back(p_body); } diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index bfb5cd8106..ca9c9c8fc4 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -817,8 +817,8 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(BODY_MODE_STATIC); BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); - BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC); - BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID_LINEAR); BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE); BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index d0c5a7189b..071ff5ffe9 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -348,8 +348,8 @@ public: enum BodyMode { BODY_MODE_STATIC, BODY_MODE_KINEMATIC, - BODY_MODE_DYNAMIC, - BODY_MODE_DYNAMIC_LINEAR, + BODY_MODE_RIGID, + BODY_MODE_RIGID_LINEAR, }; virtual RID body_create() = 0; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 6dd5be9ea8..fc32e1f665 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -988,8 +988,8 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(BODY_MODE_STATIC); BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); - BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC); - BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID_LINEAR); BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE); BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index d5c4d9713b..6237ed67aa 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -381,8 +381,8 @@ public: enum BodyMode { BODY_MODE_STATIC, BODY_MODE_KINEMATIC, - BODY_MODE_DYNAMIC, - BODY_MODE_DYNAMIC_LINEAR, + BODY_MODE_RIGID, + BODY_MODE_RIGID_LINEAR, }; enum BodyDampMode { diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 86e5e4802b..aa9772a483 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -1183,6 +1183,38 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co rect->px_range = p_px_range; } +void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate) { + Item *canvas_item = canvas_item_owner.get_or_null(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>(); + ERR_FAIL_COND(!rect); + rect->modulate = p_modulate; + rect->rect = p_rect; + + rect->texture = p_texture; + + rect->source = p_src_rect; + rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_LCD; + + if (p_rect.size.x < 0) { + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_src_rect.size.x < 0) { + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H; + rect->source.size.x = -rect->source.size.x; + } + if (p_rect.size.y < 0) { + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_src_rect.size.y < 0) { + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V; + rect->source.size.y = -rect->source.size.y; + } +} + void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_COND(!canvas_item); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index e8c54310c9..0d6a4006f8 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -225,6 +225,7 @@ public: void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0); + void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()); diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 11a7d34291..6791ed9626 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -46,6 +46,7 @@ public: CANVAS_RECT_CLIP_UV = 32, CANVAS_RECT_IS_GROUP = 64, CANVAS_RECT_MSDF = 128, + CANVAS_RECT_LCD = 256, }; struct Light { @@ -193,7 +194,7 @@ public: Rect2 rect; Color modulate; Rect2 source; - uint8_t flags; + uint16_t flags; float outline; float px_range; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h index 17ca1986c6..ef17ceb98c 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.h +++ b/servers/rendering/renderer_rd/cluster_builder_rd.h @@ -269,7 +269,7 @@ public: //spot radius *= shared->cone_overfit; // overfit icosphere - real_t len = Math::tan(Math::deg2rad(p_spot_aperture)) * radius; + real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius; //approximate, probably better to use a cone support function float max_d = -1e20; float min_d = 1e20; @@ -293,7 +293,7 @@ public: float dist = base_plane.distance_to(Vector3()); if (dist >= 0 && dist < radius) { //inside, check angle - float angle = Math::rad2deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z)))); + float angle = Math::rad_to_deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z)))); e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit } else { e.touches_near = false; diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 0f896a8aa7..874409b885 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -1604,7 +1604,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R ScreenSpaceReflectionFilterPushConstant push_constant; push_constant.view_index = v; push_constant.orthogonal = p_projections[v].is_orthogonal(); - push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0)); + push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0)); push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]); push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]); push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index eaef5ba39c..66e984174c 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -1924,7 +1924,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); + lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); idx++; @@ -2362,7 +2362,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); + lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); idx++; @@ -2800,7 +2800,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID l.color[1] = color.g; l.color[2] = color.b; - l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); + l.cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index d3601274b5..1d6b158d65 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -1232,7 +1232,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh // I know tan(0) is 0, but let's not risk it with numerical precision. // technically this will keep expanding until reaching the sun, but all we care // is expand until we reach the radius of the near plane (there can't be more occluders than that) - angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); } else { angular_diameter = 0.0; } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 38a2340d40..67c929b724 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -494,7 +494,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } //bind pipeline - { + if (rect->flags & CANVAS_RECT_LCD) { + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD_LCD_BLEND].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); + RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, rect->modulate); + } else { RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -556,6 +560,8 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend push_constant.msdf[1] = rect->outline; // Outline size. push_constant.msdf[2] = 0.f; // Reserved. push_constant.msdf[3] = 0.f; // Reserved. + } else if (rect->flags & CANVAS_RECT_LCD) { + push_constant.flags |= FLAGS_USE_LCD; } push_constant.modulation[0] = rect->modulate.r * base_color.r; @@ -1594,7 +1600,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, real_t farp = p_far; real_t aspect = 1.0; - real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5)); + real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5)); real_t ymin = -ymax; real_t xmin = ymin * aspect; real_t xmax = ymax * aspect; @@ -2113,6 +2119,18 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { RD::PipelineColorBlendState blend_state; blend_state.attachments.push_back(attachment); + RD::PipelineColorBlendState::Attachment attachment_lcd; + attachment_lcd.enable_blend = true; + attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.color_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR; + attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + RD::PipelineColorBlendState blend_state_lcd; + blend_state_lcd.attachments.push_back(attachment_lcd); + //update pipelines for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { @@ -2128,10 +2146,12 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, }; ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit + { + //non lit SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_PRIMITIVE, @@ -2141,8 +2161,11 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD, + }, + { + //lit SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT, @@ -2152,11 +2175,17 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_QUAD_LIGHT, + }, }; RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]); - pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) { + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS); + } else { + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } } } @@ -2363,6 +2392,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { blend_state.attachments.push_back(blend_attachment); + RD::PipelineColorBlendState::Attachment attachment_lcd; + attachment_lcd.enable_blend = true; + attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.color_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR; + attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + RD::PipelineColorBlendState blend_state_lcd; + blend_state_lcd.attachments.push_back(attachment_lcd); + for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { @@ -2376,10 +2417,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, }; ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit + { + //non lit SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_PRIMITIVE, @@ -2389,8 +2432,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD, + }, + { + //lit SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT, @@ -2400,11 +2446,17 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_QUAD_LIGHT, + }, }; RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); - shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) { + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS); + } else { + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } } } } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index bcbbbaa1a0..54077a5b9a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -85,6 +85,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), FLAGS_USE_MSDF = (1 << 28), + FLAGS_USE_LCD = (1 << 29), }; enum { @@ -122,6 +123,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_POINTS, + PIPELINE_VARIANT_QUAD_LCD_BLEND, PIPELINE_VARIANT_MAX }; enum PipelineLightMode { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index d8499681ad..7adc36c57c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2459,6 +2459,19 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p p_internal_width = p_width; } + if (p_use_taa) { + // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. + // This restores sharpness in still images to be roughly at the same level as without TAA, + // but moving scenes will still be blurrier. + p_texture_mipmap_bias -= 0.5; + } + + if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { + // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness. + // If both TAA and FXAA are enabled, combine their negative LOD biases together. + p_texture_mipmap_bias -= 0.25; + } + material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias); update_uniform_sets(); @@ -2862,7 +2875,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); - light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset + light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) { WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet."); @@ -2877,7 +2890,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const // I know tan(0) is 0, but let's not risk it with numerical precision. // technically this will keep expanding until reaching the sun, but all we care // is expand until we reach the radius of the near plane (there can't be more occluders than that) - angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); if (light_storage->light_has_shadow(base) && light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR) > 0.0) { // Only enable PCSS-like soft shadows if blurring is enabled. // Otherwise, performance would decrease with no visual difference. @@ -3092,7 +3105,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION); float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE); - light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle)); + light_data.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle)); light_data.mask = light_storage->light_get_cull_mask(base); @@ -3193,7 +3206,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const // Only enable PCSS-like soft shadows if blurring is enabled. // Otherwise, performance would decrease with no visual difference. Projection cm = li->shadow_transform[0].camera; - float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle)); + float half_np = cm.get_z_near() * Math::tan(Math::deg_to_rad(spot_angle)); light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width; } else { light_data.soft_shadow_size = 0.0; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index f8e9020f9f..459d798a80 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -509,7 +509,13 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - + } else if (bool(draw_data.flags & FLAGS_USE_LCD)) { + vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv); + if (lcd_sample.a == 1.0) { + color.rgb = lcd_sample.rgb * color.a; + } else { + color = vec4(0.0, 0.0, 0.0, 0.0); + } } else { #else { diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 2ea6965c09..1b627a3e81 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -25,6 +25,7 @@ #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) #define FLAGS_USE_MSDF (1 << 28) +#define FLAGS_USE_LCD (1 << 29) #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index 882afdfa54..7b58cc08dd 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -352,7 +352,7 @@ AABB LightStorage::light_get_aabb(RID p_light) const { switch (light->type) { case RS::LIGHT_SPOT: { float len = light->param[RS::LIGHT_PARAM_RANGE]; - float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; + float size = Math::tan(Math::deg_to_rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); }; case RS::LIGHT_OMNI: { diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index ba644e7eb9..022b027644 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -134,7 +134,7 @@ void process() { material_storage->material_initialize(particles_shader.default_material); material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); - ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + ParticleProcessMaterialData *md = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -1072,9 +1072,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); - ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + ParticleProcessMaterialData *m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES)); if (!m) { - m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); } ERR_FAIL_COND(!m); @@ -1696,16 +1696,16 @@ MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() { return shader_data; } -bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool ParticlesStorage::ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); } -ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() { +ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() { free_parameters_uniform_set(uniform_set); } MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) { - ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); + ParticleProcessMaterialData *material_data = memnew(ParticleProcessMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 97d100e2da..299fdc6ec8 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -354,14 +354,14 @@ private: return ParticlesStorage::get_singleton()->_create_particles_shader_func(); } - struct ParticlesMaterialData : public MaterialStorage::MaterialData { + struct ParticleProcessMaterialData : public MaterialStorage::MaterialData { ParticlesShaderData *shader_data = nullptr; RID uniform_set; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~ParticlesMaterialData(); + virtual ~ParticleProcessMaterialData(); }; MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 0b20bb372a..80c4ecea2d 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -506,7 +506,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { } if (instance->mesh_instance.is_valid()) { - RSG::mesh_storage->mesh_free(instance->mesh_instance); + RSG::mesh_storage->mesh_instance_free(instance->mesh_instance); instance->mesh_instance = RID(); // no need to set instance data flag here, as it was freed above } @@ -2146,7 +2146,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in if (soft_shadow_angle > 0.0) { float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam; - soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range; + soft_shadow_expand = Math::tan(Math::deg_to_rad(soft_shadow_angle)) * z_range; x_max += soft_shadow_expand; y_max += soft_shadow_expand; @@ -3125,8 +3125,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE); float angle = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE); - float w = radius * Math::sin(Math::deg2rad(angle)); - float d = radius * Math::cos(Math::deg2rad(angle)); + float w = radius * Math::sin(Math::deg_to_rad(angle)); + float d = radius * Math::cos(Math::deg_to_rad(angle)); Vector3 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index c07a783302..2fefdbff52 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -429,6 +429,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); + ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants); ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline); ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set); ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index a864cfa74c..6dadcab383 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -1129,6 +1129,7 @@ public: virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; + virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) = 0; virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0; virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0; virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index cc79d09503..9b174d5879 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -831,6 +831,7 @@ public: FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool) FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool) FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float) + FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &) FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &) FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float) FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index cab92e6e20..2bbc5e4dfb 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -5377,6 +5377,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } _set_tkpos(prev_pos); + ShaderNode::Varying &var = shader->varyings[identifier]; String error; if (is_token_operator_assign(next_token.type)) { if (!_validate_varying_assign(shader->varyings[identifier], &error)) { @@ -5384,8 +5385,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } } else { - ShaderNode::Varying &var = shader->varyings[identifier]; - switch (var.stage) { case ShaderNode::Varying::STAGE_VERTEX: if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) { @@ -5401,6 +5400,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons break; } } + + if ((var.stage != ShaderNode::Varying::STAGE_FRAGMENT && var.stage != ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT) && var.type < TYPE_FLOAT && var.interpolation != INTERPOLATION_FLAT) { + _set_tkpos(var.tkpos); + _set_error(RTR("Varying with integer data type must be declared with `flat` interpolation qualifier.")); + return nullptr; + } } if (ident_type == IDENTIFIER_FUNCTION) { @@ -8299,8 +8304,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } - if (!is_uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) { - _set_error(RTR("Invalid type for varying, only 'float', 'vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4', or arrays of these types are allowed.")); + if (!is_uniform && type > TYPE_MAT4) { + _set_error(RTR("Invalid data type for varying.")); return ERR_PARSE_ERROR; } diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a410cf0ed8..30b6faa360 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_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1))); ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0)); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 59887d7d37..56295a2c5f 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1326,6 +1326,7 @@ public: virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0; virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0; virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0; + virtual void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)) = 0; virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0; virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()) = 0; diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 855267e428..74ae2bfff0 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -69,8 +69,8 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style"); GDVIRTUAL_BIND(font_get_style_name, "font_rid"); - GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased"); - GDVIRTUAL_BIND(font_is_antialiased, "font_rid"); + GDVIRTUAL_BIND(font_set_antialiasing, "font_rid", "antialiasing"); + GDVIRTUAL_BIND(font_get_antialiasing, "font_rid"); GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps"); GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid"); @@ -478,16 +478,16 @@ String TextServerExtension::font_get_name(const RID &p_font_rid) const { return String(); } -void TextServerExtension::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { - GDVIRTUAL_CALL(font_set_antialiased, p_font_rid, p_antialiased); +void TextServerExtension::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) { + GDVIRTUAL_CALL(font_set_antialiasing, p_font_rid, p_antialiasing); } -bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const { - bool ret; - if (GDVIRTUAL_CALL(font_is_antialiased, p_font_rid, ret)) { +TextServer::FontAntialiasing TextServerExtension::font_get_antialiasing(RID p_font_rid) const { + TextServer::FontAntialiasing ret; + if (GDVIRTUAL_CALL(font_get_antialiasing, p_font_rid, ret)) { return ret; } - return false; + return TextServer::FONT_ANTIALIASING_NONE; } void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 7e1ed22390..6a2c199898 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -108,10 +108,10 @@ public: GDVIRTUAL2(font_set_style_name, RID, const String &); GDVIRTUAL1RC(String, font_get_style_name, RID); - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; - virtual bool font_is_antialiased(const RID &p_font_rid) const override; - GDVIRTUAL2(font_set_antialiased, RID, bool); - GDVIRTUAL1RC(bool, font_is_antialiased, RID); + virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override; + virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override; + GDVIRTUAL2(font_set_antialiasing, RID, TextServer::FontAntialiasing); + GDVIRTUAL1RC(TextServer::FontAntialiasing, font_get_antialiasing, RID); virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 66b32dba84..393160fe9e 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -223,8 +223,8 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name); ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name); - ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased); - ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased); + ClassDB::bind_method(D_METHOD("font_set_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing); + ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing); ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps); ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps); @@ -458,6 +458,17 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text); + /* Font AA */ + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_NONE); + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_GRAY); + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_LCD); + + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_NONE); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HRGB); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HBGR); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VRGB); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VBGR); + /* Direction */ BIND_ENUM_CONSTANT(DIRECTION_AUTO); BIND_ENUM_CONSTANT(DIRECTION_LTR); diff --git a/servers/text_server.h b/servers/text_server.h index 9ffc2984d1..9304771d1b 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -47,6 +47,21 @@ class TextServer : public RefCounted { GDCLASS(TextServer, RefCounted); public: + enum FontAntialiasing { + FONT_ANTIALIASING_NONE, + FONT_ANTIALIASING_GRAY, + FONT_ANTIALIASING_LCD, + }; + + enum FontLCDSubpixelLayout { + FONT_LCD_SUBPIXEL_LAYOUT_NONE, + FONT_LCD_SUBPIXEL_LAYOUT_HRGB, + FONT_LCD_SUBPIXEL_LAYOUT_HBGR, + FONT_LCD_SUBPIXEL_LAYOUT_VRGB, + FONT_LCD_SUBPIXEL_LAYOUT_VBGR, + FONT_LCD_SUBPIXEL_LAYOUT_MAX, + }; + enum Direction { DIRECTION_AUTO, DIRECTION_LTR, @@ -233,8 +248,8 @@ public: virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0; virtual String font_get_style_name(const RID &p_font_rid) const = 0; - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0; - virtual bool font_is_antialiased(const RID &p_font_rid) const = 0; + virtual void font_set_antialiasing(RID p_font_rid, FontAntialiasing p_antialiasing) = 0; + virtual FontAntialiasing font_get_antialiasing(RID p_font_rid) const = 0; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0; @@ -572,6 +587,8 @@ VARIANT_ENUM_CAST(TextServer::ContourPointTag); VARIANT_ENUM_CAST(TextServer::SpacingType); VARIANT_BITFIELD_CAST(TextServer::FontStyle); VARIANT_ENUM_CAST(TextServer::StructuredTextParser); +VARIANT_ENUM_CAST(TextServer::FontAntialiasing); +VARIANT_ENUM_CAST(TextServer::FontLCDSubpixelLayout); GDVIRTUAL_NATIVE_PTR(Glyph); GDVIRTUAL_NATIVE_PTR(CaretInfo); diff --git a/tests/core/math/test_quaternion.h b/tests/core/math/test_quaternion.h index 94eef6c463..1b80ffba0b 100644 --- a/tests/core/math/test_quaternion.h +++ b/tests/core/math/test_quaternion.h @@ -41,9 +41,9 @@ namespace TestQuaternion { Quaternion quat_euler_yxz_deg(Vector3 angle) { - double yaw = Math::deg2rad(angle[1]); - double pitch = Math::deg2rad(angle[0]); - double roll = Math::deg2rad(angle[2]); + double yaw = Math::deg_to_rad(angle[1]); + double pitch = Math::deg_to_rad(angle[0]); + double roll = Math::deg_to_rad(angle[2]); // Generate YXZ (Z-then-X-then-Y) Quaternion using single-axis Euler // constructor and quaternion product, both tested separately. @@ -77,7 +77,7 @@ TEST_CASE("[Quaternion] Construct x,y,z,w") { TEST_CASE("[Quaternion] Construct AxisAngle 1") { // Easy to visualize: 120 deg about X-axis. - Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0)); + Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg_to_rad(120.0)); // 0.866 isn't close enough; doctest::Approx doesn't cut much slack! CHECK(q[0] == doctest::Approx(0.866025)); // Sine of half the angle. @@ -88,7 +88,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 1") { TEST_CASE("[Quaternion] Construct AxisAngle 2") { // Easy to visualize: 30 deg about Y-axis. - Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0)); + Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg_to_rad(30.0)); CHECK(q[0] == doctest::Approx(0.0)); CHECK(q[1] == doctest::Approx(0.258819)); // Sine of half the angle. @@ -98,7 +98,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 2") { TEST_CASE("[Quaternion] Construct AxisAngle 3") { // Easy to visualize: 60 deg about Z-axis. - Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0)); + Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg_to_rad(60.0)); CHECK(q[0] == doctest::Approx(0.0)); CHECK(q[1] == doctest::Approx(0.0)); @@ -109,7 +109,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 3") { TEST_CASE("[Quaternion] Construct AxisAngle 4") { // More complex & hard to visualize, so test w/ data from online calculator. Vector3 axis(1.0, 2.0, 0.5); - Quaternion q(axis.normalized(), Math::deg2rad(35.0)); + Quaternion q(axis.normalized(), Math::deg_to_rad(35.0)); CHECK(q[0] == doctest::Approx(0.131239)); CHECK(q[1] == doctest::Approx(0.262478)); @@ -119,7 +119,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 4") { TEST_CASE("[Quaternion] Construct from Quaternion") { Vector3 axis(1.0, 2.0, 0.5); - Quaternion q_src(axis.normalized(), Math::deg2rad(35.0)); + Quaternion q_src(axis.normalized(), Math::deg_to_rad(35.0)); Quaternion q(q_src); CHECK(q[0] == doctest::Approx(0.131239)); @@ -129,9 +129,9 @@ TEST_CASE("[Quaternion] Construct from Quaternion") { } TEST_CASE("[Quaternion] Construct Euler SingleAxis") { - double yaw = Math::deg2rad(45.0); - double pitch = Math::deg2rad(30.0); - double roll = Math::deg2rad(10.0); + double yaw = Math::deg_to_rad(45.0); + double pitch = Math::deg_to_rad(30.0); + double roll = Math::deg_to_rad(10.0); Vector3 euler_y(0.0, yaw, 0.0); Quaternion q_y(euler_y); @@ -156,9 +156,9 @@ TEST_CASE("[Quaternion] Construct Euler SingleAxis") { } TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") { - double yaw = Math::deg2rad(45.0); - double pitch = Math::deg2rad(30.0); - double roll = Math::deg2rad(10.0); + double yaw = Math::deg_to_rad(45.0); + double pitch = Math::deg_to_rad(30.0); + double roll = Math::deg_to_rad(10.0); // Generate YXZ comparision data (Z-then-X-then-Y) using single-axis Euler // constructor and quaternion product, both tested separately. @@ -187,9 +187,9 @@ TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") { } TEST_CASE("[Quaternion] Construct Basis Euler") { - double yaw = Math::deg2rad(45.0); - double pitch = Math::deg2rad(30.0); - double roll = Math::deg2rad(10.0); + double yaw = Math::deg_to_rad(45.0); + double pitch = Math::deg_to_rad(30.0); + double roll = Math::deg_to_rad(10.0); Vector3 euler_yxz(pitch, yaw, roll); Quaternion q_yxz(euler_yxz); Basis basis_axes(euler_yxz); @@ -199,7 +199,7 @@ TEST_CASE("[Quaternion] Construct Basis Euler") { TEST_CASE("[Quaternion] Construct Basis Axes") { // Arbitrary Euler angles. - Vector3 euler_yxz(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34)); + Vector3 euler_yxz(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34)); // Basis vectors from online calculation of rotation matrix. Vector3 i_unit(0.5545787, 0.1823950, 0.8118957); Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555); @@ -248,9 +248,9 @@ TEST_CASE("[Quaternion] Product (book)") { } TEST_CASE("[Quaternion] Product") { - double yaw = Math::deg2rad(45.0); - double pitch = Math::deg2rad(30.0); - double roll = Math::deg2rad(10.0); + double yaw = Math::deg_to_rad(45.0); + double pitch = Math::deg_to_rad(30.0); + double roll = Math::deg_to_rad(10.0); Vector3 euler_y(0.0, yaw, 0.0); Quaternion q_y(euler_y); @@ -292,7 +292,7 @@ TEST_CASE("[Quaternion] Product") { TEST_CASE("[Quaternion] xform unit vectors") { // Easy to visualize: 120 deg about X-axis. // Transform the i, j, & k unit vectors. - Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0)); + Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg_to_rad(120.0)); Vector3 i_t = q.xform(Vector3(1.0, 0.0, 0.0)); Vector3 j_t = q.xform(Vector3(0.0, 1.0, 0.0)); Vector3 k_t = q.xform(Vector3(0.0, 0.0, 1.0)); @@ -305,7 +305,7 @@ TEST_CASE("[Quaternion] xform unit vectors") { CHECK(k_t.length_squared() == doctest::Approx(1.0)); // Easy to visualize: 30 deg about Y-axis. - q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0)); + q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg_to_rad(30.0)); i_t = q.xform(Vector3(1.0, 0.0, 0.0)); j_t = q.xform(Vector3(0.0, 1.0, 0.0)); k_t = q.xform(Vector3(0.0, 0.0, 1.0)); @@ -318,7 +318,7 @@ TEST_CASE("[Quaternion] xform unit vectors") { CHECK(k_t.length_squared() == doctest::Approx(1.0)); // Easy to visualize: 60 deg about Z-axis. - q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0)); + q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg_to_rad(60.0)); i_t = q.xform(Vector3(1.0, 0.0, 0.0)); j_t = q.xform(Vector3(0.0, 1.0, 0.0)); k_t = q.xform(Vector3(0.0, 0.0, 1.0)); @@ -333,7 +333,7 @@ TEST_CASE("[Quaternion] xform unit vectors") { TEST_CASE("[Quaternion] xform vector") { // Arbitrary quaternion rotates an arbitrary vector. - Vector3 euler_yzx(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34)); + Vector3 euler_yzx(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34)); Basis basis_axes(euler_yzx); Quaternion q(basis_axes); diff --git a/tests/scene/test_path_follow_2d.h b/tests/scene/test_path_follow_2d.h index abd12fe862..57261116a2 100644 --- a/tests/scene/test_path_follow_2d.h +++ b/tests/scene/test_path_follow_2d.h @@ -37,7 +37,7 @@ namespace TestPathFollow2D { -TEST_CASE("[PathFollow2D] Sampling with unit offset") { +TEST_CASE("[PathFollow2D] Sampling with progress ratio") { const Ref<Curve2D> &curve = memnew(Curve2D()); curve->add_point(Vector2(0, 0)); curve->add_point(Vector2(100, 0)); @@ -49,37 +49,37 @@ TEST_CASE("[PathFollow2D] Sampling with unit offset") { const PathFollow2D *path_follow_2d = memnew(PathFollow2D); path->add_child(path_follow_2d); - path_follow_2d->set_unit_offset(0); + path_follow_2d->set_progress_ratio(0); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0))); - path_follow_2d->set_unit_offset(0.125); + path_follow_2d->set_progress_ratio(0.125); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0))); - path_follow_2d->set_unit_offset(0.25); + path_follow_2d->set_progress_ratio(0.25); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0))); - path_follow_2d->set_unit_offset(0.375); + path_follow_2d->set_progress_ratio(0.375); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50))); - path_follow_2d->set_unit_offset(0.5); + path_follow_2d->set_progress_ratio(0.5); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100))); - path_follow_2d->set_unit_offset(0.625); + path_follow_2d->set_progress_ratio(0.625); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100))); - path_follow_2d->set_unit_offset(0.75); + path_follow_2d->set_progress_ratio(0.75); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100))); - path_follow_2d->set_unit_offset(0.875); + path_follow_2d->set_progress_ratio(0.875); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50))); - path_follow_2d->set_unit_offset(1); + path_follow_2d->set_progress_ratio(1); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0))); memdelete(path); } -TEST_CASE("[PathFollow2D] Sampling with offset") { +TEST_CASE("[PathFollow2D] Sampling with progress") { const Ref<Curve2D> &curve = memnew(Curve2D()); curve->add_point(Vector2(0, 0)); curve->add_point(Vector2(100, 0)); @@ -91,31 +91,31 @@ TEST_CASE("[PathFollow2D] Sampling with offset") { const PathFollow2D *path_follow_2d = memnew(PathFollow2D); path->add_child(path_follow_2d); - path_follow_2d->set_offset(0); + path_follow_2d->set_progress(0); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0))); - path_follow_2d->set_offset(50); + path_follow_2d->set_progress(50); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0))); - path_follow_2d->set_offset(100); + path_follow_2d->set_progress(100); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0))); - path_follow_2d->set_offset(150); + path_follow_2d->set_progress(150); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50))); - path_follow_2d->set_offset(200); + path_follow_2d->set_progress(200); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100))); - path_follow_2d->set_offset(250); + path_follow_2d->set_progress(250); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100))); - path_follow_2d->set_offset(300); + path_follow_2d->set_progress(300); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100))); - path_follow_2d->set_offset(350); + path_follow_2d->set_progress(350); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50))); - path_follow_2d->set_offset(400); + path_follow_2d->set_progress(400); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0))); memdelete(path); @@ -131,7 +131,7 @@ TEST_CASE("[PathFollow2D] Removal of a point in curve") { const PathFollow2D *path_follow_2d = memnew(PathFollow2D); path->add_child(path_follow_2d); - path_follow_2d->set_unit_offset(0.5); + path_follow_2d->set_progress_ratio(0.5); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0))); curve->remove_point(1); @@ -152,7 +152,7 @@ TEST_CASE("[PathFollow2D] Setting h_offset and v_offset") { const PathFollow2D *path_follow_2d = memnew(PathFollow2D); path->add_child(path_follow_2d); - path_follow_2d->set_unit_offset(0.5); + path_follow_2d->set_progress_ratio(0.5); CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0))); path_follow_2d->set_h_offset(25); @@ -175,32 +175,32 @@ TEST_CASE("[PathFollow2D] Unit offset out of range") { path_follow_2d->set_loop(true); - path_follow_2d->set_unit_offset(-0.3); + path_follow_2d->set_progress_ratio(-0.3); CHECK_MESSAGE( - path_follow_2d->get_unit_offset() == 0.7, - "Unit Offset should loop back from the end in the opposite direction"); + path_follow_2d->get_progress_ratio() == 0.7, + "Progress Ratio should loop back from the end in the opposite direction"); - path_follow_2d->set_unit_offset(1.3); + path_follow_2d->set_progress_ratio(1.3); CHECK_MESSAGE( - path_follow_2d->get_unit_offset() == 0.3, - "Unit Offset should loop back from the end in the opposite direction"); + path_follow_2d->get_progress_ratio() == 0.3, + "Progress Ratio should loop back from the end in the opposite direction"); path_follow_2d->set_loop(false); - path_follow_2d->set_unit_offset(-0.3); + path_follow_2d->set_progress_ratio(-0.3); CHECK_MESSAGE( - path_follow_2d->get_unit_offset() == 0, - "Unit Offset should be clamped at 0"); + path_follow_2d->get_progress_ratio() == 0, + "Progress Ratio should be clamped at 0"); - path_follow_2d->set_unit_offset(1.3); + path_follow_2d->set_progress_ratio(1.3); CHECK_MESSAGE( - path_follow_2d->get_unit_offset() == 1, - "Unit Offset should be clamped at 1"); + path_follow_2d->get_progress_ratio() == 1, + "Progress Ratio should be clamped at 1"); memdelete(path); } -TEST_CASE("[PathFollow2D] Offset out of range") { +TEST_CASE("[PathFollow2D] Progress out of range") { const Ref<Curve2D> &curve = memnew(Curve2D()); curve->add_point(Vector2(0, 0)); curve->add_point(Vector2(100, 0)); @@ -211,27 +211,27 @@ TEST_CASE("[PathFollow2D] Offset out of range") { path_follow_2d->set_loop(true); - path_follow_2d->set_offset(-50); + path_follow_2d->set_progress(-50); CHECK_MESSAGE( - path_follow_2d->get_offset() == 50, - "Offset should loop back from the end in the opposite direction"); + path_follow_2d->get_progress() == 50, + "Progress should loop back from the end in the opposite direction"); - path_follow_2d->set_offset(150); + path_follow_2d->set_progress(150); CHECK_MESSAGE( - path_follow_2d->get_offset() == 50, - "Offset should loop back from the end in the opposite direction"); + path_follow_2d->get_progress() == 50, + "Progress should loop back from the end in the opposite direction"); path_follow_2d->set_loop(false); - path_follow_2d->set_offset(-50); + path_follow_2d->set_progress(-50); CHECK_MESSAGE( - path_follow_2d->get_offset() == 0, - "Offset should be clamped at 0"); + path_follow_2d->get_progress() == 0, + "Progress should be clamped at 0"); - path_follow_2d->set_offset(150); + path_follow_2d->set_progress(150); CHECK_MESSAGE( - path_follow_2d->get_offset() == 100, - "Offset should be clamped at 1"); + path_follow_2d->get_progress() == 100, + "Progress should be clamped at 1"); memdelete(path); } diff --git a/tests/scene/test_path_follow_3d.h b/tests/scene/test_path_follow_3d.h index 9ffe49e3d6..6334fa56de 100644 --- a/tests/scene/test_path_follow_3d.h +++ b/tests/scene/test_path_follow_3d.h @@ -37,7 +37,7 @@ namespace TestPathFollow3D { -TEST_CASE("[PathFollow3D] Sampling with unit offset") { +TEST_CASE("[PathFollow3D] Sampling with progress ratio") { const Ref<Curve3D> &curve = memnew(Curve3D()); curve->add_point(Vector3(0, 0, 0)); curve->add_point(Vector3(100, 0, 0)); @@ -49,37 +49,37 @@ TEST_CASE("[PathFollow3D] Sampling with unit offset") { const PathFollow3D *path_follow_3d = memnew(PathFollow3D); path->add_child(path_follow_3d); - path_follow_3d->set_unit_offset(0); + path_follow_3d->set_progress_ratio(0); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0)); - path_follow_3d->set_unit_offset(0.125); + path_follow_3d->set_progress_ratio(0.125); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0)); - path_follow_3d->set_unit_offset(0.25); + path_follow_3d->set_progress_ratio(0.25); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0); - path_follow_3d->set_unit_offset(0.375); + path_follow_3d->set_progress_ratio(0.375); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0))); - path_follow_3d->set_unit_offset(0.5); + path_follow_3d->set_progress_ratio(0.5); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0))); - path_follow_3d->set_unit_offset(0.625); + path_follow_3d->set_progress_ratio(0.625); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50))); - path_follow_3d->set_unit_offset(0.75); + path_follow_3d->set_progress_ratio(0.75); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100))); - path_follow_3d->set_unit_offset(0.875); + path_follow_3d->set_progress_ratio(0.875); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100))); - path_follow_3d->set_unit_offset(1); + path_follow_3d->set_progress_ratio(1); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100))); memdelete(path); } -TEST_CASE("[PathFollow3D] Sampling with offset") { +TEST_CASE("[PathFollow3D] Sampling with progress") { const Ref<Curve3D> &curve = memnew(Curve3D()); curve->add_point(Vector3(0, 0, 0)); curve->add_point(Vector3(100, 0, 0)); @@ -91,31 +91,31 @@ TEST_CASE("[PathFollow3D] Sampling with offset") { const PathFollow3D *path_follow_3d = memnew(PathFollow3D); path->add_child(path_follow_3d); - path_follow_3d->set_offset(0); + path_follow_3d->set_progress(0); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0)); - path_follow_3d->set_offset(50); + path_follow_3d->set_progress(50); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0)); - path_follow_3d->set_offset(100); + path_follow_3d->set_progress(100); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0); - path_follow_3d->set_offset(150); + path_follow_3d->set_progress(150); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0))); - path_follow_3d->set_offset(200); + path_follow_3d->set_progress(200); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0))); - path_follow_3d->set_offset(250); + path_follow_3d->set_progress(250); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50))); - path_follow_3d->set_offset(300); + path_follow_3d->set_progress(300); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100))); - path_follow_3d->set_offset(350); + path_follow_3d->set_progress(350); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100))); - path_follow_3d->set_offset(400); + path_follow_3d->set_progress(400); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100))); memdelete(path); @@ -131,7 +131,7 @@ TEST_CASE("[PathFollow3D] Removal of a point in curve") { const PathFollow3D *path_follow_3d = memnew(PathFollow3D); path->add_child(path_follow_3d); - path_follow_3d->set_unit_offset(0.5); + path_follow_3d->set_progress_ratio(0.5); CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector2(100, 0, 0))); curve->remove_point(1); @@ -143,7 +143,7 @@ TEST_CASE("[PathFollow3D] Removal of a point in curve") { memdelete(path); } -TEST_CASE("[PathFollow3D] Unit offset out of range") { +TEST_CASE("[PathFollow3D] Progress ratio out of range") { const Ref<Curve3D> &curve = memnew(Curve3D()); curve->add_point(Vector3(0, 0, 0)); curve->add_point(Vector3(100, 0, 0)); @@ -154,32 +154,32 @@ TEST_CASE("[PathFollow3D] Unit offset out of range") { path_follow_3d->set_loop(true); - path_follow_3d->set_unit_offset(-0.3); + path_follow_3d->set_progress_ratio(-0.3); CHECK_MESSAGE( - path_follow_3d->get_unit_offset() == 0.7, - "Unit Offset should loop back from the end in the opposite direction"); + path_follow_3d->get_progress_ratio() == 0.7, + "Progress Ratio should loop back from the end in the opposite direction"); - path_follow_3d->set_unit_offset(1.3); + path_follow_3d->set_progress_ratio(1.3); CHECK_MESSAGE( - path_follow_3d->get_unit_offset() == 0.3, - "Unit Offset should loop back from the end in the opposite direction"); + path_follow_3d->get_progress_ratio() == 0.3, + "Progress Ratio should loop back from the end in the opposite direction"); path_follow_3d->set_loop(false); - path_follow_3d->set_unit_offset(-0.3); + path_follow_3d->set_progress_ratio(-0.3); CHECK_MESSAGE( - path_follow_3d->get_unit_offset() == 0, - "Unit Offset should be clamped at 0"); + path_follow_3d->get_progress_ratio() == 0, + "Progress Ratio should be clamped at 0"); - path_follow_3d->set_unit_offset(1.3); + path_follow_3d->set_progress_ratio(1.3); CHECK_MESSAGE( - path_follow_3d->get_unit_offset() == 1, - "Unit Offset should be clamped at 1"); + path_follow_3d->get_progress_ratio() == 1, + "Progress Ratio should be clamped at 1"); memdelete(path); } -TEST_CASE("[PathFollow3D] Offset out of range") { +TEST_CASE("[PathFollow3D] Progress out of range") { const Ref<Curve3D> &curve = memnew(Curve3D()); curve->add_point(Vector3(0, 0, 0)); curve->add_point(Vector3(100, 0, 0)); @@ -190,27 +190,27 @@ TEST_CASE("[PathFollow3D] Offset out of range") { path_follow_3d->set_loop(true); - path_follow_3d->set_offset(-50); + path_follow_3d->set_progress(-50); CHECK_MESSAGE( - path_follow_3d->get_offset() == 50, - "Offset should loop back from the end in the opposite direction"); + path_follow_3d->get_progress() == 50, + "Progress should loop back from the end in the opposite direction"); - path_follow_3d->set_offset(150); + path_follow_3d->set_progress(150); CHECK_MESSAGE( - path_follow_3d->get_offset() == 50, - "Offset should loop back from the end in the opposite direction"); + path_follow_3d->get_progress() == 50, + "Progress should loop back from the end in the opposite direction"); path_follow_3d->set_loop(false); - path_follow_3d->set_offset(-50); + path_follow_3d->set_progress(-50); CHECK_MESSAGE( - path_follow_3d->get_offset() == 0, - "Offset should be clamped at 0"); + path_follow_3d->get_progress() == 0, + "Progress should be clamped at 0"); - path_follow_3d->set_offset(150); + path_follow_3d->set_progress(150); CHECK_MESSAGE( - path_follow_3d->get_offset() == 100, - "Offset should be clamped at max value of curve"); + path_follow_3d->get_progress() == 100, + "Progress should be clamped at max value of curve"); memdelete(path); } diff --git a/thirdparty/spirv-reflect/patches/zero-calloc.patch b/thirdparty/spirv-reflect/patches/zero-calloc.patch new file mode 100644 index 0000000000..796fe1266a --- /dev/null +++ b/thirdparty/spirv-reflect/patches/zero-calloc.patch @@ -0,0 +1,28 @@ +diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c +index c174ae1900..11ccbdee3a 100644 +--- a/thirdparty/spirv-reflect/spirv_reflect.c ++++ b/thirdparty/spirv-reflect/spirv_reflect.c +@@ -3322,12 +3322,18 @@ static SpvReflectResult ParseExecutionModes( + } + for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { + SpvReflectEntryPoint* p_entry_point = &p_module->entry_points[entry_point_idx]; +- p_entry_point->execution_modes = +- (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes)); +- if (IsNull(p_entry_point->execution_modes)) { +- SafeFree(indices); +- return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; ++// -- GODOT begin -- ++ if (p_entry_point->execution_mode_count > 0) { ++// -- GODOT end -- ++ p_entry_point->execution_modes = ++ (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes)); ++ if (IsNull(p_entry_point->execution_modes)) { ++ SafeFree(indices); ++ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; ++ } ++// -- GODOT begin -- + } ++// -- GODOT end -- + } + + for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) { diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c index c174ae1900..11ccbdee3a 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.c +++ b/thirdparty/spirv-reflect/spirv_reflect.c @@ -3322,12 +3322,18 @@ static SpvReflectResult ParseExecutionModes( } for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { SpvReflectEntryPoint* p_entry_point = &p_module->entry_points[entry_point_idx]; - p_entry_point->execution_modes = - (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes)); - if (IsNull(p_entry_point->execution_modes)) { - SafeFree(indices); - return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; +// -- GODOT begin -- + if (p_entry_point->execution_mode_count > 0) { +// -- GODOT end -- + p_entry_point->execution_modes = + (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes)); + if (IsNull(p_entry_point->execution_modes)) { + SafeFree(indices); + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } +// -- GODOT begin -- } +// -- GODOT end -- } for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) { |