Merge pull request #82057 from YuriSizov/4.1-cherrypicks

Cherry-picks for the 4.1 branch (future 4.1.2) - 2nd batch
This commit is contained in:
Rémi Verschelde 2023-09-21 20:09:13 +02:00 committed by GitHub
commit 089ecc0a82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
172 changed files with 2774 additions and 3667 deletions

View File

@ -18,7 +18,7 @@ jobs:
name: Template (target=template_release)
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java 11
uses: actions/setup-java@v3

View File

@ -16,14 +16,14 @@ jobs:
runs-on: "ubuntu-20.04"
name: "Build and test Godot CPP"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup python and scons
uses: ./.github/actions/godot-deps
# Checkout godot-cpp
- name: Checkout godot-cpp
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: godotengine/godot-cpp
ref: ${{ env.GODOT_BASE_BRANCH }}

View File

@ -18,7 +18,7 @@ jobs:
name: Template (target=template_release)
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache

View File

@ -74,7 +74,7 @@ jobs:
artifact: true
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# Need newer mesa for lavapipe to work properly.
- name: Linux dependencies for tests
@ -100,7 +100,7 @@ jobs:
uses: ./.github/actions/godot-deps
- name: Set up .NET Sdk
uses: actions/setup-dotnet@v2
uses: actions/setup-dotnet@v3
if: ${{ matrix.build-mono }}
with:
dotnet-version: '6.0.x'
@ -119,7 +119,7 @@ jobs:
- name: Generate C# glue
if: ${{ matrix.build-mono }}
run: |
${{ matrix.bin }} --headless --generate-mono-glue ./modules/mono/glue || true
${{ matrix.bin }} --headless --generate-mono-glue ./modules/mono/glue
- name: Build .NET solutions
if: ${{ matrix.build-mono }}
@ -165,7 +165,7 @@ jobs:
- name: Check for GDExtension compatibility
if: ${{ matrix.api-compat }}
run: |
./misc/scripts/validate_extension_api.sh "${{ matrix.bin }}" || true # don't fail the CI for now
./misc/scripts/validate_extension_api.sh "${{ matrix.bin }}"
# Download and run the test project
- name: Test Godot project

View File

@ -33,7 +33,7 @@ jobs:
sconsflags: debug_symbols=no
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 2

View File

@ -7,7 +7,7 @@ env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: '4.1'
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no
EM_VERSION: 3.1.18
EM_VERSION: 3.1.45
EM_CACHE_FOLDER: "emsdk-cache"
concurrency:
@ -16,11 +16,11 @@ concurrency:
jobs:
web-template:
runs-on: "ubuntu-20.04"
runs-on: "ubuntu-22.04"
name: Template (target=template_release)
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Emscripten latest
uses: mymindstorm/setup-emsdk@v12

View File

@ -38,7 +38,7 @@ jobs:
sconsflags: debug_symbols=no
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache

View File

@ -8,10 +8,214 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
#### Core
- Add check to ensure registered classes are declared ([GH-81020](https://github.com/godotengine/godot/pull/81020)).
#### Rendering
- Add motion vector support for GPU 3D Particles ([GH-80688](https://github.com/godotengine/godot/pull/80688)).
#### Shaders
- Allow more hint types for uniform arrays ([GH-79100](https://github.com/godotengine/godot/pull/79100)).
- Add autocomplete for filter/repeat hints on uniform arrays ([GH-79402](https://github.com/godotengine/godot/pull/79402)).
### Changed
#### 3D
- Change property hint range for camera attributes exposure multiplier ([GH-79138](https://github.com/godotengine/godot/pull/79138)).
#### Buildsystem
- Disable C++ exception handling (off by default in 4.1) ([GH-80612](https://github.com/godotengine/godot/pull/80612)).
- libpng: Enable intrinsics on x86/SSE2, ppc64/VSX, and all arm/NEON ([GH-78325](https://github.com/godotengine/godot/pull/78325)).
- Linux: Allow unbundling OpenXR ([GH-73443](https://github.com/godotengine/godot/pull/73443)).
- MSVC: Pass build options configuration to Visual Studio projects ([GH-79238](https://github.com/godotengine/godot/pull/79238)).
- MSVC: Make incremental linking optional ([GH-80482](https://github.com/godotengine/godot/pull/80482), [GH-81144](https://github.com/godotengine/godot/pull/81144)).
- MSVC: Enable `/WX` on LINKFLAGS for MSVC with `werror=yes` ([GH-80711](https://github.com/godotengine/godot/pull/80711)).
#### C#/.NET
- Hide hostfxr not found error ([GH-81690](https://github.com/godotengine/godot/pull/81690)).
#### Editor
- Don't use splash minimum display time in editor ([GH-79388](https://github.com/godotengine/godot/pull/79388)).
- Automatically add path to built-in scripts ([GH-79920](https://github.com/godotengine/godot/pull/79920)).
- Uncollapse favorites by default in the editor FileSystem dock ([GH-79971](https://github.com/godotengine/godot/pull/79971)).
- Use `ui_text_submit` instead of `ui_accept` to confirm and close text prompts ([GH-81189](https://github.com/godotengine/godot/pull/81189)).
- Make editor camera speed indicator use `m/s` and `m` ([GH-81810](https://github.com/godotengine/godot/pull/81810)).
#### GUI
- Enable transparent background for GUI tooltips ([GH-81669](https://github.com/godotengine/godot/pull/81669)).
#### Input
- Prevent double input events on gamepad when running through steam input ([GH-76045](https://github.com/godotengine/godot/pull/76045)).
- Ensure `joy_connection_changed` is emitted on the main thread ([GH-80432](https://github.com/godotengine/godot/pull/80432)).
- Android: Set `echo` property for the physical keyboard events ([GH-79089](https://github.com/godotengine/godot/pull/79089)).
#### Networking
- Web: Always return -1 as body length in HTTPClientWeb ([GH-79846](https://github.com/godotengine/godot/pull/79846)).
#### Porting
- X11: Do not fail DisplayServer init if non-essential extensions are missing ([GH-80240](https://github.com/godotengine/godot/pull/80240)).
#### Rendering
- Enable depth writes during shadow pass and depth pass, disable during color pass ([GH-80070](https://github.com/godotengine/godot/pull/80070)).
- Remove GPU readback from `NoiseTexture3D.get_format()` ([GH-80407](https://github.com/godotengine/godot/pull/80407)).
- Clamp Volumetric Fog Length property to prevent rendering issues ([GH-80485](https://github.com/godotengine/godot/pull/80485)).
- Propagate error correctly when max texture size for lightmaps is too small ([GH-81543](https://github.com/godotengine/godot/pull/81543)).
- GLES3: Reset anisotropic filtering when changing texture filtering mode ([GH-79568](https://github.com/godotengine/godot/pull/79568)).
- GLES3: Don't call `glTexParameter*` for invalid filter and repeat modes ([GH-79685](https://github.com/godotengine/godot/pull/79685)).
#### Thirdparty
- FreeType updated to version 2.13.2.
- ICU4C updated to version 73.2.
- libpng updated to version 1.6.40.
- libwebp updated to version 1.3.1.
- mbedtls updated to version version 2.28.4.
- miniupnpc updated to version 2.2.5.
- openxr updated to version 1.0.28.
- tinyexr updated to version 1.0.7.
### Fixed
#### 2D
- Fix Camera2D crash when edited scene root is null ([GH-79645](https://github.com/godotengine/godot/pull/79645)).
- Fix `CanvasModulate` logic for modulating the canvas ([GH-79747](https://github.com/godotengine/godot/pull/79747)).
#### 3D
- Fix VoxelGI saving VoxelGIData as a built-in file, despite being prompted to save it to an external file ([GH-78772](https://github.com/godotengine/godot/pull/78772)).
- Fix Curve3D baking up vectors for nontrivial curves ([GH-81885](https://github.com/godotengine/godot/pull/81885)).
#### Animation
- Fix `Animation::subtract_variant` for affine transforms ([GH-79279](https://github.com/godotengine/godot/pull/79279)).
- Fix `AnimationNodeTransition` with negative time scale ([GH-79403](https://github.com/godotengine/godot/pull/79403)).
- Remove animation tracks with correct indices ([GH-81651](https://github.com/godotengine/godot/pull/81651)).
#### Audio
- Fix audio stream generators getting freed accidentally ([GH-81508](https://github.com/godotengine/godot/pull/81508)).
#### Buildsystem
- Fix GCC `-Wmaybe-uninitialized` warnings ([GH-80615](https://github.com/godotengine/godot/pull/80615)).
- Web: Workaround Emscripten 3.1.42+ LTO regression ([GH-81340](https://github.com/godotengine/godot/pull/81340)).
#### C#/.NET
- Fix deserialization of delegates that are 0-parameter overloads ([GH-78877](https://github.com/godotengine/godot/pull/78877)).
- Add missing `useModelFront` parameter to GodotSharp Basis and Transform ([GH-79082](https://github.com/godotengine/godot/pull/79082)).
- Fix double unregistration on dispose of Array ([GH-81230](https://github.com/godotengine/godot/pull/81230)).
#### Core
- Fix range error for `Array.slice` ([GH-79103](https://github.com/godotengine/godot/pull/79103)).
- Fix byte to float color conversion in `DisplayServerWindows::screen_get_pixel` ([GH-79350](https://github.com/godotengine/godot/pull/79350)).
- Fix recursion level check for array stringification ([GH-79370](https://github.com/godotengine/godot/pull/79370)).
- Fix global transform validity for `Node2D` and `Control` ([GH-80105](https://github.com/godotengine/godot/pull/80105)).
- Fix recursion level check for `VariantWriter::write()` with objects ([GH-81123](https://github.com/godotengine/godot/pull/81123)).
- Fix string conversion for -0.0 float values ([GH-81328](https://github.com/godotengine/godot/pull/81328)).
#### Editor
- Fix history mismatch ([GH-78827](https://github.com/godotengine/godot/pull/78827)).
- Improve resolution of script type icons ([GH-79203](https://github.com/godotengine/godot/pull/79203), [GH-81336](https://github.com/godotengine/godot/pull/81336)).
- Fix arg count checks in `SceneDebugger` ([GH-79655](https://github.com/godotengine/godot/pull/79655)).
- Make the single window mode check more strict ([GH-79793](https://github.com/godotengine/godot/pull/79793)).
- Fix crash when using "Close All Tabs" ([GH-79917](https://github.com/godotengine/godot/pull/79917)).
- Fix a crash when plugin tries to call `make_mesh_previews` on enable ([GH-81121](https://github.com/godotengine/godot/pull/81121)).
#### Export
- Fix Windows console wrapper and icon being swapped ([GH-80357](https://github.com/godotengine/godot/pull/80357)).
#### GDExtension
- Fix version check for GDExtension ([GH-80591](https://github.com/godotengine/godot/pull/80591)).
- Fix overriding `_export_begin`, `_export_file` and `_export_end` from GDExtension ([GH-80999](https://github.com/godotengine/godot/pull/80999)).
#### GDScript
- Fix conflict between property and group names ([GH-78254](https://github.com/godotengine/godot/pull/78254)).
- Properly track extents of constants ([GH-79301](https://github.com/godotengine/godot/pull/79301)).
- Fix dumping of signal API parameters ([GH-81599](https://github.com/godotengine/godot/pull/81599)).
#### GUI
- Fix RichTextLabel character line and paragraph index getters ([GH-76759](https://github.com/godotengine/godot/pull/76759)).
- Fix text overlapping icon in `Tree` ([GH-78756](https://github.com/godotengine/godot/pull/78756)).
- Fix delay on tab resizing when (un)hovering tabs ([GH-78777](https://github.com/godotengine/godot/pull/78777)).
- Fix `Tree` performance regression by using cache ([GH-79325](https://github.com/godotengine/godot/pull/79325)).
- Fix Button clipping when internal margins exist ([GH-79455](https://github.com/godotengine/godot/pull/79455)).
- Make `OptionButton`` resize when disabling "Fit to Longest Item" ([GH-79494](https://github.com/godotengine/godot/pull/79494)).
- Fix `root_node_layout_direction` project setting being incorrectly exposed as a range ([GH-79611](https://github.com/godotengine/godot/pull/79611)).
- Fix `Button` text when the overrun behavior is other than "No Trimming" ([GH-80402](https://github.com/godotengine/godot/pull/80402)).
- Fix `CodeEdit` completion being very slow in certain cases ([GH-80472](https://github.com/godotengine/godot/pull/80472)).
- Fix crash when hiding subwindow during popup of new subwindow ([GH-80780](https://github.com/godotengine/godot/pull/80780)).
- RTL: Improve performance by using list iterators for item/paragraph removal ([GH-80857](https://github.com/godotengine/godot/pull/80857)).
- Fix setting TabContainer's `font_hovered_color` theme property ([GH-81040](https://github.com/godotengine/godot/pull/81040)).
- Fix ItemList not updating when icon scale changes ([GH-81268](https://github.com/godotengine/godot/pull/81268)).
#### Import
- Use image index instead of texture index for `source_images` ([GH-80314](https://github.com/godotengine/godot/pull/80314)).
#### Navigation
- Fix NavigationObstacle2D debug position ([GH-79392](https://github.com/godotengine/godot/pull/79392)).
- Make NavigationRegion3D baking NavMesh on the main thread not finish deferred ([GH-79465](https://github.com/godotengine/godot/pull/79465)).
- Fix NavMesh `map_update_id` returning 0 results in errors ([GH-80189](https://github.com/godotengine/godot/pull/80189)).
#### Networking
- Prevent crash when accessing `Node` Multiplayer from thread ([GH-79332](https://github.com/godotengine/godot/pull/79332)).
- ENet: Better handle truncated socket messages ([GH-79699](https://github.com/godotengine/godot/pull/79699)).
- ENet: Properly set transfer flags when using custom channels ([GH-80293](https://github.com/godotengine/godot/pull/80293)).
#### Porting
- macOS: Fix uncapped frame rate for windows in the non-active workspaces ([GH-79572](https://github.com/godotengine/godot/pull/79572)).
- Web: Fix file permissions for the web platform (affects every Unix-like platform) ([GH-79866](https://github.com/godotengine/godot/pull/79866)).
- Web: Fix `JavaScriptBridge.eval()` never returning PackedByteArray ([GH-81015](https://github.com/godotengine/godot/pull/81015)).
#### Rendering
- Fix crash when calling `get_video_adapter_*` in a thread ([GH-79528](https://github.com/godotengine/godot/pull/79528)).
- Unbind the framebuffer when updating meshes ([GH-79772](https://github.com/godotengine/godot/pull/79772)).
- Fix motion vectors being corrupted when using `precision=double` ([GH-80257](https://github.com/godotengine/godot/pull/80257)).
- Fix integer underflow when rounding up in VoxelGI ([GH-80356](https://github.com/godotengine/godot/pull/80356)).
- Improve handling of motion vectors for multimesh instances ([GH-80414](https://github.com/godotengine/godot/pull/80414)).
- Clear SDFGI textures when created ([GH-80889](https://github.com/godotengine/godot/pull/80889)).
- Fix integer value for `GL_MAX_UNIFORM_BLOCK_SIZE` overflowing ([GH-80909](https://github.com/godotengine/godot/pull/80909)).
- Add half-pixel offset to lightmapper rasterization ([GH-81872](https://github.com/godotengine/godot/pull/81872)).
- GLES3: Fix multimesh rendering when using colors or custom data ([GH-79660](https://github.com/godotengine/godot/pull/79660)).
- GLES3: Fix memory access error for `MultiMesh` ([GH-80788](https://github.com/godotengine/godot/pull/80788)).
- GLES3: Fix `glMapBufferRange` return null when `r_index + last_item_index > max_instance` ([GH-81036](https://github.com/godotengine/godot/pull/81036)).
- Vulkan: Fix texture update ([GH-80781](https://github.com/godotengine/godot/pull/80781)).
- Vulkan: Fix crash with many Omni/SpotLights, Decals or ReflectionProbes ([GH-80845](https://github.com/godotengine/godot/pull/80845)).
#### Shaders
- Fix shader type detection ([GH-79287](https://github.com/godotengine/godot/pull/79287)).
- Fix Shader and ShaderInclude resource loading ([GH-80705](https://github.com/godotengine/godot/pull/80705)).
- Fix empty shader resource loading ([GH-81300](https://github.com/godotengine/godot/pull/81300)).
#### XR
- Fix issue with accessing hand tracking without timing info ([GH-78817](https://github.com/godotengine/godot/pull/78817)).
## [4.1.1] - 2023-07-17

View File

@ -193,6 +193,7 @@ opts.Add(BoolVariable("vulkan", "Enable the vulkan rendering driver", True))
opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 rendering driver", True))
opts.Add(BoolVariable("openxr", "Enable the OpenXR driver", True))
opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loader dynamically", True))
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", False))
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
@ -240,6 +241,7 @@ opts.Add(BoolVariable("builtin_libwebp", "Use the built-in libwebp library", Tru
opts.Add(BoolVariable("builtin_wslay", "Use the built-in wslay library", True))
opts.Add(BoolVariable("builtin_mbedtls", "Use the built-in mbedTLS library", True))
opts.Add(BoolVariable("builtin_miniupnpc", "Use the built-in miniupnpc library", True))
opts.Add(BoolVariable("builtin_openxr", "Use the built-in OpenXR library", True))
opts.Add(BoolVariable("builtin_pcre2", "Use the built-in PCRE2 library", True))
opts.Add(BoolVariable("builtin_pcre2_with_jit", "Use JIT compiler for the built-in PCRE2 library", True))
opts.Add(BoolVariable("builtin_recastnavigation", "Use the built-in Recast navigation library", True))
@ -699,6 +701,16 @@ if selected_platform in platform_list:
)
Exit(255)
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time (GH-80513).
if env["disable_exceptions"]:
if env.msvc:
env.Append(CPPDEFINES=[("_HAS_EXCEPTIONS", 0)])
else:
env.Append(CCFLAGS=["-fno-exceptions"])
elif env.msvc:
env.Append(CCFLAGS=["/EHsc"])
# Configure compiler warnings
if env.msvc: # MSVC
if env["warnings"] == "no":
@ -728,11 +740,9 @@ if selected_platform in platform_list:
]
)
# Set exception handling model to avoid warnings caused by Windows system headers.
env.Append(CCFLAGS=["/EHsc"])
if env["werror"]:
env.Append(CCFLAGS=["/WX"])
env.Append(LINKFLAGS=["/WX"])
else: # GCC, Clang
common_warnings = []
@ -958,7 +968,7 @@ if selected_platform in platform_list:
print("Error: The `vsproj` option is only usable on Windows with Visual Studio.")
Exit(255)
env["CPPPATH"] = [Dir(path) for path in env["CPPPATH"]]
methods.generate_vs_project(env, GetOption("num_jobs"), env["vsproj_name"])
methods.generate_vs_project(env, ARGUMENTS, env["vsproj_name"])
methods.generate_cpp_hint_file("cpp.hint")
# Check for the existence of headers

View File

@ -603,12 +603,13 @@ Ref<Resource> GDExtensionResourceLoader::load(const String &p_path, const String
}
bool compatible = true;
if (VERSION_MAJOR < compatibility_minimum[0]) {
compatible = false;
} else if (VERSION_MINOR < compatibility_minimum[1]) {
compatible = false;
} else if (VERSION_PATCH < compatibility_minimum[2]) {
compatible = false;
// Check version lexicographically.
if (VERSION_MAJOR != compatibility_minimum[0]) {
compatible = VERSION_MAJOR > compatibility_minimum[0];
} else if (VERSION_MINOR != compatibility_minimum[1]) {
compatible = VERSION_MINOR > compatibility_minimum[1];
} else {
compatible = VERSION_PATCH >= compatibility_minimum[2];
}
if (!compatible) {
if (r_error) {

View File

@ -113,6 +113,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &Input::get_joy_axis);
ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &Input::get_joy_name);
ClassDB::bind_method(D_METHOD("get_joy_guid", "device"), &Input::get_joy_guid);
ClassDB::bind_method(D_METHOD("should_ignore_device", "vendor_id", "product_id"), &Input::should_ignore_device);
ClassDB::bind_method(D_METHOD("get_connected_joypads"), &Input::get_connected_joypads);
ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength);
ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration);
@ -472,7 +473,8 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S
}
joy_names[p_idx] = js;
emit_signal(SNAME("joy_connection_changed"), p_idx, p_connected);
// Ensure this signal is emitted on the main thread, as some platforms (e.g. Linux) call this from a different thread.
call_deferred("emit_signal", SNAME("joy_connection_changed"), p_idx, p_connected);
}
Vector3 Input::get_gravity() const {
@ -1498,6 +1500,11 @@ String Input::get_joy_guid(int p_device) const {
return joy_names[p_device].uid;
}
bool Input::should_ignore_device(int p_vendor_id, int p_product_id) const {
uint32_t full_id = (((uint32_t)p_vendor_id) << 16) | ((uint16_t)p_product_id);
return ignored_device_ids.has(full_id);
}
TypedArray<int> Input::get_connected_joypads() {
TypedArray<int> ret;
HashMap<int, Joypad>::Iterator elem = joy_names.begin();
@ -1542,6 +1549,27 @@ Input::Input() {
}
}
String env_ignore_devices = OS::get_singleton()->get_environment("SDL_GAMECONTROLLER_IGNORE_DEVICES");
if (!env_ignore_devices.is_empty()) {
Vector<String> entries = env_ignore_devices.split(",");
for (int i = 0; i < entries.size(); i++) {
Vector<String> vid_pid = entries[i].split("/");
if (vid_pid.size() < 2) {
continue;
}
print_verbose(vformat("Device Ignored -- Vendor: %s Product: %s", vid_pid[0], vid_pid[1]));
const uint16_t vid_unswapped = vid_pid[0].hex_to_int();
const uint16_t pid_unswapped = vid_pid[1].hex_to_int();
const uint16_t vid = BSWAP16(vid_unswapped);
const uint16_t pid = BSWAP16(pid_unswapped);
uint32_t full_id = (((uint32_t)vid) << 16) | ((uint16_t)pid);
ignored_device_ids.insert(full_id);
}
}
legacy_just_pressed_behavior = GLOBAL_DEF("input_devices/compatibility/legacy_just_pressed_behavior", false);
if (Engine::get_singleton()->is_editor_hint()) {
// Always use standard behavior in the editor.

View File

@ -154,6 +154,9 @@ private:
VelocityTrack mouse_velocity_track;
HashMap<int, VelocityTrack> touch_velocity_track;
HashMap<int, Joypad> joy_names;
HashSet<uint32_t> ignored_device_ids;
int fallback_mapping = -1;
CursorShape default_shape = CURSOR_ARROW;
@ -328,6 +331,7 @@ public:
bool is_joy_known(int p_device);
String get_joy_guid(int p_device) const;
bool should_ignore_device(int p_vendor_id, int p_product_id) const;
void set_fallback_mapping(String p_guid);
void flush_buffered_events();

View File

@ -44,8 +44,8 @@ protected:
String _get_cache_path() { return cache_path; }
struct FileCache {
String path; // Local path (as in "folder/to/file.png")
uint64_t server_modified_time; // MD5 checksum.
uint64_t modified_time;
uint64_t server_modified_time = 0; // MD5 checksum.
uint64_t modified_time = 0;
};
virtual bool _is_configured() { return !cache_path.is_empty(); }
// Can be re-implemented per platform. If so, feel free to ignore get_cache_path()

View File

@ -187,6 +187,7 @@ public:
template <class T>
static void register_class(bool p_virtual = false) {
GLOBAL_LOCK_FUNCTION;
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
@ -201,6 +202,7 @@ public:
template <class T>
static void register_abstract_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
@ -221,6 +223,7 @@ public:
template <class T>
static void register_custom_instance_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);

View File

@ -382,6 +382,7 @@ private:
friend class ::ClassDB; \
\
public: \
typedef m_class self_type; \
static constexpr bool _class_is_enabled = !bool(GD_IS_DEFINED(ClassDB_Disable_##m_class)) && m_inherits::_class_is_enabled; \
virtual String get_class() const override { \
if (_get_extension()) { \
@ -551,6 +552,8 @@ class ScriptInstance;
class Object {
public:
typedef Object self_type;
enum ConnectFlags {
CONNECT_DEFERRED = 1,
CONNECT_PERSIST = 2, // hint for scene to save this connection

View File

@ -1493,9 +1493,9 @@ String String::num(double p_num, int p_decimals) {
if (p_decimals < 0) {
p_decimals = 14;
const double abs_num = ABS(p_num);
const double abs_num = Math::abs(p_num);
if (abs_num > 10) {
// We want to align the digits to the above sane default, so we only
// We want to align the digits to the above reasonable default, so we only
// need to subtract log10 for numbers with a positive power of ten.
p_decimals -= (int)floor(log10(abs_num));
}
@ -4869,8 +4869,8 @@ String String::sprintf(const Array &values, bool *error) const {
}
double value = values[value_index];
bool is_negative = (value < 0);
String str = String::num(ABS(value), min_decimals);
bool is_negative = signbit(value);
String str = String::num(Math::abs(value), min_decimals);
const bool is_finite = Math::is_finite(value);
// Pad decimals out.
@ -4932,7 +4932,7 @@ String String::sprintf(const Array &values, bool *error) const {
String str = "(";
for (int i = 0; i < count; i++) {
double val = vec[i];
String number_str = String::num(ABS(val), min_decimals);
String number_str = String::num(Math::abs(val), min_decimals);
const bool is_finite = Math::is_finite(val);
// Pad decimals out.

View File

@ -1754,11 +1754,10 @@ String Variant::stringify(int recursion_count) const {
case COLOR:
return operator Color();
case DICTIONARY: {
ERR_FAIL_COND_V_MSG(recursion_count > MAX_RECURSION, "{ ... }", "Maximum dictionary recursion reached!");
recursion_count++;
const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem);
if (recursion_count > MAX_RECURSION) {
ERR_PRINT("Maximum dictionary recursion reached!");
return "{ ... }";
}
// Add leading and trailing space to Dictionary printing. This distinguishes it
// from array printing on fonts that have similar-looking {} and [] characters.
@ -1768,7 +1767,6 @@ String Variant::stringify(int recursion_count) const {
Vector<_VariantStrPair> pairs;
recursion_count++;
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
_VariantStrPair sp;
sp.key = stringify_variant_clean(E->get(), recursion_count);
@ -1787,6 +1785,7 @@ String Variant::stringify(int recursion_count) const {
return str;
}
// Packed arrays cannot contain recursive structures, the recursion_count increment is not needed.
case PACKED_VECTOR2_ARRAY: {
return stringify_vector(operator Vector<Vector2>(), recursion_count);
}
@ -1815,13 +1814,10 @@ String Variant::stringify(int recursion_count) const {
return stringify_vector(operator Vector<double>(), recursion_count);
}
case ARRAY: {
Array arr = operator Array();
if (recursion_count > MAX_RECURSION) {
ERR_PRINT("Maximum array recursion reached!");
return "[...]";
}
ERR_FAIL_COND_V_MSG(recursion_count > MAX_RECURSION, "[...]", "Maximum array recursion reached!");
recursion_count++;
return stringify_vector(arr, recursion_count);
return stringify_vector(operator Array(), recursion_count);
}
case OBJECT: {
if (_get_obj().obj) {

View File

@ -1708,7 +1708,7 @@ static String rtos_fix(double p_value) {
}
}
Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int recursion_count) {
Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count) {
switch (p_variant.get_type()) {
case Variant::NIL: {
p_store_string_func(p_store_string_ud, "null");
@ -1730,10 +1730,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::STRING: {
String str = p_variant;
str = "\"" + str.c_escape_multiline() + "\"";
p_store_string_func(p_store_string_ud, str);
} break;
// Math types.
case Variant::VECTOR2: {
Vector2 v = p_variant;
p_store_string_func(p_store_string_ud, "Vector2(" + rtos_fix(v.x) + ", " + rtos_fix(v.y) + ")");
@ -1745,12 +1746,10 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
case Variant::RECT2: {
Rect2 aabb = p_variant;
p_store_string_func(p_store_string_ud, "Rect2(" + rtos_fix(aabb.position.x) + ", " + rtos_fix(aabb.position.y) + ", " + rtos_fix(aabb.size.x) + ", " + rtos_fix(aabb.size.y) + ")");
} break;
case Variant::RECT2I: {
Rect2i aabb = p_variant;
p_store_string_func(p_store_string_ud, "Rect2i(" + itos(aabb.position.x) + ", " + itos(aabb.position.y) + ", " + itos(aabb.size.x) + ", " + itos(aabb.size.y) + ")");
} break;
case Variant::VECTOR3: {
Vector3 v = p_variant;
@ -1771,17 +1770,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
case Variant::PLANE: {
Plane p = p_variant;
p_store_string_func(p_store_string_ud, "Plane(" + rtos_fix(p.normal.x) + ", " + rtos_fix(p.normal.y) + ", " + rtos_fix(p.normal.z) + ", " + rtos_fix(p.d) + ")");
} break;
case Variant::AABB: {
AABB aabb = p_variant;
p_store_string_func(p_store_string_ud, "AABB(" + rtos_fix(aabb.position.x) + ", " + rtos_fix(aabb.position.y) + ", " + rtos_fix(aabb.position.z) + ", " + rtos_fix(aabb.size.x) + ", " + rtos_fix(aabb.size.y) + ", " + rtos_fix(aabb.size.z) + ")");
} break;
case Variant::QUATERNION: {
Quaternion quaternion = p_variant;
p_store_string_func(p_store_string_ud, "Quaternion(" + rtos_fix(quaternion.x) + ", " + rtos_fix(quaternion.y) + ", " + rtos_fix(quaternion.z) + ", " + rtos_fix(quaternion.w) + ")");
} break;
case Variant::TRANSFORM2D: {
String s = "Transform2D(";
@ -1796,7 +1792,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, s + ")");
} break;
case Variant::BASIS: {
String s = "Basis(";
@ -1811,7 +1806,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, s + ")");
} break;
case Variant::TRANSFORM3D: {
String s = "Transform3D(";
@ -1845,30 +1839,23 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, s + ")");
} break;
// misc types
// Misc types.
case Variant::COLOR: {
Color c = p_variant;
p_store_string_func(p_store_string_ud, "Color(" + rtos_fix(c.r) + ", " + rtos_fix(c.g) + ", " + rtos_fix(c.b) + ", " + rtos_fix(c.a) + ")");
} break;
case Variant::STRING_NAME: {
String str = p_variant;
str = "&\"" + str.c_escape() + "\"";
p_store_string_func(p_store_string_ud, str);
} break;
case Variant::NODE_PATH: {
String str = p_variant;
str = "NodePath(\"" + str.c_escape() + "\")";
p_store_string_func(p_store_string_ud, str);
} break;
case Variant::RID: {
RID rid = p_variant;
if (rid == RID()) {
p_store_string_func(p_store_string_ud, "RID()");
} else {
@ -1885,6 +1872,13 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} break;
case Variant::OBJECT: {
if (unlikely(p_recursion_count > MAX_RECURSION)) {
ERR_PRINT("Max recursion reached");
p_store_string_func(p_store_string_ud, "null");
return OK;
}
p_recursion_count++;
Object *obj = p_variant.get_validated_object();
if (!obj) {
@ -1934,21 +1928,20 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, "\"" + E.name + "\":");
write(obj->get(E.name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
write(obj->get(E.name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count);
}
}
p_store_string_func(p_store_string_ud, ")\n");
} break;
case Variant::DICTIONARY: {
Dictionary dict = p_variant;
if (recursion_count > MAX_RECURSION) {
if (unlikely(p_recursion_count > MAX_RECURSION)) {
ERR_PRINT("Max recursion reached");
p_store_string_func(p_store_string_ud, "{}");
} else {
recursion_count++;
p_recursion_count++;
List<Variant> keys;
dict.get_key_list(&keys);
@ -1961,9 +1954,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, "{\n");
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, recursion_count);
write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count);
p_store_string_func(p_store_string_ud, ": ");
write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, recursion_count);
write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count);
if (E->next()) {
p_store_string_func(p_store_string_ud, ",\n");
} else {
@ -1973,7 +1966,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, "}");
}
} break;
case Variant::ARRAY: {
@ -2009,11 +2001,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, "](");
}
if (recursion_count > MAX_RECURSION) {
if (unlikely(p_recursion_count > MAX_RECURSION)) {
ERR_PRINT("Max recursion reached");
p_store_string_func(p_store_string_ud, "[]");
} else {
recursion_count++;
p_recursion_count++;
p_store_string_func(p_store_string_ud, "[");
int len = array.size();
@ -2021,7 +2013,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (i > 0) {
p_store_string_func(p_store_string_ud, ", ");
}
write(array[i], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, recursion_count);
write(array[i], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count);
}
p_store_string_func(p_store_string_ud, "]");
@ -2030,7 +2022,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
if (array.get_typed_builtin() != Variant::NIL) {
p_store_string_func(p_store_string_ud, ")");
}
} break;
case Variant::PACKED_BYTE_ARRAY: {
@ -2048,7 +2039,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
case Variant::PACKED_INT32_ARRAY: {
p_store_string_func(p_store_string_ud, "PackedInt32Array(");
@ -2065,7 +2055,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
case Variant::PACKED_INT64_ARRAY: {
p_store_string_func(p_store_string_ud, "PackedInt64Array(");
@ -2082,7 +2071,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
case Variant::PACKED_FLOAT32_ARRAY: {
p_store_string_func(p_store_string_ud, "PackedFloat32Array(");
@ -2098,7 +2086,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
case Variant::PACKED_FLOAT64_ARRAY: {
p_store_string_func(p_store_string_ud, "PackedFloat64Array(");
@ -2114,7 +2101,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
case Variant::PACKED_STRING_ARRAY: {
p_store_string_func(p_store_string_ud, "PackedStringArray(");
@ -2130,7 +2116,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
case Variant::PACKED_VECTOR2_ARRAY: {
p_store_string_func(p_store_string_ud, "PackedVector2Array(");
@ -2146,7 +2131,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
case Variant::PACKED_VECTOR3_ARRAY: {
p_store_string_func(p_store_string_ud, "PackedVector3Array(");
@ -2162,7 +2146,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
case Variant::PACKED_COLOR_ARRAY: {
p_store_string_func(p_store_string_ud, "PackedColorArray(");
@ -2178,8 +2161,8 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
}
p_store_string_func(p_store_string_ud, ")");
} break;
default: {
ERR_PRINT("Unknown variant type");
return ERR_BUG;

View File

@ -160,7 +160,7 @@ public:
typedef Error (*StoreStringFunc)(void *ud, const String &p_string);
typedef String (*EncodeResourceFunc)(void *ud, const Ref<Resource> &p_resource);
static Error write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int recursion_count = 0);
static Error write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count = 0);
static Error write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func = nullptr, void *p_encode_res_ud = nullptr);
};

View File

@ -5,7 +5,7 @@
</brief_description>
<description>
A node that provides a thickened polygon shape (a prism) to a [CollisionObject2D] parent and allows to edit it. The polygon can be concave or convex. This can give a detection shape to an [Area2D] or turn [PhysicsBody2D] into a solid object.
[b]Warning:[/b] A non-uniformly scaled [CollisionShape3D] will likely not behave as expected. Make sure to keep its scale the same on all axes and adjust its shape resource instead.
[b]Warning:[/b] A non-uniformly scaled [CollisionShape2D] will likely not behave as expected. Make sure to keep its scale the same on all axes and adjust its shape resource instead.
</description>
<tutorials>
</tutorials>

View File

@ -6,7 +6,7 @@
<description>
A 2D convex polygon shape, intended for use in physics. Used internally in [CollisionPolygon2D] when it's in [code]BUILD_SOLIDS[/code] mode.
[ConvexPolygonShape2D] is [i]solid[/i], which means it detects collisions from objects that are fully inside it, unlike [ConcavePolygonShape2D] which is hollow. This makes it more suitable for both detection and physics.
[b]Convex decomposition:[/b] A concave polygon can be split up into several convex polygons. This allows dynamic physics bodies to have complex concave collisions (at a performance cost) and can be achieved by using several [ConvexPolygonShape3D] nodes or by using the [CollisionPolygon2D] node in [code]BUILD_SOLIDS[/code] mode. To generate a collision polygon from a sprite, select the [Sprite2D] node, go to the [b]Sprite2D[/b] menu that appears above the viewport, and choose [b]Create Polygon2D Sibling[/b].
[b]Convex decomposition:[/b] A concave polygon can be split up into several convex polygons. This allows dynamic physics bodies to have complex concave collisions (at a performance cost) and can be achieved by using several [ConvexPolygonShape2D] nodes or by using the [CollisionPolygon2D] node in [code]BUILD_SOLIDS[/code] mode. To generate a collision polygon from a sprite, select the [Sprite2D] node, go to the [b]Sprite2D[/b] menu that appears above the viewport, and choose [b]Create Polygon2D Sibling[/b].
[b]Performance:[/b] [ConvexPolygonShape2D] is faster to check collisions against compared to [ConcavePolygonShape2D], but it is slower than primitive collision shapes such as [CircleShape2D] and [RectangleShape2D]. Its use should generally be limited to medium-sized objects that cannot have their collision accurately represented by primitive shapes.
</description>
<tutorials>

View File

@ -4,9 +4,9 @@
A 3D cylinder shape used for physics collision.
</brief_description>
<description>
A 2D capsule shape, intended for use in physics. Usually used to provide a shape for a [CollisionShape3D].
A 3D cylinder shape, intended for use in physics. Usually used to provide a shape for a [CollisionShape3D].
[b]Note:[/b] There are several known bugs with cylinder collision shapes. Using [CapsuleShape3D] or [BoxShape3D] instead is recommended.
[b]Performance:[/b] [CylinderShape3D] is fast to check collisions against, but it is slower than [CapsuleShape3D], [BoxShape3D], and [CylinderShape3D].
[b]Performance:[/b] [CylinderShape3D] is fast to check collisions against, but it is slower than [CapsuleShape3D], [BoxShape3D], and [SphereShape3D].
</description>
<tutorials>
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>

View File

@ -59,6 +59,7 @@
</member>
<member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="GPUParticles3D.DrawOrder" default="0">
Particle draw order. Uses [enum DrawOrder] values.
[b]Note:[/b] [constant DRAW_ORDER_INDEX] is the only option that supports motion vectors for effects like TAA. It is suggested to use this draw order if the particles are opaque to fix ghosting artifacts.
</member>
<member name="draw_pass_1" type="Mesh" setter="set_draw_pass_mesh" getter="get_draw_pass_mesh">
[Mesh] that is drawn for the first draw pass.

View File

@ -41,6 +41,7 @@
<description>
Returns the response's body length.
[b]Note:[/b] Some Web servers may not send a body length. In this case, the value returned will be [code]-1[/code]. If using chunked transfer encoding, the body length will also be [code]-1[/code].
[b]Note:[/b] This function always returns [code]-1[/code] on the Web platform due to browsers limitations.
</description>
</method>
<method name="get_response_code" qualifiers="const">

View File

@ -343,6 +343,15 @@
[b]Note:[/b] This value can be immediately overwritten by the hardware sensor value on Android and iOS.
</description>
</method>
<method name="should_ignore_device" qualifiers="const">
<return type="bool" />
<param index="0" name="vendor_id" type="int" />
<param index="1" name="product_id" type="int" />
<description>
Queries whether an input device should be ignored or not. Devices can be ignored by setting the environment variable [code]SDL_GAMECONTROLLER_IGNORE_DEVICES[/code]. Read the [url=https://wiki.libsdl.org/SDL2]SDL documentation[/url] for more information.
[b]Note:[/b] Some 3rd party tools can contribute to the list of ignored devices. For example, [i]SteamInput[/i] creates virtual devices from physical devices for remapping purposes. To avoid handling the same input device twice, the original device is added to the ignore list.
</description>
</method>
<method name="start_joy_vibration">
<return type="void" />
<param index="0" name="device" type="int" />

View File

@ -117,6 +117,9 @@
<constant name="BAKE_ERROR_USER_ABORTED" value="8" enum="BakeError">
The user aborted the lightmap baking operation (typically by clicking the [b]Cancel[/b] button in the progress dialog).
</constant>
<constant name="BAKE_ERROR_TEXTURE_SIZE_TOO_SMALL" value="9" enum="BakeError">
Lightmap baking failed as the maximum texture size is too small to fit some of the meshes marked for baking.
</constant>
<constant name="ENVIRONMENT_MODE_DISABLED" value="0" enum="EnvironmentMode">
Ignore environment lighting when baking lightmaps.
</constant>

View File

@ -230,8 +230,8 @@
- [code]type[/code]: Always [constant NavigationPathQueryResult3D.PATH_SEGMENT_TYPE_LINK].
- [code]rid[/code]: The [RID] of the link.
- [code]owner[/code]: The object which manages the link (usually [NavigationLink3D]).
- [code]link_entry_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point the agent is entering.
- [code]link_exit_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point which the agent is exiting.
- [code]link_entry_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink3D], it will contain the global position of the link's point the agent is entering.
- [code]link_exit_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink3D], it will contain the global position of the link's point which the agent is exiting.
</description>
</signal>
<signal name="navigation_finished">

View File

@ -4,7 +4,7 @@
A server interface for low-level 3D navigation access.
</brief_description>
<description>
NavigationServer2D is the server that handles navigation maps, regions and agents. It does not handle A* navigation from [AStar3D].
NavigationServer3D is the server that handles navigation maps, regions and agents. It does not handle A* navigation from [AStar3D].
Maps are made up of regions, which are made of navigation meshes. Together, they define the navigable areas in the 3D world.
[b]Note:[/b] Most [NavigationServer3D] changes take effect after the next physics frame and not immediately. This includes all changes made to maps, regions or agents by navigation-related nodes in the scene tree or made through scripts.
For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [code]edge_connection_margin[/code] to the respective other edge's vertex.

View File

@ -4,7 +4,7 @@
A server interface for low-level 3D physics access.
</brief_description>
<description>
PhysicsServer2D is the server responsible for all 2D physics. It can directly create and manipulate all physics objects:
PhysicsServer3D is the server responsible for all 3D physics. It can directly create and manipulate all physics objects:
- A [i]space[/i] is a self-contained world for a physics simulation. It contains bodies, areas, and joints. Its state can be queried for collision and intersection information, and several parameters of the simulation can be modified.
- A [i]shape[/i] is a geometric shape such as a sphere, a box, a cylinder, or a polygon. It can be used for collision detection by adding it to a body/area, possibly with an extra transformation relative to the body/area's origin. Bodies/areas can have multiple (transformed) shapes added to them, and a single shape can be added to bodies/areas multiple times with different local transformations.
- A [i]body[/i] is a physical object which can be in static, kinematic, or rigid mode. Its state (such as position and velocity) can be queried and updated. A force integration callback can be set to customize the body's physics.

View File

@ -4,7 +4,7 @@
A physics joint that attaches two 3D physics bodies at a single point, allowing them to freely rotate.
</brief_description>
<description>
A physics joint that attaches two 2D physics bodies at a single point, allowing them to freely rotate. For example, a [RigidBody3D] can be attached to a [StaticBody3D] to create a pendulum or a seesaw.
A physics joint that attaches two 3D physics bodies at a single point, allowing them to freely rotate. For example, a [RigidBody3D] can be attached to a [StaticBody3D] to create a pendulum or a seesaw.
</description>
<tutorials>
</tutorials>

View File

@ -1443,6 +1443,7 @@
<description>
Returns the name of the video adapter (e.g. "GeForce GTX 1080/PCIe/SSE2").
[b]Note:[/b] When running a headless or server binary, this function returns an empty string.
[b]Note:[/b] On the web platform, some browsers such as Firefox may report a different, fixed GPU name such as "GeForce GTX 980" (regardless of the user's actual GPU model). This is done to make fingerprinting more difficult.
</description>
</method>
<method name="get_video_adapter_type" qualifiers="const">

View File

@ -50,7 +50,7 @@
Deadzone for touch scrolling. Lower deadzone makes the scrolling more sensitive.
</member>
<member name="scroll_horizontal" type="int" setter="set_h_scroll" getter="get_h_scroll" default="0">
The current horizontal scroll value.
The current horizontal scroll value.
[b]Note:[/b] If you are setting this value in the [method Node._ready] function or earlier, it needs to be wrapped with [method Object.set_deferred], since scroll bar's [member Range.max_value] is not initialized yet.
[codeblock]
func _ready():
@ -78,12 +78,14 @@
<signals>
<signal name="scroll_ended">
<description>
Emitted when scrolling stops.
Emitted when scrolling stops when dragging the scrollable area [i]with a touch event[/i]. This signal is [i]not[/i] emitted when scrolling by dragging the scrollbar, scrolling with the mouse wheel or scrolling with keyboard/gamepad events.
[b]Note:[/b] This signal is only emitted on Android or iOS, or on desktop/web platforms when [member ProjectSettings.input_devices/pointing/emulate_touch_from_mouse] is enabled.
</description>
</signal>
<signal name="scroll_started">
<description>
Emitted when scrolling is started.
Emitted when scrolling starts when dragging the scrollable area w[i]ith a touch event[/i]. This signal is [i]not[/i] emitted when scrolling by dragging the scrollbar, scrolling with the mouse wheel or scrolling with keyboard/gamepad events.
[b]Note:[/b] This signal is only emitted on Android or iOS, or on desktop/web platforms when [member ProjectSettings.input_devices/pointing/emulate_touch_from_mouse] is enabled.
</description>
</signal>
</signals>

View File

@ -4,7 +4,7 @@
A 3D ray shape used for physics collision that tries to separate itself from any collider.
</brief_description>
<description>
A 3D ray shape, intended for use in physics. Usually used to provide a shape for a [CollisionShape2D]. When a [SeparationRayShape3D] collides with an object, it tries to separate itself from it by moving its endpoint to the collision point. It can for example be used for spears falling from the sky.
A 3D ray shape, intended for use in physics. Usually used to provide a shape for a [CollisionShape3D]. When a [SeparationRayShape3D] collides with an object, it tries to separate itself from it by moving its endpoint to the collision point. It can for example be used for spears falling from the sky.
</description>
<tutorials>
</tutorials>

View File

@ -118,7 +118,7 @@
Removes the index array by expanding the vertex array.
</description>
</method>
<method name="generate_lod">
<method name="generate_lod" is_deprecated="true">
<return type="PackedInt32Array" />
<param index="0" name="nd_threshold" type="float" />
<param index="1" name="target_index_count" type="int" default="3" />

View File

@ -339,6 +339,13 @@
Returns item's text base writing direction.
</description>
</method>
<method name="get_text_overrun_behavior" qualifiers="const">
<return type="int" enum="TextServer.OverrunBehavior" />
<param index="0" name="column" type="int" />
<description>
Returns the clipping behavior when the text exceeds the item's bounding rectangle in the given [param column]. By default it is [constant TextServer.OVERRUN_TRIM_ELLIPSIS].
</description>
</method>
<method name="get_tooltip_text" qualifiers="const">
<return type="String" />
<param index="0" name="column" type="int" />
@ -719,6 +726,14 @@
Sets item's text base writing direction.
</description>
</method>
<method name="set_text_overrun_behavior">
<return type="void" />
<param index="0" name="column" type="int" />
<param index="1" name="overrun_behavior" type="int" enum="TextServer.OverrunBehavior" />
<description>
Sets the clipping behavior when the text exceeds the item's bounding rectangle in the given [param column].
</description>
</method>
<method name="set_tooltip_text">
<return type="void" />
<param index="0" name="column" type="int" />

View File

@ -1451,7 +1451,7 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
void RasterizerCanvasGLES3::_add_to_batch(uint32_t &r_index, bool &r_batch_broken) {
state.canvas_instance_batches[state.current_batch_index].instance_count++;
r_index++;
if (r_index >= data.max_instances_per_buffer) {
if (r_index + state.last_item_index >= data.max_instances_per_buffer) {
// Copy over all data needed for rendering right away
// then go back to recording item commands.
glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[state.current_instance_buffer_index]);

View File

@ -2166,7 +2166,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
if (scene_state.current_depth_draw != shader->depth_draw) {
switch (shader->depth_draw) {
case GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE: {
glDepthMask(p_pass_mode == PASS_MODE_COLOR);
glDepthMask((p_pass_mode == PASS_MODE_COLOR && !GLES3::Config::get_singleton()->use_depth_prepass) ||
p_pass_mode == PASS_MODE_DEPTH ||
p_pass_mode == PASS_MODE_SHADOW);
} break;
case GLES3::SceneShaderData::DEPTH_DRAW_ALWAYS: {
glDepthMask(GL_TRUE);

View File

@ -769,7 +769,7 @@ void ShaderGLES3::initialize(const String &p_general_defines, int p_base_texture
print_verbose("Shader '" + name + "' SHA256: " + base_sha256);
}
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units);
glGetInteger64v(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units);
}
void ShaderGLES3::set_shader_cache_dir(const String &p_dir) {

View File

@ -154,7 +154,7 @@ private:
static bool shader_cache_save_debug;
bool shader_cache_dir_valid = false;
GLint max_image_units = 0;
int64_t max_image_units = 0;
enum StageType {
STAGE_TYPE_VERTEX,

View File

@ -53,9 +53,9 @@ Config::Config() {
singleton = this;
{
GLint max_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &max_extensions);
for (int i = 0; i < max_extensions; i++) {
int64_t max_extensions = 0;
glGetInteger64v(GL_NUM_EXTENSIONS, &max_extensions);
for (int64_t i = 0; i < max_extensions; i++) {
const GLubyte *s = glGetStringi(GL_EXTENSIONS, i);
if (!s) {
break;
@ -88,11 +88,11 @@ Config::Config() {
rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc");
#endif
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
glGetInteger64v(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
glGetInteger64v(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units);
glGetInteger64v(GL_MAX_TEXTURE_SIZE, &max_texture_size);
glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
glGetInteger64v(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
support_anisotropic_filter = extensions.has("GL_EXT_texture_filter_anisotropic");
if (support_anisotropic_filter) {

View File

@ -58,14 +58,14 @@ public:
bool use_nearest_mip_filter = false;
bool use_depth_prepass = true;
int max_vertex_texture_image_units = 0;
int max_texture_image_units = 0;
int max_texture_size = 0;
int max_viewport_size[2] = { 0, 0 };
int max_uniform_buffer_size = 0;
int max_renderable_elements = 0;
int max_renderable_lights = 0;
int max_lights_per_object = 0;
int64_t max_vertex_texture_image_units = 0;
int64_t max_texture_image_units = 0;
int64_t max_texture_size = 0;
int64_t max_viewport_size[2] = { 0, 0 };
int64_t max_uniform_buffer_size = 0;
int64_t max_renderable_elements = 0;
int64_t max_renderable_lights = 0;
int64_t max_lights_per_object = 0;
// TODO implement wireframe in OpenGL
// bool generate_wireframes;

View File

@ -1285,13 +1285,17 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
multimesh->data_cache_used_dirty_regions = 0;
}
// If we have either color or custom data, reserve space for both to make data handling logic simpler.
// This way we can always treat them both as a single, compressed uvec4.
int color_and_custom_strides = (p_use_colors || p_use_custom_data) ? 2 : 0;
multimesh->instances = p_instances;
multimesh->xform_format = p_transform_format;
multimesh->uses_colors = p_use_colors;
multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
multimesh->uses_custom_data = p_use_custom_data;
multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 2 : 0);
multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 2 : 0);
multimesh->custom_data_offset_cache = multimesh->color_offset_cache + color_and_custom_strides;
multimesh->stride_cache = multimesh->custom_data_offset_cache + color_and_custom_strides;
multimesh->buffer_set = false;
multimesh->data_cache = Vector<float>();
@ -1685,14 +1689,16 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
// Color and custom need to be packed so copy buffer to data_cache and pack.
_multimesh_make_local(multimesh);
multimesh->data_cache = p_buffer;
float *w = multimesh->data_cache.ptrw();
uint32_t old_stride = multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
old_stride += multimesh->uses_colors ? 4 : 0;
old_stride += multimesh->uses_custom_data ? 4 : 0;
ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)old_stride));
multimesh->data_cache = p_buffer;
float *w = multimesh->data_cache.ptrw();
for (int i = 0; i < multimesh->instances; i++) {
{
float *dataptr = w + i * old_stride;

View File

@ -108,10 +108,7 @@ Error FileAccessUnix::open_internal(const String &p_path, int p_mode_flags) {
last_error = ERR_FILE_CANT_OPEN;
return last_error;
}
// Fix temporary file permissions (defaults to 0600 instead of 0666 & ~umask).
mode_t mask = umask(022);
umask(mask);
fchmod(fd, 0666 & ~mask);
fchmod(fd, 0666);
path = String::utf8(cs.ptr());
f = fdopen(fd, mode_string);

View File

@ -2607,7 +2607,7 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
vkCmdCopyBufferToImage(command_buffer, staging_buffer_blocks[staging_buffer_current].buffer, texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy);
staging_buffer_blocks.write[staging_buffer_current].fill_amount += alloc_size;
staging_buffer_blocks.write[staging_buffer_current].fill_amount = alloc_offset + alloc_size;
}
}
}

View File

@ -1154,15 +1154,6 @@ Ref<Texture2D> EditorData::get_script_icon(const Ref<Script> &p_script) {
return ext_icon;
}
// Look for the base type in the editor theme.
// This is only relevant for built-in classes.
const Control *gui_base = EditorNode::get_singleton()->get_gui_base();
if (gui_base && gui_base->has_theme_icon(base_type, SNAME("EditorIcons"))) {
Ref<Texture2D> theme_icon = gui_base->get_theme_icon(base_type, SNAME("EditorIcons"));
_script_icon_cache[p_script] = theme_icon;
return theme_icon;
}
// If no icon found, cache it as null.
_script_icon_cache[p_script] = Ref<Texture>();
return nullptr;

View File

@ -42,7 +42,7 @@ void EditorLayoutsDialog::_line_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
if (k->is_action_pressed(SNAME("ui_accept"), false, true)) {
if (k->is_action_pressed(SNAME("ui_text_submit"), false, true)) {
if (get_hide_on_ok()) {
hide();
}

View File

@ -1982,6 +1982,9 @@ void EditorNode::_dialog_action(String p_file) {
if (scene_idx != -1) {
_discard_changes();
} else {
// Update the path of the edited scene to ensure later do/undo action history matches.
editor_data.set_scene_path(editor_data.get_edited_scene(), p_file);
}
}
@ -3574,7 +3577,9 @@ void EditorNode::set_current_scene(int p_idx) {
_update_title();
_update_scene_tabs();
call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // Do after everything else is done setting up.
if (tabs_to_close.is_empty()) {
call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // Do after everything else is done setting up.
}
}
void EditorNode::setup_color_picker(ColorPicker *p_picker) {
@ -4234,7 +4239,7 @@ void EditorNode::_pick_main_scene_custom_action(const String &p_custom_action_na
}
}
Ref<Texture2D> EditorNode::_get_class_or_script_icon(const String &p_class, const Ref<Script> &p_script, const String &p_fallback) {
Ref<Texture2D> EditorNode::_get_class_or_script_icon(const String &p_class, const Ref<Script> &p_script, const String &p_fallback, bool p_fallback_script_to_theme) {
ERR_FAIL_COND_V_MSG(p_class.is_empty(), nullptr, "Class name cannot be empty.");
EditorData &ed = EditorNode::get_editor_data();
@ -4244,6 +4249,16 @@ Ref<Texture2D> EditorNode::_get_class_or_script_icon(const String &p_class, cons
if (script_icon.is_valid()) {
return script_icon;
}
if (p_fallback_script_to_theme) {
// Look for the native base type in the editor theme. This is relevant for
// scripts extending other scripts and for built-in classes.
String script_class_name = p_script->get_language()->get_global_class_name(p_script->get_path());
String base_type = ScriptServer::get_global_class_native_base(script_class_name);
if (gui_base && gui_base->has_theme_icon(base_type, SNAME("EditorIcons"))) {
return gui_base->get_theme_icon(base_type, SNAME("EditorIcons"));
}
}
}
// Script was not valid or didn't yield any useful values, try the class name
@ -4296,7 +4311,7 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p
scr = EditorNode::get_editor_data().script_class_load_script(p_class);
}
return _get_class_or_script_icon(p_class, scr, p_fallback);
return _get_class_or_script_icon(p_class, scr, p_fallback, true);
}
bool EditorNode::is_object_of_custom_type(const Object *p_object, const StringName &p_class) {
@ -4950,12 +4965,17 @@ void EditorNode::_load_editor_layout() {
config.instantiate();
Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
if (err != OK) { // No config.
// If config is not found, expand the res:// folder by default.
// If config is not found, expand the res:// folder and favorites by default.
TreeItem *root = FileSystemDock::get_singleton()->get_tree_control()->get_item_with_metadata("res://", 0);
if (root) {
root->set_collapsed(false);
}
TreeItem *favorites = FileSystemDock::get_singleton()->get_tree_control()->get_item_with_metadata("Favorites", 0);
if (favorites) {
favorites->set_collapsed(false);
}
if (overridden_default_layout >= 0) {
_layout_menu_option(overridden_default_layout);
}
@ -7135,7 +7155,7 @@ EditorNode::EditorNode() {
dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
dock_vb->add_child(dock_select);
if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && EDITOR_GET("interface/multi_window/enable")) {
if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && !EDITOR_GET("interface/editor/single_window_mode") && EDITOR_GET("interface/multi_window/enable")) {
dock_float = memnew(Button);
dock_float->set_icon(theme->get_icon("MakeFloating", "EditorIcons"));
dock_float->set_text(TTR("Make Floating"));

View File

@ -687,7 +687,7 @@ private:
void _feature_profile_changed();
bool _is_class_editor_disabled_by_feature_profile(const StringName &p_class);
Ref<Texture2D> _get_class_or_script_icon(const String &p_class, const Ref<Script> &p_script, const String &p_fallback = "Object");
Ref<Texture2D> _get_class_or_script_icon(const String &p_class, const Ref<Script> &p_script, const String &p_fallback = "Object", bool p_fallback_script_to_theme = false);
void _pick_main_scene_custom_action(const String &p_custom_action_name);

View File

@ -243,7 +243,7 @@ EditorPluginSettings::EditorPluginSettings() {
plugin_list->set_column_custom_minimum_width(3, 80 * EDSCALE);
plugin_list->set_column_custom_minimum_width(4, 40 * EDSCALE);
plugin_list->set_hide_root(true);
plugin_list->connect("item_edited", callable_mp(this, &EditorPluginSettings::_plugin_activity_changed));
plugin_list->connect("item_edited", callable_mp(this, &EditorPluginSettings::_plugin_activity_changed), CONNECT_DEFERRED);
VBoxContainer *mc = memnew(VBoxContainer);
mc->add_child(plugin_list);

View File

@ -497,7 +497,7 @@ EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_pla
//initial export plugin callback
for (int i = 0; i < export_plugins.size(); i++) {
export_plugins.write[i]->set_export_preset(p_preset);
if (export_plugins[i]->get_script_instance()) { //script based
if (GDVIRTUAL_IS_OVERRIDDEN_PTR(export_plugins[i], _export_begin)) {
PackedStringArray features_psa;
for (const String &feature : features) {
features_psa.push_back(feature);
@ -512,7 +512,7 @@ EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_pla
EditorExportPlatform::ExportNotifier::~ExportNotifier() {
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
if (export_plugins[i]->get_script_instance()) {
if (GDVIRTUAL_IS_OVERRIDDEN_PTR(export_plugins[i], _export_end)) {
export_plugins.write[i]->_export_end_script();
}
export_plugins.write[i]->_export_end();
@ -1222,7 +1222,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
bool do_export = true;
for (int i = 0; i < export_plugins.size(); i++) {
if (export_plugins[i]->get_script_instance()) { //script based
if (GDVIRTUAL_IS_OVERRIDDEN_PTR(export_plugins[i], _export_file)) {
export_plugins.write[i]->_export_file_script(path, type, features_psa);
} else {
export_plugins.write[i]->_export_file(path, type, features);

View File

@ -1871,7 +1871,6 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_cop
if (!to_move[i].is_file) {
new_path = new_path.path_join(old_path.trim_suffix("/").get_file());
print_line(new_path);
}
if (old_path != new_path) {

View File

@ -417,7 +417,7 @@ void ResourceImporterTexture::_save_editor_meta(const Dictionary &p_metadata, co
Dictionary ResourceImporterTexture::_load_editor_meta(const String &p_path) const {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(f.is_null(), Dictionary(), "Missing required editor-specific import metadata for a texture; please, reimport.");
ERR_FAIL_COND_V_MSG(f.is_null(), Dictionary(), vformat("Missing required editor-specific import metadata for a texture (please reimport it using the 'Import' tab): '%s'", p_path));
return f->get_var();
}

View File

@ -103,6 +103,9 @@ void LightmapGIEditorPlugin::_bake_select_file(const String &p_file) {
case LightmapGI::BAKE_ERROR_FOREIGN_DATA: {
EditorNode::get_singleton()->show_warning(TTR("Lightmap data is not local to the scene."));
} break;
case LightmapGI::BAKE_ERROR_TEXTURE_SIZE_TOO_SMALL: {
EditorNode::get_singleton()->show_warning(TTR("Maximum texture size is too small for the lightmap images."));
} break;
default: {
} break;
}

View File

@ -3104,7 +3104,7 @@ void Node3DEditorViewport::_draw() {
get_theme_icon(SNAME("ViewportSpeed"), SNAME("EditorIcons")),
get_theme_font(SNAME("font"), SNAME("Label")),
get_theme_font_size(SNAME("font_size"), SNAME("Label")),
vformat("%s u/s", String::num(freelook_speed).pad_decimals(precision)),
vformat("%s m/s", String::num(freelook_speed).pad_decimals(precision)),
Color(1.0, 0.95, 0.7));
}
@ -3127,7 +3127,7 @@ void Node3DEditorViewport::_draw() {
get_theme_icon(SNAME("ViewportZoom"), SNAME("EditorIcons")),
get_theme_font(SNAME("font"), SNAME("Label")),
get_theme_font_size(SNAME("font_size"), SNAME("Label")),
vformat("%s u", String::num(cursor.distance).pad_decimals(precision)),
vformat("%s m", String::num(cursor.distance).pad_decimals(precision)),
Color(0.7, 0.95, 1.0));
}
}

View File

@ -1834,7 +1834,7 @@ void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref<InputEvent> &p_
return;
}
if (k->is_action_pressed(SNAME("ui_accept"), false, true)) {
if (k->is_action_pressed(SNAME("ui_text_submit"), false, true)) {
_confirm_edit_theme_item();
edit_theme_item_dialog->hide();
edit_theme_item_dialog->set_input_as_handled();

View File

@ -2156,7 +2156,7 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
Ref<TileSetAtlasSource> atlas_source = atlas_source_proxy->get_edited();
ERR_FAIL_COND(!atlas_source.is_valid());
UndoRedo *internal_undo_redo = undo_redo_man->get_history_for_object(atlas_source.ptr()).undo_redo;
UndoRedo *internal_undo_redo = undo_redo_man->get_history_for_object(atlas_source_proxy).undo_redo;
internal_undo_redo->start_force_keep_in_merge_ends();
PackedVector2Array arr;
@ -2180,7 +2180,7 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
String prefix = vformat("%d:%d/", coords.x, coords.y);
for (PropertyInfo pi : properties) {
if (pi.name.begins_with(prefix)) {
ADD_UNDO(atlas_source.ptr(), pi.name);
ADD_UNDO(atlas_source_proxy, pi.name);
}
}
}

View File

@ -1386,6 +1386,11 @@ void SceneTreeDock::_notification(int p_what) {
filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
PopupMenu *filter_menu = filter->get_menu();
filter_menu->set_item_icon(filter_menu->get_item_idx_from_text(TTR("Filters")), get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
filter_menu->set_item_icon(filter_menu->get_item_index(FILTER_BY_TYPE), get_theme_icon(SNAME("Node"), SNAME("EditorIcons")));
filter_menu->set_item_icon(filter_menu->get_item_index(FILTER_BY_GROUP), get_theme_icon(SNAME("Groups"), SNAME("EditorIcons")));
// These buttons are created on READY, because reasons...
if (button_2d) {
button_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons")));
@ -1738,6 +1743,8 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath>
continue;
}
int tracks_removed = 0;
for (int i = 0; i < anim->get_track_count(); i++) {
NodePath track_np = anim->track_get_path(i);
Node *n = root->get_node_or_null(track_np);
@ -1755,14 +1762,8 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath>
if (found_path->value.is_empty()) {
//will be erased
int idx = 0;
HashSet<int>::Iterator EI = ran.begin();
ERR_FAIL_COND(!EI); //bug
while (*EI != i) {
idx++;
++EI;
ERR_FAIL_COND(!EI); //another bug
}
int idx = i - tracks_removed;
tracks_removed++;
undo_redo->add_do_method(anim.ptr(), "remove_track", idx);
undo_redo->add_undo_method(anim.ptr(), "add_track", anim->track_get_type(i), idx);
@ -2053,6 +2054,10 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
return;
}
if (p_script->is_built_in()) {
p_script->set_path(edited_scene->get_scene_file_path() + "::");
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, selected.front()->get());
for (Node *E : selected) {
@ -3030,10 +3035,6 @@ void SceneTreeDock::_update_tree_menu() {
tree_menu->add_submenu_item(TTR("All Scene Sub-Resources"), "AllResources");
}
void SceneTreeDock::_update_filter_menu() {
_append_filter_options_to(filter->get_menu());
}
void SceneTreeDock::_filter_changed(const String &p_filter) {
scene_tree->set_filter(p_filter);
@ -3088,14 +3089,11 @@ void SceneTreeDock::_append_filter_options_to(PopupMenu *p_menu, bool p_include_
p_menu->add_separator();
p_menu->set_item_text(-1, TTR("Filters"));
p_menu->set_item_icon(-1, get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
p_menu->set_item_indent(-1, -2);
}
p_menu->add_item(TTR("Filter by Type"), FILTER_BY_TYPE);
p_menu->add_item(TTR("Filter by Group"), FILTER_BY_GROUP);
p_menu->set_item_icon(p_menu->get_item_index(FILTER_BY_TYPE), get_theme_icon(SNAME("Node"), SNAME("EditorIcons")));
p_menu->set_item_icon(p_menu->get_item_index(FILTER_BY_GROUP), get_theme_icon(SNAME("Groups"), SNAME("EditorIcons")));
p_menu->set_item_tooltip(p_menu->get_item_index(FILTER_BY_TYPE), TTR("Selects all Nodes of the given type."));
p_menu->set_item_tooltip(p_menu->get_item_index(FILTER_BY_GROUP), TTR("Selects all Nodes belonging to the given group.\nIf empty, selects any Node belonging to any group."));
}
@ -3716,8 +3714,8 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
filter->add_theme_constant_override("minimum_character_width", 0);
filter->connect("text_changed", callable_mp(this, &SceneTreeDock::_filter_changed));
filter->connect("gui_input", callable_mp(this, &SceneTreeDock::_filter_gui_input));
filter->get_menu()->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_update_filter_menu));
filter->get_menu()->connect("id_pressed", callable_mp(this, &SceneTreeDock::_filter_option_selected));
_append_filter_options_to(filter->get_menu());
filter_quick_menu = memnew(PopupMenu);
filter_quick_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_filter_option_selected));

View File

@ -249,7 +249,6 @@ class SceneTreeDock : public VBoxContainer {
void _tree_rmb(const Vector2 &p_menu_pos);
void _update_tree_menu();
void _update_filter_menu();
void _filter_changed(const String &p_filter);
void _filter_gui_input(const Ref<InputEvent> &p_event);

View File

@ -313,7 +313,7 @@ void WindowWrapper::set_margins_enabled(bool p_enabled) {
}
WindowWrapper::WindowWrapper() {
if (SceneTree::get_singleton()->get_root()->is_embedding_subwindows() || !EDITOR_GET("interface/multi_window/enable")) {
if (SceneTree::get_singleton()->get_root()->is_embedding_subwindows() || EDITOR_GET("interface/editor/single_window_mode") || !EDITOR_GET("interface/multi_window/enable")) {
return;
}

View File

@ -776,8 +776,18 @@ def add_to_vs_project(env, sources):
env.vs_srcs += [basename + ".cpp"]
def generate_vs_project(env, num_jobs, project_name="godot"):
def generate_vs_project(env, original_args, project_name="godot"):
batch_file = find_visual_c_batch_file(env)
filtered_args = original_args.copy()
# Ignore the "vsproj" option to not regenerate the VS project on every build
filtered_args.pop("vsproj", None)
# The "platform" option is ignored because only the Windows platform is currently supported for VS projects
filtered_args.pop("platform", None)
# The "target" option is ignored due to the way how targets configuration is performed for VS projects (there is a separate project configuration for each target)
filtered_args.pop("target", None)
# The "progress" option is ignored as the current compilation progress indication doesn't work in VS
filtered_args.pop("progress", None)
if batch_file:
class ModuleConfigs(Mapping):
@ -853,23 +863,10 @@ def generate_vs_project(env, num_jobs, project_name="godot"):
"platform=windows",
f"target={configuration_getter}",
"progress=no",
"-j%s" % num_jobs,
]
if env["dev_build"]:
common_build_postfix.append("dev_build=yes")
if env["dev_mode"]:
common_build_postfix.append("dev_mode=yes")
elif env["tests"]:
common_build_postfix.append("tests=yes")
if env["custom_modules"]:
common_build_postfix.append("custom_modules=%s" % env["custom_modules"])
if env["precision"] == "double":
common_build_postfix.append("precision=double")
for arg, value in filtered_args.items():
common_build_postfix.append(f"{arg}={value}")
result = " ^& ".join(common_build_prefix + [" ".join([commands] + common_build_postfix)])
return result

View File

@ -1,5 +1,5 @@
#!/bin/bash
set -uo pipefail
set -o pipefail
if [ ! -f "version.py" ]; then
echo "Warning: This script is intended to be run from the root of the Godot repository."
@ -18,7 +18,7 @@ make_annotation()
local body=$2
local type=$3
local file=$4
if [ ! -v GITHUB_OUTPUT ]; then
if [[ "$GITHUB_OUTPUT" == "" ]]; then
echo "$title"
echo "$body"
else
@ -43,8 +43,8 @@ while read -r file; do
awk '/^Validate extension JSON:/' - < "$file" | sort > "$allowed_errors"
# Differences between the expected and actual errors
new_validation_error="$(comm "$validation_output" "$allowed_errors" -23)"
obsolete_validation_error="$(comm "$validation_output" "$allowed_errors" -13)"
new_validation_error="$(comm -23 "$validation_output" "$allowed_errors")"
obsolete_validation_error="$(comm -13 "$validation_output" "$allowed_errors")"
if [ -n "$obsolete_validation_error" ]; then
make_annotation "The following validation errors no longer occur (compared to $reference_tag):" "$obsolete_validation_error" warning "$file"

View File

@ -109,6 +109,15 @@ env_oidn.AppendUnique(CPPDEFINES=["NDEBUG"]) # No assert() even in debug builds
env_thirdparty = env_oidn.Clone()
env_thirdparty.disable_warnings()
if env["disable_exceptions"]:
# OIDN hard-requires exceptions, so we re-enable them here.
if env.msvc and ("_HAS_EXCEPTIONS", 0) in env_thirdparty["CPPDEFINES"]:
env_thirdparty["CPPDEFINES"].remove(("_HAS_EXCEPTIONS", 0))
env_thirdparty.AppendUnique(CCFLAGS=["/EHsc"])
elif not env.msvc and "-fno-exceptions" in env_thirdparty["CCFLAGS"]:
env_thirdparty["CCFLAGS"].remove("-fno-exceptions")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
env.modules_sources += thirdparty_obj

View File

@ -343,23 +343,22 @@ Error ENetMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size
int packet_flags = 0;
int channel = SYSCH_RELIABLE;
int tr_channel = get_transfer_channel();
switch (get_transfer_mode()) {
case TRANSFER_MODE_UNRELIABLE: {
packet_flags = ENET_PACKET_FLAG_UNSEQUENCED | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
case TRANSFER_MODE_UNRELIABLE_ORDERED: {
packet_flags = ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
case TRANSFER_MODE_RELIABLE: {
packet_flags = ENET_PACKET_FLAG_RELIABLE;
channel = SYSCH_RELIABLE;
} break;
}
if (tr_channel > 0) {
channel = SYSCH_MAX + tr_channel - 1;
} else {
switch (get_transfer_mode()) {
case TRANSFER_MODE_UNRELIABLE: {
packet_flags = ENET_PACKET_FLAG_UNSEQUENCED | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
case TRANSFER_MODE_UNRELIABLE_ORDERED: {
packet_flags = ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT;
channel = SYSCH_UNRELIABLE;
} break;
case TRANSFER_MODE_RELIABLE: {
packet_flags = ENET_PACKET_FLAG_RELIABLE;
channel = SYSCH_RELIABLE;
} break;
}
}
#ifdef DEBUG_ENABLED

View File

@ -2700,6 +2700,11 @@ Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const Str
Error err;
Ref<GDScript> scr = GDScriptCache::get_full_script(p_path, err, "", p_cache_mode == CACHE_MODE_IGNORE);
if (err && scr.is_valid()) {
// If !scr.is_valid(), the error was likely from scr->load_source_code(), which already generates an error.
ERR_PRINT_ED(vformat(R"(Failed to load script "%s" with error "%s".)", p_path, error_names[err]));
}
if (r_error) {
// Don't fail loading because of parsing error.
*r_error = scr.is_valid() ? OK : err;

View File

@ -2705,20 +2705,21 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
case GDScriptParser::ClassNode::Member::GROUP: {
const GDScriptParser::AnnotationNode *annotation = member.annotation;
StringName name = annotation->export_info.name;
// Avoid name conflict. See GH-78252.
StringName name = vformat("@group_%d_%s", p_script->members.size(), annotation->export_info.name);
// This is not a normal member, but we need this to keep indices in order.
GDScript::MemberInfo minfo;
minfo.index = p_script->member_indices.size();
PropertyInfo prop_info;
prop_info.name = name;
prop_info.name = annotation->export_info.name;
prop_info.usage = annotation->export_info.usage;
prop_info.hint_string = annotation->export_info.hint_string;
p_script->member_info[name] = prop_info;
p_script->member_indices[name] = minfo;
p_script->members.insert(name);
p_script->members.insert(Variant());
} break;
default:

View File

@ -2444,7 +2444,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(Expression
complete_extents(operation);
if (operation->right_operand == nullptr) {
push_error(vformat(R"(Expected expression after "%s" operator.")", op.get_name()));
push_error(vformat(R"(Expected expression after "%s" operator.)", op.get_name()));
}
// TODO: Also for unary, ternary, and assignment.

View File

@ -753,7 +753,9 @@ public:
members.push_back(Member(p_enum_value));
}
void add_member_group(AnnotationNode *p_annotation_node) {
members_indices[p_annotation_node->export_info.name] = members.size();
// Avoid name conflict. See GH-78252.
StringName name = vformat("@group_%d_%s", members.size(), p_annotation_node->export_info.name);
members_indices[name] = members.size();
members.push_back(Member(p_annotation_node));
}

View File

@ -812,7 +812,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
api["name"] = m.signal->identifier->name;
Array pars;
for (int j = 0; j < m.signal->parameters.size(); j++) {
pars.append(String(m.signal->parameters[i]->identifier->name));
pars.append(String(m.signal->parameters[j]->identifier->name));
}
api["arguments"] = pars;
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.signal->start_line))) {

View File

@ -0,0 +1,17 @@
extends RefCounted # TODO: Fix standalone annotations parsing.
# GH-73843
@export_group("Resource")
# GH-78252
@export var prop_1: int
@export_category("prop_1")
@export var prop_2: int
func test():
var resource := Resource.new()
prints("Not shadowed:", resource.get_class())
for property in get_property_list():
if property.name in ["prop_1", "prop_2"]:
print(property)

View File

@ -0,0 +1,5 @@
GDTEST_OK
Not shadowed: Resource
{ "name": "prop_1", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
{ "name": "prop_1", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 128 }
{ "name": "prop_2", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }

View File

@ -3385,10 +3385,11 @@ Ref<Texture2D> GLTFDocument::_get_texture(Ref<GLTFState> p_state, const GLTFText
const GLTFImageIndex image = p_state->textures[p_texture]->get_src_image();
ERR_FAIL_INDEX_V(image, p_state->images.size(), Ref<Texture2D>());
if (GLTFState::GLTFHandleBinary(p_state->handle_binary_image) == GLTFState::GLTFHandleBinary::HANDLE_BINARY_EMBED_AS_BASISU) {
ERR_FAIL_INDEX_V(image, p_state->source_images.size(), Ref<Texture2D>());
Ref<PortableCompressedTexture2D> portable_texture;
portable_texture.instantiate();
portable_texture->set_keep_compressed_buffer(true);
Ref<Image> new_img = p_state->source_images[p_texture]->duplicate();
Ref<Image> new_img = p_state->source_images[image]->duplicate();
ERR_FAIL_COND_V(new_img.is_null(), Ref<Texture2D>());
new_img->generate_mipmaps();
if (p_texture_types) {

View File

@ -70,9 +70,9 @@ static void _editor_init() {
if (blend_enabled) {
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.");
WARN_PRINT(TTR("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->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.");
WARN_PRINT(TTR("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();

View File

@ -589,8 +589,12 @@ void LightmapperRD::_raster_geometry(RenderingDevice *rd, Size2i atlas_size, int
raster_push_constant.grid_size[0] = grid_size;
raster_push_constant.grid_size[1] = grid_size;
raster_push_constant.grid_size[2] = grid_size;
raster_push_constant.uv_offset[0] = 0;
raster_push_constant.uv_offset[1] = 0;
// Half pixel offset is required so the rasterizer doesn't output face edges directly aligned into pixels.
// This fixes artifacts where the pixel would be traced from the edge of a face, causing half the rays to
// be outside of the boundaries of the geometry. See <https://github.com/godotengine/godot/issues/69126>.
raster_push_constant.uv_offset[0] = -0.5f / float(atlas_size.x);
raster_push_constant.uv_offset[1] = -0.5f / float(atlas_size.y);
RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
//draw opaque
@ -1579,8 +1583,8 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
{
seams_push_constant.base_index = seam_offset;
rd->draw_list_bind_render_pipeline(draw_list, blendseams_line_raster_pipeline);
seams_push_constant.uv_offset[0] = uv_offsets[0].x / float(atlas_size.width);
seams_push_constant.uv_offset[1] = uv_offsets[0].y / float(atlas_size.height);
seams_push_constant.uv_offset[0] = (uv_offsets[0].x - 0.5f) / float(atlas_size.width);
seams_push_constant.uv_offset[1] = (uv_offsets[0].y - 0.5f) / float(atlas_size.height);
seams_push_constant.blend = uv_offsets[0].z;
rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant));
@ -1603,8 +1607,8 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
for (int j = 1; j < uv_offset_count; j++) {
seams_push_constant.base_index = seam_offset;
seams_push_constant.uv_offset[0] = uv_offsets[j].x / float(atlas_size.width);
seams_push_constant.uv_offset[1] = uv_offsets[j].y / float(atlas_size.height);
seams_push_constant.uv_offset[0] = (uv_offsets[j].x - 0.5f) / float(atlas_size.width);
seams_push_constant.uv_offset[1] = (uv_offsets[j].y - 0.5f) / float(atlas_size.height);
seams_push_constant.blend = uv_offsets[0].z;
rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant));

View File

@ -320,7 +320,12 @@ bool get_dotnet_root_from_env(String &r_dotnet_root) {
bool godotsharp::hostfxr_resolver::try_get_path_from_dotnet_root(const String &p_dotnet_root, String &r_fxr_path) {
String fxr_dir = path::join(p_dotnet_root, "host", "fxr");
ERR_FAIL_COND_V_MSG(!DirAccess::exists(fxr_dir), false, "The host fxr folder does not exist: " + fxr_dir);
if (!DirAccess::exists(fxr_dir)) {
if (OS::get_singleton()->is_stdout_verbose()) {
ERR_PRINT("The host fxr folder does not exist: " + fxr_dir + ".");
}
return false;
}
return get_latest_fxr(fxr_dir, r_fxr_path);
}

View File

@ -52,7 +52,7 @@ namespace Godot.Collections
/// </summary>
/// <param name="array">The objects to put in the new array.</param>
/// <returns>A new Godot Array.</returns>
public Array(Variant[] array) : this()
public Array(Variant[] array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@ -68,7 +68,7 @@ namespace Godot.Collections
this[i] = array[i];
}
public Array(Span<StringName> array) : this()
public Array(Span<StringName> array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@ -84,7 +84,7 @@ namespace Godot.Collections
this[i] = array[i];
}
public Array(Span<NodePath> array) : this()
public Array(Span<NodePath> array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@ -100,7 +100,7 @@ namespace Godot.Collections
this[i] = array[i];
}
public Array(Span<Rid> array) : this()
public Array(Span<Rid> array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@ -121,7 +121,7 @@ namespace Godot.Collections
// fine as long as the array is not mutated. However, Span does this type checking at
// instantiation, so it's not possible to use it even when not mutating anything.
// ReSharper disable once RedundantNameQualifier
public Array(ReadOnlySpan<GodotObject> array) : this()
public Array(ReadOnlySpan<GodotObject> array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@ -1057,7 +1057,7 @@ namespace Godot.Collections
/// </summary>
/// <param name="array">The items to put in the new array.</param>
/// <returns>A new Godot Array.</returns>
public Array(T[] array) : this()
public Array(T[] array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));

View File

@ -1043,7 +1043,8 @@ void NavMap::sync() {
}
// Update the update ID.
map_update_id = (map_update_id + 1) % 9999999;
// Some code treats 0 as a failure case, so we avoid returning 0.
map_update_id = map_update_id % 9999999 + 1;
}
// Do we have modified obstacle positions?

View File

@ -112,6 +112,7 @@ void NoiseTexture3D::_set_texture_data(const TypedArray<Image> &p_data) {
} else {
texture = RS::get_singleton()->texture_3d_create(data[0]->get_format(), data[0]->get_width(), data[0]->get_height(), data.size(), false, data);
}
format = data[0]->get_format();
}
emit_changed();
}
@ -348,6 +349,5 @@ Vector<Ref<Image>> NoiseTexture3D::get_data() const {
}
Image::Format NoiseTexture3D::get_format() const {
ERR_FAIL_COND_V(!texture.is_valid(), Image::FORMAT_L8);
return RS::get_singleton()->texture_3d_get(texture)[0]->get_format();
return format;
}

View File

@ -60,6 +60,8 @@ private:
Ref<Gradient> color_ramp;
Ref<Noise> noise;
Image::Format format = Image::FORMAT_L8;
void _thread_done(const TypedArray<Image> &p_data);
static void _thread_function(void *p_ud);

View File

@ -5,22 +5,13 @@ Import("env_modules")
env_openxr = env_modules.Clone()
#################################################
# Add in our Khronos OpenXR loader
# Thirdparty source files
thirdparty_obj = []
thirdparty_dir = "#thirdparty/openxr"
env_openxr.Prepend(
CPPPATH=[
thirdparty_dir,
thirdparty_dir + "/include",
thirdparty_dir + "/src",
thirdparty_dir + "/src/common",
thirdparty_dir + "/src/external/jsoncpp/include",
]
)
# Khronos OpenXR loader
# Needs even for build against shared library, at least the defines used in public headers.
if env["platform"] == "android":
# may need to set OPENXR_ANDROID_VERSION_SUFFIX
env_openxr.AppendUnique(CPPDEFINES=["XR_OS_ANDROID", "XR_USE_PLATFORM_ANDROID"])
@ -41,43 +32,58 @@ elif env["platform"] == "windows":
# may need to check and set:
# - XR_USE_TIMESPEC
env_thirdparty = env_openxr.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.AppendUnique(CPPDEFINES=["DISABLE_STD_FILESYSTEM"])
if env["builtin_openxr"]:
thirdparty_dir = "#thirdparty/openxr"
if "-fno-exceptions" in env_thirdparty["CXXFLAGS"]:
env_thirdparty["CXXFLAGS"].remove("-fno-exceptions")
env_thirdparty.Append(CPPPATH=[thirdparty_dir + "/src/loader"])
env_openxr.Prepend(
CPPPATH=[
thirdparty_dir,
thirdparty_dir + "/include",
thirdparty_dir + "/src",
thirdparty_dir + "/src/common",
thirdparty_dir + "/src/external/jsoncpp/include",
]
)
# add in external jsoncpp dependency
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/jsoncpp/src/lib_json/json_reader.cpp")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/jsoncpp/src/lib_json/json_value.cpp")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/jsoncpp/src/lib_json/json_writer.cpp")
env_thirdparty = env_openxr.Clone()
env_thirdparty.disable_warnings()
# add in load
if env["platform"] != "android":
# On Android the openxr_loader is provided by separate plugins for each device
# Build the engine using object files
khrloader_obj = []
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/xr_generated_dispatch_table.c")
env_thirdparty.AppendUnique(CPPDEFINES=["DISABLE_STD_FILESYSTEM"])
if env["disable_exceptions"]:
env_thirdparty.AppendUnique(CPPDEFINES=["XRLOADER_DISABLE_EXCEPTION_HANDLING", ("JSON_USE_EXCEPTION", 0)])
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/filesystem_utils.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/object_info.cpp")
env_thirdparty.Append(CPPPATH=[thirdparty_dir + "/src/loader"])
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/api_layer_interface.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_core.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_instance.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger_recorders.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/manifest_file.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/runtime_interface.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/xr_generated_loader.cpp")
env.modules_sources += khrloader_obj
# add in external jsoncpp dependency
thirdparty_jsoncpp_dir = thirdparty_dir + "/src/external/jsoncpp/src/lib_json/"
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_jsoncpp_dir + "json_reader.cpp")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_jsoncpp_dir + "json_value.cpp")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_jsoncpp_dir + "json_writer.cpp")
env.modules_sources += thirdparty_obj
# add in load
if env["platform"] != "android":
# On Android the openxr_loader is provided by separate plugins for each device
# Build the engine using object files
khrloader_obj = []
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/xr_generated_dispatch_table.c")
#################################################
# And include our module source
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/filesystem_utils.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/object_info.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/api_layer_interface.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_core.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_instance.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger_recorders.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/manifest_file.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/runtime_interface.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/xr_generated_loader.cpp")
env.modules_sources += khrloader_obj
env.modules_sources += thirdparty_obj
# Godot source files
module_obj = []

View File

@ -547,7 +547,7 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p
for (int i = 0; i < interaction_profiles.size(); i++) {
Ref<OpenXRInteractionProfile> ip = interaction_profiles[i];
const OpenXRInteractionProfileMetaData::InteractionProfile *profile = OpenXRInteractionProfileMetaData::get_singleton()->get_profile(ip->get_interaction_profile_path());
const OpenXRInteractionProfileMetadata::InteractionProfile *profile = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(ip->get_interaction_profile_path());
if (profile != nullptr) {
for (int j = 0; j < ip->get_binding_count(); j++) {
@ -556,7 +556,7 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p
PackedStringArray paths = binding->get_paths();
for (int k = 0; k < paths.size(); k++) {
const OpenXRInteractionProfileMetaData::IOPath *io_path = profile->get_io_path(paths[k]);
const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(paths[k]);
if (io_path != nullptr) {
String top_path = io_path->top_level_path;

View File

@ -32,7 +32,7 @@
#define OPENXR_INTERACTION_PROFILE_H
#include "openxr_action.h"
#include "openxr_interaction_profile_meta_data.h"
#include "openxr_interaction_profile_metadata.h"
#include "core/io/resource.h"

View File

@ -1,5 +1,5 @@
/**************************************************************************/
/* openxr_interaction_profile_meta_data.cpp */
/* openxr_interaction_profile_metadata.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,30 +28,30 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "openxr_interaction_profile_meta_data.h"
#include "openxr_interaction_profile_metadata.h"
#include "../openxr_api.h"
OpenXRInteractionProfileMetaData *OpenXRInteractionProfileMetaData::singleton = nullptr;
OpenXRInteractionProfileMetadata *OpenXRInteractionProfileMetadata::singleton = nullptr;
OpenXRInteractionProfileMetaData::OpenXRInteractionProfileMetaData() {
OpenXRInteractionProfileMetadata::OpenXRInteractionProfileMetadata() {
singleton = this;
_register_core_metadata();
OpenXRAPI::register_extension_metadata();
}
OpenXRInteractionProfileMetaData::~OpenXRInteractionProfileMetaData() {
OpenXRInteractionProfileMetadata::~OpenXRInteractionProfileMetadata() {
singleton = nullptr;
}
void OpenXRInteractionProfileMetaData::_bind_methods() {
ClassDB::bind_method(D_METHOD("register_top_level_path", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetaData::register_top_level_path);
ClassDB::bind_method(D_METHOD("register_interaction_profile", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetaData::register_interaction_profile);
ClassDB::bind_method(D_METHOD("register_io_path", "interaction_profile", "display_name", "toplevel_path", "openxr_path", "openxr_extension_name", "action_type"), &OpenXRInteractionProfileMetaData::register_io_path);
void OpenXRInteractionProfileMetadata::_bind_methods() {
ClassDB::bind_method(D_METHOD("register_top_level_path", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetadata::register_top_level_path);
ClassDB::bind_method(D_METHOD("register_interaction_profile", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetadata::register_interaction_profile);
ClassDB::bind_method(D_METHOD("register_io_path", "interaction_profile", "display_name", "toplevel_path", "openxr_path", "openxr_extension_name", "action_type"), &OpenXRInteractionProfileMetadata::register_io_path);
}
void OpenXRInteractionProfileMetaData::register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) {
void OpenXRInteractionProfileMetadata::register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) {
ERR_FAIL_COND_MSG(has_top_level_path(p_openxr_path), p_openxr_path + " had already been registered");
TopLevelPath new_toplevel_path = {
@ -63,7 +63,7 @@ void OpenXRInteractionProfileMetaData::register_top_level_path(const String &p_d
top_level_paths.push_back(new_toplevel_path);
}
void OpenXRInteractionProfileMetaData::register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) {
void OpenXRInteractionProfileMetadata::register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) {
ERR_FAIL_COND_MSG(has_interaction_profile(p_openxr_path), p_openxr_path + " has already been registered");
InteractionProfile new_profile;
@ -74,7 +74,7 @@ void OpenXRInteractionProfileMetaData::register_interaction_profile(const String
interaction_profiles.push_back(new_profile);
}
void OpenXRInteractionProfileMetaData::register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_name, OpenXRAction::ActionType p_action_type) {
void OpenXRInteractionProfileMetadata::register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_name, OpenXRAction::ActionType p_action_type) {
ERR_FAIL_COND_MSG(!has_interaction_profile(p_interaction_profile), "Unknown interaction profile " + p_interaction_profile);
ERR_FAIL_COND_MSG(!has_top_level_path(p_toplevel_path), "Unknown top level path " + p_toplevel_path);
@ -95,7 +95,7 @@ void OpenXRInteractionProfileMetaData::register_io_path(const String &p_interact
}
}
bool OpenXRInteractionProfileMetaData::has_top_level_path(const String p_openxr_path) const {
bool OpenXRInteractionProfileMetadata::has_top_level_path(const String p_openxr_path) const {
for (int i = 0; i < top_level_paths.size(); i++) {
if (top_level_paths[i].openxr_path == p_openxr_path) {
return true;
@ -105,7 +105,7 @@ bool OpenXRInteractionProfileMetaData::has_top_level_path(const String p_openxr_
return false;
}
String OpenXRInteractionProfileMetaData::get_top_level_name(const String p_openxr_path) const {
String OpenXRInteractionProfileMetadata::get_top_level_name(const String p_openxr_path) const {
for (int i = 0; i < top_level_paths.size(); i++) {
if (top_level_paths[i].openxr_path == p_openxr_path) {
return top_level_paths[i].display_name;
@ -115,7 +115,7 @@ String OpenXRInteractionProfileMetaData::get_top_level_name(const String p_openx
return String();
}
String OpenXRInteractionProfileMetaData::get_top_level_extension(const String p_openxr_path) const {
String OpenXRInteractionProfileMetadata::get_top_level_extension(const String p_openxr_path) const {
for (int i = 0; i < top_level_paths.size(); i++) {
if (top_level_paths[i].openxr_path == p_openxr_path) {
return top_level_paths[i].openxr_extension_name;
@ -125,7 +125,7 @@ String OpenXRInteractionProfileMetaData::get_top_level_extension(const String p_
return XR_PATH_UNSUPPORTED_NAME;
}
bool OpenXRInteractionProfileMetaData::has_interaction_profile(const String p_openxr_path) const {
bool OpenXRInteractionProfileMetadata::has_interaction_profile(const String p_openxr_path) const {
for (int i = 0; i < interaction_profiles.size(); i++) {
if (interaction_profiles[i].openxr_path == p_openxr_path) {
return true;
@ -135,7 +135,7 @@ bool OpenXRInteractionProfileMetaData::has_interaction_profile(const String p_op
return false;
}
String OpenXRInteractionProfileMetaData::get_interaction_profile_extension(const String p_openxr_path) const {
String OpenXRInteractionProfileMetadata::get_interaction_profile_extension(const String p_openxr_path) const {
for (int i = 0; i < interaction_profiles.size(); i++) {
if (interaction_profiles[i].openxr_path == p_openxr_path) {
return interaction_profiles[i].openxr_extension_name;
@ -145,7 +145,7 @@ String OpenXRInteractionProfileMetaData::get_interaction_profile_extension(const
return XR_PATH_UNSUPPORTED_NAME;
}
const OpenXRInteractionProfileMetaData::InteractionProfile *OpenXRInteractionProfileMetaData::get_profile(const String p_openxr_path) const {
const OpenXRInteractionProfileMetadata::InteractionProfile *OpenXRInteractionProfileMetadata::get_profile(const String p_openxr_path) const {
for (int i = 0; i < interaction_profiles.size(); i++) {
if (interaction_profiles[i].openxr_path == p_openxr_path) {
return &interaction_profiles[i];
@ -155,7 +155,7 @@ const OpenXRInteractionProfileMetaData::InteractionProfile *OpenXRInteractionPro
return nullptr;
}
bool OpenXRInteractionProfileMetaData::InteractionProfile::has_io_path(const String p_io_path) const {
bool OpenXRInteractionProfileMetadata::InteractionProfile::has_io_path(const String p_io_path) const {
for (int i = 0; i < io_paths.size(); i++) {
if (io_paths[i].openxr_path == p_io_path) {
return true;
@ -165,7 +165,7 @@ bool OpenXRInteractionProfileMetaData::InteractionProfile::has_io_path(const Str
return false;
}
const OpenXRInteractionProfileMetaData::IOPath *OpenXRInteractionProfileMetaData::InteractionProfile::get_io_path(const String p_io_path) const {
const OpenXRInteractionProfileMetadata::IOPath *OpenXRInteractionProfileMetadata::InteractionProfile::get_io_path(const String p_io_path) const {
for (int i = 0; i < io_paths.size(); i++) {
if (io_paths[i].openxr_path == p_io_path) {
return &io_paths[i];
@ -175,8 +175,8 @@ const OpenXRInteractionProfileMetaData::IOPath *OpenXRInteractionProfileMetaData
return nullptr;
}
const OpenXRInteractionProfileMetaData::IOPath *OpenXRInteractionProfileMetaData::get_io_path(const String p_interaction_profile, const String p_io_path) const {
const OpenXRInteractionProfileMetaData::InteractionProfile *profile = get_profile(p_interaction_profile);
const OpenXRInteractionProfileMetadata::IOPath *OpenXRInteractionProfileMetadata::get_io_path(const String p_interaction_profile, const String p_io_path) const {
const OpenXRInteractionProfileMetadata::InteractionProfile *profile = get_profile(p_interaction_profile);
if (profile != nullptr) {
return profile->get_io_path(p_io_path);
}
@ -184,7 +184,7 @@ const OpenXRInteractionProfileMetaData::IOPath *OpenXRInteractionProfileMetaData
return nullptr;
}
PackedStringArray OpenXRInteractionProfileMetaData::get_interaction_profile_paths() const {
PackedStringArray OpenXRInteractionProfileMetadata::get_interaction_profile_paths() const {
PackedStringArray arr;
for (int i = 0; i < interaction_profiles.size(); i++) {
@ -194,7 +194,7 @@ PackedStringArray OpenXRInteractionProfileMetaData::get_interaction_profile_path
return arr;
}
void OpenXRInteractionProfileMetaData::_register_core_metadata() {
void OpenXRInteractionProfileMetadata::_register_core_metadata() {
// Note, currently we add definitions that belong in extensions.
// Extensions are registered when our OpenXRAPI is instantiated
// however this does not happen in the editor.

View File

@ -1,5 +1,5 @@
/**************************************************************************/
/* openxr_interaction_profile_meta_data.h */
/* openxr_interaction_profile_metadata.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef OPENXR_INTERACTION_PROFILE_META_DATA_H
#define OPENXR_INTERACTION_PROFILE_META_DATA_H
#ifndef OPENXR_INTERACTION_PROFILE_METADATA_H
#define OPENXR_INTERACTION_PROFILE_METADATA_H
///////////////////////////////////////////////////////////////////////////
// Stores available interaction profile meta data
// Stores available interaction profile metadata
//
// OpenXR defines and hardcodes all the supported input devices and their
// paths as part of the OpenXR spec. When support for new devices is
@ -57,7 +57,9 @@
#define XR_PATH_UNSUPPORTED_NAME "unsupported"
class OpenXRInteractionProfileMetaData : public Object {
class OpenXRInteractionProfileMetadata : public Object {
GDCLASS(OpenXRInteractionProfileMetadata, Object);
public:
struct TopLevelPath {
String display_name; // User friendly display name (i.e. Left controller)
@ -84,7 +86,7 @@ public:
};
private:
static OpenXRInteractionProfileMetaData *singleton;
static OpenXRInteractionProfileMetadata *singleton;
Vector<TopLevelPath> top_level_paths;
Vector<InteractionProfile> interaction_profiles;
@ -95,10 +97,10 @@ protected:
static void _bind_methods();
public:
static OpenXRInteractionProfileMetaData *get_singleton() { return singleton; }
static OpenXRInteractionProfileMetadata *get_singleton() { return singleton; }
OpenXRInteractionProfileMetaData();
~OpenXRInteractionProfileMetaData();
OpenXRInteractionProfileMetadata();
~OpenXRInteractionProfileMetadata();
void register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name);
bool has_top_level_path(const String p_openxr_path) const;
@ -115,4 +117,4 @@ public:
const IOPath *get_io_path(const String p_interaction_profile, const String p_io_path) const;
};
#endif // OPENXR_INTERACTION_PROFILE_META_DATA_H
#endif // OPENXR_INTERACTION_PROFILE_METADATA_H

View File

@ -16,7 +16,10 @@ def get_doc_classes():
"OpenXRAction",
"OpenXRActionSet",
"OpenXRActionMap",
"OpenXRAPIExtension",
"OpenXRExtensionWrapperExtension",
"OpenXRInteractionProfile",
"OpenXRInteractionProfileMetadata",
"OpenXRIPBinding",
"OpenXRHand",
]

View File

@ -4,7 +4,7 @@
Suggested bindings object for OpenXR.
</brief_description>
<description>
This object stores suggested bindings for an interaction profile. Interaction profiles define the meta data for a tracked XR device such as an XR controller.
This object stores suggested bindings for an interaction profile. Interaction profiles define the metadata for a tracked XR device such as an XR controller.
For more information see the [url=https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#semantic-path-interaction-profiles]interaction profiles info in the OpenXR specification[/url].
</description>
<tutorials>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="OpenXRInteractionProfileMetadata" inherits="Object" version="4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
Meta class registering supported devices in OpenXR.
</brief_description>
<description>
This class allows OpenXR core and extensions to register metadata relating to supported interaction devices such as controllers, trackers, haptic devices, etc. It is primarily used by the action map editor and to sanitize any action map by removing extension-dependent entries when applicable.
</description>
<tutorials>
</tutorials>
<methods>
<method name="register_interaction_profile">
<return type="void" />
<param index="0" name="display_name" type="String" />
<param index="1" name="openxr_path" type="String" />
<param index="2" name="openxr_extension_name" type="String" />
<description>
Registers an interaction profile using its OpenXR designation (e.g. [code]/interaction_profiles/khr/simple_controller[/code] is the profile for OpenXR's simple controller profile).
[param display_name] is the description shown to the user. [param openxr_path] is the interaction profile path being registered. [param openxr_extension_name] optionally restricts this profile to the given extension being enabled/available. If the extension is not available, the profile and all related entries used in an action map are filtered out.
</description>
</method>
<method name="register_io_path">
<return type="void" />
<param index="0" name="interaction_profile" type="String" />
<param index="1" name="display_name" type="String" />
<param index="2" name="toplevel_path" type="String" />
<param index="3" name="openxr_path" type="String" />
<param index="4" name="openxr_extension_name" type="String" />
<param index="5" name="action_type" type="int" enum="OpenXRAction.ActionType" />
<description>
Registers an input/output path for the given [param interaction_profile]. The profile should previously have been registered using [method register_interaction_profile]. [param display_name] is the description shown to the user. [param toplevel_path] specifies the bind path this input/output can be bound to (e.g. [code]/user/hand/left[/code] or [code]/user/hand/right[/code]). [param openxr_path] is the action input/output being registered (e.g. [code]/user/hand/left/input/aim/pose[/code]). [param openxr_extension_name] restricts this input/output to an enabled/available extension, this doesn't need to repeat the extension on the profile but relates to overlapping extension (e.g. [code]XR_EXT_palm_pose[/code] that introduces [code]…/input/palm_ext/pose[/code] input paths). [param action_type] defines the type of input or output provided by OpenXR.
</description>
</method>
<method name="register_top_level_path">
<return type="void" />
<param index="0" name="display_name" type="String" />
<param index="1" name="openxr_path" type="String" />
<param index="2" name="openxr_extension_name" type="String" />
<description>
Registers a top level path to which profiles can be bound. For instance [code]/user/hand/left[/code] refers to the bind point for the player's left hand. Extensions can register additional top level paths, for instance a haptic vest extension might register [code]/user/body/vest[/code].
[param display_name] is the name shown to the user. [param openxr_path] is the top level path being registered. [param openxr_extension_name] is optional and ensures the top level path is only used if the specified extension is available/enabled.
When a top level path ends up being bound by OpenXR, a [XRPositionalTracker] is instantiated to manage the state of the device.
</description>
</method>
</methods>
</class>

View File

@ -148,7 +148,7 @@ OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenX
String profile_path = interaction_profile->get_interaction_profile_path();
String profile_name = profile_path;
profile_def = OpenXRInteractionProfileMetaData::get_singleton()->get_profile(profile_path);
profile_def = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(profile_path);
if (profile_def != nullptr) {
profile_name = profile_def->display_name;
}
@ -185,7 +185,7 @@ void OpenXRInteractionProfileEditor::_on_remove_pressed(const String p_action, c
undo_redo->commit_action(true);
}
void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetaData::IOPath *p_io_path) {
void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetadata::IOPath *p_io_path) {
HBoxContainer *path_hb = memnew(HBoxContainer);
path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
p_container->add_child(path_hb);
@ -274,7 +274,7 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() {
// Determine toplevel paths
Vector<String> top_level_paths;
for (int i = 0; i < profile_def->io_paths.size(); i++) {
const OpenXRInteractionProfileMetaData::IOPath *io_path = &profile_def->io_paths[i];
const OpenXRInteractionProfileMetadata::IOPath *io_path = &profile_def->io_paths[i];
if (!top_level_paths.has(io_path->top_level_path)) {
top_level_paths.push_back(io_path->top_level_path);
@ -291,11 +291,11 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() {
panel->add_child(container);
Label *label = memnew(Label);
label->set_text(OpenXRInteractionProfileMetaData::get_singleton()->get_top_level_name(top_level_paths[i]));
label->set_text(OpenXRInteractionProfileMetadata::get_singleton()->get_top_level_name(top_level_paths[i]));
container->add_child(label);
for (int j = 0; j < profile_def->io_paths.size(); j++) {
const OpenXRInteractionProfileMetaData::IOPath *io_path = &profile_def->io_paths[j];
const OpenXRInteractionProfileMetadata::IOPath *io_path = &profile_def->io_paths[j];
if (io_path->top_level_path == top_level_paths[i]) {
_add_io_path(container, io_path);
}

View File

@ -33,7 +33,7 @@
#include "../action_map/openxr_action_map.h"
#include "../action_map/openxr_interaction_profile.h"
#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
#include "openxr_select_action_dialog.h"
#include "editor/editor_undo_redo_manager.h"
@ -52,7 +52,7 @@ protected:
static void _bind_methods();
void _notification(int p_what);
const OpenXRInteractionProfileMetaData::InteractionProfile *profile_def = nullptr;
const OpenXRInteractionProfileMetadata::InteractionProfile *profile_def = nullptr;
public:
Ref<OpenXRInteractionProfile> get_interaction_profile() { return interaction_profile; }
@ -77,7 +77,7 @@ private:
HBoxContainer *main_hb = nullptr;
OpenXRSelectActionDialog *select_action_dialog = nullptr;
void _add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetaData::IOPath *p_io_path);
void _add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetadata::IOPath *p_io_path);
public:
void select_action_for(const String p_io_path);

View File

@ -75,13 +75,13 @@ void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_inclu
ip_buttons.clear();
// in with the new
PackedStringArray interaction_profiles = OpenXRInteractionProfileMetaData::get_singleton()->get_interaction_profile_paths();
PackedStringArray interaction_profiles = OpenXRInteractionProfileMetadata::get_singleton()->get_interaction_profile_paths();
for (int i = 0; i < interaction_profiles.size(); i++) {
String path = interaction_profiles[i];
if (!p_do_not_include.has(path)) {
Button *ip_button = memnew(Button);
ip_button->set_flat(true);
ip_button->set_text(OpenXRInteractionProfileMetaData::get_singleton()->get_profile(path)->display_name);
ip_button->set_text(OpenXRInteractionProfileMetadata::get_singleton()->get_profile(path)->display_name);
ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile).bind(path));
main_vb->add_child(ip_button);

View File

@ -31,7 +31,7 @@
#ifndef OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
#define OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"

View File

@ -36,8 +36,6 @@
#include "core/templates/hash_map.h"
#include "core/templates/rid.h"
#include "thirdparty/openxr/src/common/xr_linear.h"
#include <openxr/openxr.h>
class OpenXRAPI;

View File

@ -30,7 +30,7 @@
#include "openxr_htc_controller_extension.h"
#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
HashMap<String, bool *> OpenXRHTCControllerExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;
@ -46,7 +46,7 @@ bool OpenXRHTCControllerExtension::is_available(HTCControllers p_type) {
}
void OpenXRHTCControllerExtension::on_register_metadata() {
OpenXRInteractionProfileMetaData *metadata = OpenXRInteractionProfileMetaData::get_singleton();
OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton();
ERR_FAIL_NULL(metadata);
// HTC Vive Cosmos controller

View File

@ -30,7 +30,7 @@
#include "openxr_htc_vive_tracker_extension.h"
#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
#include "core/string/print_string.h"
@ -47,7 +47,7 @@ bool OpenXRHTCViveTrackerExtension::is_available() {
}
void OpenXRHTCViveTrackerExtension::on_register_metadata() {
OpenXRInteractionProfileMetaData *metadata = OpenXRInteractionProfileMetaData::get_singleton();
OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton();
ERR_FAIL_NULL(metadata);
// HTC Vive tracker

View File

@ -30,7 +30,7 @@
#include "openxr_huawei_controller_extension.h"
#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
HashMap<String, bool *> OpenXRHuaweiControllerExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;
@ -45,7 +45,7 @@ bool OpenXRHuaweiControllerExtension::is_available() {
}
void OpenXRHuaweiControllerExtension::on_register_metadata() {
OpenXRInteractionProfileMetaData *metadata = OpenXRInteractionProfileMetaData::get_singleton();
OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton();
ERR_FAIL_NULL(metadata);
// Huawei controller

View File

@ -30,7 +30,7 @@
#include "openxr_ml2_controller_extension.h"
#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
HashMap<String, bool *> OpenXRML2ControllerExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;
@ -45,7 +45,7 @@ bool OpenXRML2ControllerExtension::is_available() {
}
void OpenXRML2ControllerExtension::on_register_metadata() {
OpenXRInteractionProfileMetaData *metadata = OpenXRInteractionProfileMetaData::get_singleton();
OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton();
ERR_FAIL_NULL(metadata);
// Magic Leap 2 Controller

View File

@ -278,8 +278,8 @@ bool OpenXROpenGLExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
}
bool OpenXROpenGLExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) {
XrMatrix4x4f matrix;
XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
OpenXRUtil::XrMatrix4x4f matrix;
OpenXRUtil::XrMatrix4x4f_CreateProjectionFov(&matrix, OpenXRUtil::GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {

View File

@ -30,7 +30,7 @@
#include "openxr_pico_controller_extension.h"
#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
// Pico controllers are not part of the OpenXR spec at the time of writing this
// code. We'll hardcode the extension name that is used internally, verified by
@ -53,7 +53,7 @@ bool OpenXRPicoControllerExtension::is_available() {
}
void OpenXRPicoControllerExtension::on_register_metadata() {
OpenXRInteractionProfileMetaData *metadata = OpenXRInteractionProfileMetaData::get_singleton();
OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton();
ERR_FAIL_NULL(metadata);
// Pico controller (Pico 4 and Pico Neo 3 controllers)

View File

@ -381,8 +381,8 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) {
// Even though this is a Vulkan renderer we're using OpenGL coordinate systems
XrMatrix4x4f matrix;
XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
OpenXRUtil::XrMatrix4x4f matrix;
OpenXRUtil::XrMatrix4x4f_CreateProjectionFov(&matrix, OpenXRUtil::GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {

View File

@ -30,7 +30,7 @@
#include "openxr_wmr_controller_extension.h"
#include "../action_map/openxr_interaction_profile_meta_data.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
HashMap<String, bool *> OpenXRWMRControllerExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;
@ -47,7 +47,7 @@ bool OpenXRWMRControllerExtension::is_available(WMRControllers p_type) {
}
void OpenXRWMRControllerExtension::on_register_metadata() {
OpenXRInteractionProfileMetaData *metadata = OpenXRInteractionProfileMetaData::get_singleton();
OpenXRInteractionProfileMetadata *metadata = OpenXRInteractionProfileMetadata::get_singleton();
ERR_FAIL_NULL(metadata);
// HP MR controller (newer G2 controllers)

Some files were not shown because too many files have changed in this diff Show More