diff options
124 files changed, 1788 insertions, 1003 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index fe5631cefd..d1e622edb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,428 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [4.0] - TBD + +### Added + +#### Animation + +- [Revamped 3D animation storage.](https://godotengine.org/article/animation-data-redesign-40) + - [New blend shape track to adjust blend shapes in animations more efficiently.](https://github.com/godotengine/godot/pull/53865) + - [New expression-based transitions in AnimationTree state machines.](https://github.com/godotengine/godot/pull/54327) + - [Support for animation compression to improve performance with long animations such as cutscenes.](https://github.com/godotengine/godot/pull/54050) + - [Replaced transform tracks by position, rotation and scale tracks.](https://github.com/godotengine/godot/pull/53689) + - [Removed the animation dependency on bone rests.](https://github.com/godotengine/godot/pull/53765) + - Better compatibility with models that use non-uniform scaling in animations. + - Better compatibility with models exported from Maya and 3DS Max. + - Easier animation reuse across different models. + - Easier procedural generation of animations. + +#### Core + +- New TileMap and TileSet resources. +- New Vector2i, Vector3i and Rect2i types. + - These are integer variants of Vector2, Vector3 and Rect2. +- Callable type for first-class functions (can be created with lambdas in GDScript). +- The Euler rotation order can now be adjusted in Node3D. +- [New `Array.map()`, `Array.filter()` and `Array.reduce()` methods that can be used with Callables.](https://github.com/godotengine/godot/pull/38645) +- [Rewritten Tween with more functionality](https://github.com/godotengine/godot/pull/41794). + - Tween is no longer a node. + - Easier chaining of tweens. + - Low-level tweening option to get an interpolated value directly. + - *Existing projects will have to be modified to account for this, as automatic conversion isn't feasible.* +- [New and improved IK in Skeleton2D](https://github.com/godotengine/godot/pull/40347). + - New classes: SkeletonModifier2D, SkeletonModifierStack2D, SkeletonModification2DLookAt, SkeletonModification2DCCDIK, SkeletonModification2DFABRIK, SkeletonModification2DJiggle, SkeletonModification2DTwoBoneIK, PhysicalBone2D, SkeletonModification2DPhysicalBones, SkeletonModification2DStackHolder. + - New `Transform2D.looking_at()` function. +- [New and improved IK in Skeleton3D](https://github.com/godotengine/godot/pull/39353). + - New classes: SkeletonModifier3D, SkeletonModifierStack3D, SkeletonModifier3DLookAt, SkeletonModification3DCCDIK, SkeletonModification3DFABRIK, SkeletonModification3DJiggle, SkeletonModification3DTwoBoneIK, SkeletonModification3DStackHolder. + - The Bone struct now includes a local_pose_override. + - The Bone struct now keeps track of its children bones, if it has any. + - Added functions to Skeleton3D for getting the forward vector using the information stored in the rest pose for the bones. + - New `Basis.rotate_to_align()` function. + - Refactored the BoneAttachment3D node. + - Removed the `process_list` functions. +- [New GradientTexture2D resource (useful for 2D lights, particles, …)](https://github.com/godotengine/godot/pull/53234). +- [Support for gettext PO template generation from scene and script files.](https://github.com/godotengine/godot/pull/39415) + - Translation parser plugins can be written to allow extracting strings from custom file types. +- [New Time singleton to replace date/time handling methods in the OS singleton.](https://github.com/godotengine/godot/pull/49123) + - Includes new methods to handle ISO 8601 timestamp conversion. +- [Support for custom performance monitors](https://github.com/godotengine/godot/pull/39302). +- New `randi_range()` global scope function to return a random *integer* number within a range. +- New `randfn()` global scope function to return a floating-point number along a normal gaussian distribution. +- [New `pingpong()` global scope function to return a floating-point number that increments then decrements in a "sawtooth" fashion.](https://github.com/godotengine/godot/pull/46346) +- Vectors and Colors can now be clamped between two values their respective `clamp()` methods. +- New `Vector3.limit_length()` method as a Vector3 counterpart to `Vector2.limit_length()` (formerly `Vector2.clamped()`). +- New PackedArrays to replace PoolArrays. + - 64-bit integer and float arrays are now available in addition to the existing 32-bit ones. +- New `ConfigFile.parse(data: String)` method to load a string as if it was a ConfigFile on disk. +- New `Image.save_png_to_buffer()` method to save a PNG image to memory as a PackedByteArray (instead of saving to disk). +- [New File API to check, read and write symbolic links on macOS and Linux.](https://github.com/godotengine/godot/pull/46866) +- [Replaced GDNative with GDExtension](https://godotengine.org/article/introducing-gd-extensions). + - Easier setup and compilation for various platforms. + - Code structure is more similar to [statically compiled C++ modules](https://docs.godotengine.org/en/stable/development/cpp/custom_modules_in_cpp.html). + - Lower performance overhead compared to GDNative. + +#### Editor + +- New TileMap and TileSet editors with better usability. +- Support for multiple windows. + - Docks can be moved out of the main window into separate windows. + - Single-window mode can be enabled in the Editor Settings to revert to the old behavior. +- Movement and scaling handles in the 2D editor (similar to the 3D editor). +- New Replace in Files dialog in the script editor to complement Find in Files. +- **macOS:** More built-in mouse cursors are now exposed (such as diagonal resize cursors). +- **macOS:** Support for building Godot with Clang sanitizers. +- **HTML5:** [Support for profiling projects exported to HTML5.](https://godotengine.org/article/html5-export-profiling) + +#### Export + +- **macOS:** Projects can now optionally be exported to a application bundle contained within a ZIP archive. + - Previously, a DMG image was always used when exporting from macOS. +- **macOS:** DMG images can now be codesigned after exporting. + +#### GDScript + +- GDScript was rewritten from scratch with a cleaner approach. + - Annotations to replace keywords in certain cases (`@export`, `@onready`, `@rpc()`, `@tool`, `@warning_ignore()`, …). + - Typed arrays (`var array_of_nodes: Array[Node]`). Any type can be used, including custom classes. + - See individual progress reports for more information: + [#1](https://godotengine.org/article/gdscript-progress-report-writing-tokenizer), + [#2](https://godotengine.org/article/gdscript-progress-report-writing-new-parser), + [#3](https://godotengine.org/article/gdscript-progress-report-type-checking-back). +- [New documentation generation system](https://github.com/godotengine/godot/pull/41095). + - Comments starting with `##` are considered documentation comments. + - Documentation comments be placed before any member variable, constant, enum or function declaration, or at the top of a file. + - Documentation comments appear in the editor help and when hovering exported properties in the inspector. + +#### GUI + +- Support for multiple windows on desktop platforms. Projects can spawn additional windows, each with their own viewport. + - Added `NOTIFICATION_APPLICATION_FOCUS_IN` and `NOTIFICATION_APPLICATION_FOCUS_OUT` notifications for "global" project focus changes (separate from `NOTIFICATION_WM_FOCUS_IN` and `NOTIFICATION_WM_FOCUS_OUT`). +- RichTextLabel property `fit_content_height` to make the label's height fit its content automatically (not always reliable). +- RichTextLabel's `img` tag now supports an optional `color` attribute to modulate the image. +- `get_char_size()` is now exposed in Font, making it usable in DynamicFont rather than being limited to BitmapFont. +- [Tree can now highlight relationship lines for the currently selected item, its parents and direct children.](https://github.com/godotengine/godot/pull/48546) + - This is used in the scene tree dock in the editor. + +#### Import + +- Support for importing lights from glTF scenes. + +#### Input + +- Support for physical (keyboard layout-independent) key codes. + - This can be used to provide <kbd>W</kbd>/<kbd>A</kbd>/<kbd>S</kbd>/<kbd>D</kbd> controls that work on any keyboard layout. +- `DisplayServer.keyboard_get_current_layout()` and `DisplayServer.keyboard_get_layout_*()` methods to get information about keyboard layouts. +- New `Input.MOUSE_MODE_CONFINED_HIDDEN` mouse mode to combine the confined and hidden mouse modes. + +#### Mono/C# + +- Support for exporting C# projects to iOS and HTML5. +- [C# events can now be used to implement Godot signals](https://godotengine.org/article/csharp-ios-signals-events). +- [New Visual Studio and Visual Studio Code add-ons.](https://godotengine.org/article/csharp-vs-and-vscode) + +#### Navigation + +- [New NavigationServer.](https://godotengine.org/article/navigation-server-godot-4-0) + - Support for dynamic obstacle avoidance. + +#### Networking + +- [Support for DTLS encryption in UDP and ENet.](https://godotengine.org/article/enet-dtls-encryption) + +#### Porting + +- New DisplayServer abstraction, allowing for the creation of multiple windows. + - This is used in the editor for detachable docks, but can also be used in projects. +- **Android:** [Allow basic user data backup. This can be disabled in the export preset if needed.](https://github.com/godotengine/godot/pull/49069) +- **Android:** [Support for changing the mouse cursor shape (no custom images)](https://github.com/godotengine/godot/pull/44201). +- **iOS:** [The targeted device family (iPhone, iPad, iPhone and iPad) can now be specified in the export preset.](https://github.com/godotengine/godot/pull/49137) + +#### Physics + +- New CharacterBody node to supersede KinematicBody. + - Some KinematicBody features were moved to PhysicsBody. + +#### Porting + +- **Android:** Clients of the Godot library can now add their own command line arguments. + +#### Rendering + +- New Vulkan renderer. +- [New OpenGL renderer, using OpenGL 3.3/OpenGL ES 3.0/WebGL 2.0 as a baseline.](https://github.com/godotengine/godot/pull/53150) + - Designed to target mobile/web platforms first, but also usable on desktop platforms. + - Uses a low-end-friendly approach to maximize performance in simple scenes. + - Currently supports 2D rendering only. + - OpenGL 3D rendering is planned for a future 4.x release. +- Support for specular mapping when using 2D lighting. +- [New DirectionalLight2D node for 2D lighting.](https://github.com/godotengine/godot/pull/43297) +- CanvasGroup node to modulate several 2D nodes as a group (or apply shaders to them). +- Support for clipping in CanvasItem, replacing the use of Light2D as masks in a more convenient manner. +- [Support for light projectors/"cookies" in OmniLight3D and SpotLight3D.](https://github.com/godotengine/godot/pull/37887) + - Only supported for lights with shadows enabled. +- 3D lights now have a Size property which can be set to simulate area lights. + - This property also affects how fast shadow penumbras will grow over distance. + - A shadow blur property is also available to set a constant blurring factor on a per-light basis. +- Shadow mapping with improved filtering and PCSS-like penumbra simulation. + - Shadow normal offset bias is now implemented to avoid issues with shadow acne or peter-panning. +- [New Decal node to project textures onto 3D surfaces.](https://github.com/godotengine/godot/pull/37861) +- New fully real-time VoxelGI (formerly GIProbe). + - Dynamic lights and emissive can emit GI that's updated every frame (instead of only updating sporadically). + - Dynamic objects can receive GI and contribute to it. +- [New signed distance field-based global illumination](https://godotengine.org/article/godot-40-gets-sdf-based-real-time-global-illumination) (SDFGI) for open world lighting. + - Enabled in the WorldEnvironment. No node required, no baking. + - Semi-realtime: dynamic objects can receive GI, but not contribute to it. +- [Volumetric fog](https://github.com/godotengine/godot/pull/41213) with optional GI contribution. +- [Fog volumes to locally apply volumetric fog (or subtract to global fog using negative density).](https://github.com/godotengine/godot/pull/53353) +- More physically accurate exponential fog to replace the old distance-based fog. +- New Aerial Scattering property in distance-based fog to fade out to the background sky instead of a fixed color. + - Also available in volumetric fog with the Ambient Inject property. +- [New GPU-based lightmapper.](https://godotengine.org/article/godot-40-will-get-new-modernized-lightmapper) + - When using a dedicated GPU, this results in much faster bake speeds compared to the CPU lightmapper. + - Optional support for storing directional lighting information and rough reflections using spherical harmonics. + - Improved support for lighting dynamic objects with better performance and quality. + - In addition to automatic generation, LightmapProbe nodes can now be placed manually to provide better lighting information for dynamic objects where needed. +- [Physical sky material and custom sky shaders](https://godotengine.org/article/custom-sky-shaders-godot-4-0), both supporting real-time updates. +- [Global and per-instance shader uniforms.](https://godotengine.org/article/godot-40-gets-global-and-instance-shader-uniforms) + - This can be used to better reuse shaders, leading to improved performance. +- Support for automatically generating and using mesh LODs to improve performance. + - Several LOD levels are generated for imported 3D scenes by default. + - LODs are automatically used for mesh rendering using a pixel coverage-based selection algorithm. + - Uses the [meshoptimizer](https://github.com/zeux/meshoptimizer) library. +- Support for LOD visibility ranges in GeometryInstance3D. + - Manually authored LODs can be configured using distance and hysteresis cutoffs. + - Can be used for <abbr title="Hierarchical Level of Detail">HLOD</abbr> setups to reduce draw calls while preserving culling opportunities when up close. +- [Support for GeometryInstance3D distance fade to make distant meshes disappear smoothly without having to modify their material.](https://github.com/godotengine/godot/pull/54222) +- Support for automatically generating and using shadow meshes to improve performance. + - The generated shadow meshes are welded aggressively to improve performance with no difference in visual quality. + - To further improve performance, hand-made shadow meshes can be specified in the inspector in MeshInstance nodes. +- [Support for rendering a viewport's 3D contents at a lower resolution to improve performance](https://github.com/godotengine/godot/pull/51870). + - 2D elements remain at full resolution to improve perceived sharpness. + - A scaling factor above 1.0 can be used for supersampling, which is useful to maximize quality for offline rendering. +- See individual progress reports for more information: + [#1](https://godotengine.org/article/vulkan-progress-report-1), + [#2](https://godotengine.org/article/vulkan-progress-report-2), + [#3](https://godotengine.org/article/vulkan-progress-report-3), + [#4](https://godotengine.org/article/vulkan-progress-report-4), + [#5](https://godotengine.org/article/vulkan-progress-report-5), + [#6](https://godotengine.org/article/vulkan-progress-report-6), + [#7](https://godotengine.org/article/vulkan-progress-report-7). + +#### Shaders + +- New shader compiler rewritten from scratch. + - [Support for uniform arrays (including sampler arrays).](https://github.com/godotengine/godot/pull/49485) + - [Arrays can now be passed as function parameters (including arrays of structs).](https://github.com/godotengine/godot/pull/48933) + - [The return type of a function can now be an array (including arrays of structs).](https://github.com/godotengine/godot/pull/48933) + - [Array size can now be optionally written before the identifier (`int[2] array;` instead of `int array[2]`).](https://github.com/godotengine/godot/pull/53527) + - This eases porting shaders from GLSL. + - [Array constructors can now be called at any time after initialization.](https://github.com/godotengine/godot/pull/44705) + - For example, `int array[3]; array = {1, 2, 3}` is now valid. + - [New `fma()` (fused multiply-add) built-in function to optimize shaders in a low-level way.](https://github.com/godotengine/godot/pull/36225) + - [New built-in data (un)packing functions to optimize shaders in a low-level way.](https://github.com/godotengine/godot/pull/53066) + - Warning system for common issues such as floating-point comparison and unused variables. + - Argument names now appear in code completion tooltips. + - More information in the [progress report](https://godotengine.org/article/improvements-shaders-visual-shaders-godot-4). +- [Add Billboard mode to visual shaders.](https://github.com/godotengine/godot/pull/49157) +- [The constants `PI`, `TAU` and `E` are now available in the shader language.](https://github.com/godotengine/godot/pull/48837) + +#### Miscellaneous + +- The engine is now unit-tested using [doctest](https://github.com/onqtam/doctest). + - [GDScript also now has integration tests.](https://docs.godotengine.org/en/latest/development/cpp/unit_testing.html#integration-tests-for-gdscript) +- Switched from Travis CI and AppVeyor to GitHub Actions. +- A Fish shell completion file is now available for the Godot editor's command line interface. + +### Changed + +#### Audio + +- [Increased the default AudioStreamPlayer3D unit size to (1 → 10) to make sounds more audible while setting up the node.](https://github.com/godotengine/godot/pull/38224) +- Renamed the audio-related `FFT_Size` enum to `FFTSize` for consistency. + +#### Core + +- Tweaked the output strings to be more human-readable when printing various built-in Variant and Object types. +- Renamed File's `endian_swap` property to `big_endian` for consistency with ResourceSaver and StreamPeer. +- [Renamed File's `get_len()` method to `get_length()`.](https://github.com/godotengine/godot/pull/49061) +- [Renamed Object's `PROPERTY_USAGE_NOEDITOR` to `PROPERTY_USAGE_NO_EDITOR`.](https://github.com/godotengine/godot/pull/54571) +- Renamed `Vector2.clamped()` to `Vector2.limit_length()` to differentiate it from the new `Vector2.clamp()`. +- Renamed `rand_range()` to `randf_range()` to avoid ambiguity with the new `randi_range()` and make its return type more obvious. +- Replaced `Node.add_child_below_node()` with `Node.add_sibling()`. +- Replaced `Directory.list_dir_begin()`'s `skip_navigational` and `skip_hidden` arguments with `show_navigational` and `show_hidden`. + - Both arguments are `false` by default, which means the default behavior is now to exclude both navigational and hidden files from the returned list. +- Renamed the built-in Quat type to Quaternion. +- Renamed the built-in Transform type to Transform3D. +- Renamed Node3D's `translation` property to `position` for consistency with Node2D. +- Moved YSort functionality to a Node2D property. +- Viewports now use a size of 512×512 by default to make them visible out of the box. +- [Screen orientation is now represented as an enum in the Project Settings.](https://github.com/godotengine/godot/pull/48939) +- [Renamed 3D nodes to contain an explicit "3D" prefix for clarity and consistency](https://github.com/godotengine/godot/pull/37340). +- Renamed various nodes: + - Spatial → Node3D + - GIProbe → VoxelGI + - BakedLightmap → LightmapGI + - Light2D -> PointLight2D + - VisibilityNotifier2D -> VisibleOnScreenNotifier2D + - VisibilityNotifier3D -> VisibleOnScreenNotifier3D + - VisibilityEnabler2D -> VisibleOnScreenEnabler2D + - VisibilityEnabler3D -> VisibleOnScreenEnabler3D +- Renamed various resources: + - GradientTexture -> GradientTexture1D +- Old node and resource names are automatically converted when loading scenes from Godot 3.x. + +#### Editor + +- Renewed the editor theme for a more modern design. + - [Increased icon saturation by 30% when using a dark theme.](https://github.com/godotengine/godot/pull/48644) + - Icon saturation can now be adjusted in the Editor Settings. +- [Improved the audio bus editor appearance.](https://github.com/godotengine/godot/pull/49130) +- Improved layout and texts of the Manage Editor Features dialog. +- Improved the Video RAM debugger usability. + - The Video RAM tab is now refreshed automatically when switching to it. +- Hovering layer checkboxes in the inspector now results in visual feedback. + - Clicking between two checkboxes will now enable the checkbox that was last highlighted instead of doing nothing. +- CSV profiler measures can now be saved anywhere on the filesystem, not just in the project folder. +- Improved the 2D zooming algorithm to always visit powers of two (50%, 100%, 200%, …) and avoid floating-point precision issues. +- Times are now displayed as milliseconds in the profiler and performance monitors (instead of seconds). +- Improved the batch rename dialog usability and design consistency. + - Clarified error messages when there are regular expression errors. +- Optimized editor icon generation to speed up editor startup. +- Script editor autocompletion now displays previews next to color constant suggestions. +- The number of replaced results now appears in place of the matches counter when replacing text in the script editor. +- Pressing <kbd>Enter</kbd> (or <kbd>Shift + Enter</kbd>) in the script editor replacement dialog now performs a forwards (or backwards) replacement operation. +- Pressing <kbd>Ctrl + F</kbd> now focuses the search field in the AssetLib tab. +- Pressing <kbd>G</kbd> now switches to the Pan mode in the 2D editor. + - The TileMap editor's Bucket Fill shortcut was moved to <kbd>B</kbd> to cater for this change. +- Mouse wheel behavior for zooming in the animation behavior is now inverted. +- The Sync Scene Changes and Sync Script Changes settings' values now persist on a per-project basis instead of being always enabled by default. +- Various tooltips have been added or modified to clarify the editor operation. +- Various visual and formatting changes to the editor help to improve readability and be closer to the online class reference. +- Tweaked Camera2D editor line colors for better visibility. +- Light theme presets now use a negative contrast rate by default for a more logical preview of UI elevation. +- Increased the use of bold fonts throughout the editor. +- Revised icons for the Gradient and GradientTexture resources. +- Renamed "Identifier" to "Bundle Identifier" in the macOS and iOS export presets for clarity. +- Renamed the script editor's "Adaptive" syntax theme to "Default" and "Default" to "Godot 2", for consistency with the editor theme presets. +- Flipped the 2D editor icon to match Godot's coordinate handedness. + +#### GUI + +- Improved drive letter handling in EditorFileDialog and FileDialog. +- Container nodes (except PanelContainer) now use the Pass mouse mode by default. +- Pressing the left/right arrows while having selected text will now move the cursor to the beginning/end of the selection in LineEdit (while unselecting the text as usual). +- TextEdit's `search()` method now returns a Dictionary instead of a PackedIntArray. +- **macOS:** The <kbd>Ctrl + A</kbd> and <kbd>Ctrl + E</kbd> navigation shortcuts now work in LineEdit. + +#### Input + +- Renamed InputEventKey's `scancode` to `keycode`. +- Renamed InputMap's `get_action_list()` to `get_action_events()`. + +#### Networking + +- Optimized bandwidth usage in the high-level multiplayer API. + +#### Physics + +- Split KinematicBody into the new CharacterBody node and PhysicsBody. +- RayCast nodes are now enabled by default. + - The `disabled` property was renamed to `enabled` with its behavior inverted. +- Renamed PlaneShape to WorldBoundaryShape. + +#### Rendering + +- Some Environment settings such as depth of field have been moved to a CameraEffects resource which is assigned to individual Camera nodes. +- [The ACES Fitted tonemapping algoirthm is now used in place of the old ACES algorithm.](https://github.com/godotengine/godot/pull/52476) + - The old non-fitted ACES tonemapping algorithm was removed. +- Quality settings have been moved from individual nodes and resources to the Project Settings for better centralization. +- Quality settings now have performance hints in their values' names, such as "Fast" or "Slow". + +#### Shaders + +- Renamed the `.shader` file extension to `.gdshader`. + - Existing text-based shader files will have to be renamed before loading the project in a new engine version. + +#### Miscellaneous + +- Renamed the `x11` platform to `linuxbsd` to prepare for Wayland support. +- The engine is now written in C++17. +- Python 3.6 and SCons 3.1 are now required to build Godot from source. + +### Removed + +#### Buildsystem + +- Removed the `server` platform in favor of disabling specific DisplayServers at build-time (e.g. `vulkan=no`). + +#### Core + +- Removed the YSort node in favor of the Node2D YSort property. +- Removed the deprecated `Color.gray()` method. + - Use `Color.v()` for a better grayscale approximation instead. +- Removed built-in HQ2X implementation (used for crude hiDPI support in the default project theme). + - This helps with binary size as HQ2X is made of particularly large functions. + +#### Editor + +- Removed the **Dim Dialog on Editor Popup** editor setting since it was made obsolete by the multi-window paradigm. + +#### GUI + +- [Removed the ToolButton node in favor of Button.](https://github.com/godotengine/godot/pull/39690) + - Existing ToolButton nodes from Godot 3.x projects will be converted to Button nodes. + +#### Input + +- Removed the `DisplayServer.get_latin_keyboard_variant()` method (replaced by the more flexible `DisplayServer.keyboard_get_current_layout()`). + +#### Networking + +- Removed the deprecated `allow_object_decoding` property from PacketPeer. +- Removed the deprecated `sync` and `slave` high-level multiplayer keywords. + +#### Export + +- **iOS:** [Remove redundant orientation export setting in favor of the orientation project setting.](https://github.com/godotengine/godot/pull/48939) + +#### Physics + +- Removed the deprecated PhysicsBody `friction` and `bounce` properties (replaced by PhysicsMaterial). + +#### Rendering + +- Removed OpenGL ES 2.0 renderer (replaced by the new mobile-oriented OpenGL 3 renderer). + - Vulkan, OpenGL 3.3, OpenGL ES 3.0 or WebGL 2.0 support is now required to run Godot. +- [Removed support for 16× MSAA due to driver bugs and low performance.](https://github.com/godotengine/godot/pull/49063) + - For high-quality offline rendering, using supersampling together with 8× MSAA is a better option anyway. + +### Fixed + +#### Core + +- The positional command line argument now considers `.res` and `.tres` files as runnable scene formats. + - This fixes Godot not running the main scene or a custom scene if they were saved with a `.res` or `.tres` extension. +- **macOS/Linux:** Fix the result of `Directory.get_space_left()`. +- **Windows:** Godot can now kill its own PID using `OS.kill()`. + +#### Editor + +- The Android exporter no longer reports progress on each file, greatly speeding up the exporting process. +- Searching with the Whole Words option enabled in the script editor is no longer exceedingly slow. + +#### GUI + +- Fixed OptionButton minimum size. +- TabContainer is no longer too large when tabs are hidden. +- ScrollBar now allows using `scroll_to_line()` when Scroll Active is disabled. +- DynamicFont outlines now have antialiasing disabled if it was disabled on the font itself. + +#### Porting + +- **Windows:** `OS.execute()` now only quotes command line arguments if they contain special characters. + ## [3.2] - 2020-01-29 ### Added @@ -13,8 +13,6 @@ generous deed immortalized in the next stable release of Godot Engine. ## Platinum sponsors Gamblify <https://www.gamblify.com> - Heroic Labs <https://heroiclabs.com> - Spiffcode <http://www.spiffcode.com> ## Gold sponsors diff --git a/SConstruct b/SConstruct index 83bd1560ff..1922e904d0 100644 --- a/SConstruct +++ b/SConstruct @@ -149,7 +149,7 @@ opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False)) opts.Add("disable_classes", "Disable given classes (comma separated)", "") opts.Add(BoolVariable("modules_enabled_by_default", "If no, disable all modules except ones explicitly enabled", True)) -opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", False)) +opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", True)) opts.Add("system_certs_path", "Use this path as SSL certificates default for editor (for package maintainers)", "") opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False)) @@ -329,6 +329,9 @@ if env_base["target"] == "debug": if env_base["use_precise_math_checks"]: env_base.Append(CPPDEFINES=["PRECISE_MATH_CHECKS"]) +if not env_base.File("#main/splash_editor.png").exists(): + # Force disabling editor splash if missing. + env_base["no_editor_splash"] = True if env_base["no_editor_splash"]: env_base.Append(CPPDEFINES=["NO_EDITOR_SPLASH"]) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 21a802cb78..0e15edc29f 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -65,6 +65,14 @@ String ProjectSettings::get_resource_path() const { return resource_path; } +String ProjectSettings::get_safe_project_name() const { + String safe_name = OS::get_singleton()->get_safe_dir_name(get("application/config/name")); + if (safe_name.is_empty()) { + safe_name = "UnnamedProject"; + } + return safe_name; +} + String ProjectSettings::get_imported_files_path() const { return get_project_data_path().plus_file("imported"); } @@ -701,11 +709,6 @@ Error ProjectSettings::_load_settings_text(const String &p_path) { } else { if (section == String()) { set(assign, value); - } else if (section == "application" && assign == "config/features") { - const PackedStringArray project_features_untrimmed = value; - const PackedStringArray project_features = _trim_to_supported_features(project_features_untrimmed); - set("application/config/features", project_features); - save(); } else { set(section + "/" + assign, value); } @@ -923,6 +926,34 @@ Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other par Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) { ERR_FAIL_COND_V_MSG(p_path == "", ERR_INVALID_PARAMETER, "Project settings save path cannot be empty."); + PackedStringArray project_features = has_setting("application/config/features") ? (PackedStringArray)get_setting("application/config/features") : PackedStringArray(); + // If there is no feature list currently present, force one to generate. + if (project_features.is_empty()) { + project_features = ProjectSettings::get_required_features(); + } + // Check the rendering API. + const String rendering_api = has_setting("rendering/quality/driver/driver_name") ? (String)get_setting("rendering/quality/driver/driver_name") : String(); + if (rendering_api != "") { + // Add the rendering API as a project feature if it doesn't already exist. + if (!project_features.has(rendering_api)) { + project_features.append(rendering_api); + } + } + // Check for the existence of a csproj file. + if (FileAccess::exists(get_resource_path().plus_file(get_safe_project_name() + ".csproj"))) { + // If there is a csproj file, add the C# feature if it doesn't already exist. + if (!project_features.has("C#")) { + project_features.append("C#"); + } + } else { + // If there isn't a csproj file, remove the C# feature if it exists. + if (project_features.has("C#")) { + project_features.remove_at(project_features.find("C#")); + } + } + project_features = _trim_to_supported_features(project_features); + set_setting("application/config/features", project_features); + Set<_VCSort> vclist; if (p_merge_with_current) { diff --git a/core/config/project_settings.h b/core/config/project_settings.h index 2d8ec76b7a..5b74356337 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -151,6 +151,7 @@ public: String get_project_data_dir_name() const; String get_project_data_path() const; String get_resource_path() const; + String get_safe_project_name() const; String get_imported_files_path() const; static ProjectSettings *get_singleton(); diff --git a/core/doc_data.h b/core/doc_data.h index c75cdfcde5..066cc6b848 100644 --- a/core/doc_data.h +++ b/core/doc_data.h @@ -70,18 +70,29 @@ public: Vector<int> errors_returned; bool operator<(const MethodDoc &p_method) const { if (name == p_method.name) { - // Must be a constructor since there is no overloading. - // We want this arbitrary order for a class "Foo": - // - 1. Default constructor: Foo() - // - 2. Copy constructor: Foo(Foo) - // - 3+. Other constructors Foo(Bar, ...) based on first argument's name - if (arguments.size() == 0 || p_method.arguments.size() == 0) { // 1. + // Must be an operator or a constructor since there is no other overloading + if (name.left(8) == "operator") { + if (arguments.size() == p_method.arguments.size()) { + if (arguments.size() == 0) { + return false; + } + return arguments[0].type < p_method.arguments[0].type; + } return arguments.size() < p_method.arguments.size(); + } else { + // Must be a constructor + // We want this arbitrary order for a class "Foo": + // - 1. Default constructor: Foo() + // - 2. Copy constructor: Foo(Foo) + // - 3+. Other constructors Foo(Bar, ...) based on first argument's name + if (arguments.size() == 0 || p_method.arguments.size() == 0) { // 1. + return arguments.size() < p_method.arguments.size(); + } + if (arguments[0].type == return_type || p_method.arguments[0].type == p_method.return_type) { // 2. + return (arguments[0].type == return_type) || (p_method.arguments[0].type != p_method.return_type); + } + return arguments[0] < p_method.arguments[0]; } - if (arguments[0].type == return_type || p_method.arguments[0].type == p_method.return_type) { // 2. - return (arguments[0].type == return_type) || (p_method.arguments[0].type != p_method.return_type); - } - return arguments[0] < p_method.arguments[0]; } return name < p_method.name; } diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp index 719ea8afb5..61bb949ed4 100644 --- a/core/error/error_macros.cpp +++ b/core/error/error_macros.cpp @@ -76,7 +76,7 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co // Main error printing function. void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) { - OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, (Logger::ErrorType)p_type); + OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type); _global_lock(); ErrorHandlerList *l = error_handler_list; diff --git a/core/io/logger.cpp b/core/io/logger.cpp index b68a8b20a5..8a8bdf07d3 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -266,7 +266,7 @@ void CompositeLogger::log_error(const char *p_function, const char *p_file, int } for (int i = 0; i < loggers.size(); ++i) { - loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type); + loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type); } } diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 8a44646ef9..bdceae4374 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -210,7 +210,7 @@ bool AStar::has_point(int p_id) const { return points.has(p_id); } -Array AStar::get_points() { +Array AStar::get_point_ids() { Array point_list; for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) { @@ -539,7 +539,7 @@ void AStar::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar::remove_point); ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar::has_point); ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar::get_point_connections); - ClassDB::bind_method(D_METHOD("get_points"), &AStar::get_points); + ClassDB::bind_method(D_METHOD("get_point_ids"), &AStar::get_point_ids); ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar::set_point_disabled, DEFVAL(true)); ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar::is_point_disabled); @@ -606,8 +606,8 @@ Vector<int> AStar2D::get_point_connections(int p_id) { return astar.get_point_connections(p_id); } -Array AStar2D::get_points() { - return astar.get_points(); +Array AStar2D::get_point_ids() { + return astar.get_point_ids(); } void AStar2D::set_point_disabled(int p_id, bool p_disabled) { @@ -859,7 +859,7 @@ void AStar2D::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar2D::remove_point); ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar2D::has_point); ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar2D::get_point_connections); - ClassDB::bind_method(D_METHOD("get_points"), &AStar2D::get_points); + ClassDB::bind_method(D_METHOD("get_point_ids"), &AStar2D::get_point_ids); ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar2D::set_point_disabled, DEFVAL(true)); ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar2D::is_point_disabled); diff --git a/core/math/a_star.h b/core/math/a_star.h index 64fa32a325..ef6f22d228 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -138,7 +138,7 @@ public: void remove_point(int p_id); bool has_point(int p_id) const; Vector<int> get_point_connections(int p_id); - Array get_points(); + Array get_point_ids(); void set_point_disabled(int p_id, bool p_disabled = true); bool is_point_disabled(int p_id) const; @@ -188,7 +188,7 @@ public: void remove_point(int p_id); bool has_point(int p_id) const; Vector<int> get_point_connections(int p_id); - Array get_points(); + Array get_point_ids(); void set_point_disabled(int p_id, bool p_disabled = true); bool is_point_disabled(int p_id) const; diff --git a/core/math/expression.cpp b/core/math/expression.cpp index f366fd0499..fe277cff96 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -410,6 +410,14 @@ Error Expression::_get_token(Token &r_token) { } else if (id == "self") { r_token.type = TK_SELF; } else { + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + if (id == Variant::get_type_name(Variant::Type(i))) { + r_token.type = TK_BASIC_TYPE; + r_token.value = i; + return OK; + } + } + if (Variant::has_utility_function(id)) { r_token.type = TK_BUILTIN_FUNC; r_token.value = id; diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 42e3da0b27..b9bd04b8c1 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -108,10 +108,10 @@ Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const { return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta; } -Basis Vector3::outer(const Vector3 &p_b) const { - Vector3 row0(x * p_b.x, x * p_b.y, x * p_b.z); - Vector3 row1(y * p_b.x, y * p_b.y, y * p_b.z); - Vector3 row2(z * p_b.x, z * p_b.y, z * p_b.z); +Basis Vector3::outer(const Vector3 &p_with) const { + Vector3 row0(x * p_with.x, x * p_with.y, x * p_with.z); + Vector3 row1(y * p_with.x, y * p_with.y, y * p_with.z); + Vector3 row2(z * p_with.x, z * p_with.y, z * p_with.z); return Basis(row0, row1, row2); } diff --git a/core/math/vector3.h b/core/math/vector3.h index 02a56f684e..6c21968aae 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -128,9 +128,9 @@ struct Vector3 { return n.normalized(); } - _FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const; - _FORCE_INLINE_ real_t dot(const Vector3 &p_b) const; - Basis outer(const Vector3 &p_b) const; + _FORCE_INLINE_ Vector3 cross(const Vector3 &p_with) const; + _FORCE_INLINE_ real_t dot(const Vector3 &p_with) const; + Basis outer(const Vector3 &p_with) const; _FORCE_INLINE_ Vector3 abs() const; _FORCE_INLINE_ Vector3 floor() const; @@ -199,17 +199,17 @@ struct Vector3 { } }; -Vector3 Vector3::cross(const Vector3 &p_b) const { +Vector3 Vector3::cross(const Vector3 &p_with) const { Vector3 ret( - (y * p_b.z) - (z * p_b.y), - (z * p_b.x) - (x * p_b.z), - (x * p_b.y) - (y * p_b.x)); + (y * p_with.z) - (z * p_with.y), + (z * p_with.x) - (x * p_with.z), + (x * p_with.y) - (y * p_with.x)); return ret; } -real_t Vector3::dot(const Vector3 &p_b) const { - return x * p_b.x + y * p_b.y + z * p_b.z; +real_t Vector3::dot(const Vector3 &p_with) const { + return x * p_with.x + y * p_with.y + z * p_with.z; } Vector3 Vector3::abs() const { diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index c2449e3ddc..8ec1a973e7 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -511,7 +511,7 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c Variant defval; if (script->get_property_default_value(E->key(), defval)) { //remove because it's the same as the default value - if (defval == E) { + if (defval == E->get()) { to_remove.push_back(E->key()); } } diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 34b8b782d2..b586757dcd 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1471,7 +1471,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector2, angle, sarray(), varray()); bind_method(Vector2, angle_to, sarray("to"), varray()); bind_method(Vector2, angle_to_point, sarray("to"), varray()); - bind_method(Vector2, direction_to, sarray("b"), varray()); + bind_method(Vector2, direction_to, sarray("to"), varray()); bind_method(Vector2, distance_to, sarray("to"), varray()); bind_method(Vector2, distance_squared_to, sarray("to"), varray()); bind_method(Vector2, length, sarray(), varray()); @@ -1551,9 +1551,9 @@ static void _register_variant_builtin_methods() { bind_method(Vector3, max_axis, sarray(), varray()); bind_method(Vector3, angle_to, sarray("to"), varray()); bind_method(Vector3, signed_angle_to, sarray("to", "axis"), varray()); - bind_method(Vector3, direction_to, sarray("b"), varray()); - bind_method(Vector3, distance_to, sarray("b"), varray()); - bind_method(Vector3, distance_squared_to, sarray("b"), varray()); + bind_method(Vector3, direction_to, sarray("to"), varray()); + bind_method(Vector3, distance_to, sarray("to"), varray()); + bind_method(Vector3, distance_squared_to, sarray("to"), varray()); bind_method(Vector3, length, sarray(), varray()); bind_method(Vector3, length_squared, sarray(), varray()); bind_method(Vector3, limit_length, sarray("length"), varray(1.0)); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index b1350c0241..41cc043a74 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1,13 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="@GlobalScope" version="4.0"> <brief_description> - Global scope constants and variables. + Global scope constants and functions. </brief_description> <description> - Global scope constants and variables. This is all that resides in the globals, constants regarding error codes, keycodes, property hints, etc. + A list of global scope enumerated constants and built-in functions. This is all that resides in the globals, constants regarding error codes, keycodes, property hints, etc. Singletons are also documented here, since they can be accessed from anywhere. + For the entries related to GDScript which can be accessed in any script see [@GDScript]. </description> <tutorials> + <link title="Random number generation">$DOCS_URL/tutorials/math/random_number_generation.html</link> </tutorials> <methods> <method name="abs"> diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml index 11c0fc33b8..bbb5f6b8e3 100644 --- a/doc/classes/AStar.xml +++ b/doc/classes/AStar.xml @@ -244,6 +244,12 @@ Returns the number of points currently in the points pool. </description> </method> + <method name="get_point_ids"> + <return type="Array" /> + <description> + Returns an array of all point IDs. + </description> + </method> <method name="get_point_path"> <return type="PackedVector3Array" /> <argument index="0" name="from_id" type="int" /> @@ -267,12 +273,6 @@ Returns the weight scale of the point associated with the given [code]id[/code]. </description> </method> - <method name="get_points"> - <return type="Array" /> - <description> - Returns an array of all points. - </description> - </method> <method name="has_point" qualifiers="const"> <return type="bool" /> <argument index="0" name="id" type="int" /> diff --git a/doc/classes/AStar2D.xml b/doc/classes/AStar2D.xml index 43e7d59665..dc821ebb8b 100644 --- a/doc/classes/AStar2D.xml +++ b/doc/classes/AStar2D.xml @@ -215,6 +215,12 @@ Returns the number of points currently in the points pool. </description> </method> + <method name="get_point_ids"> + <return type="Array" /> + <description> + Returns an array of all point IDs. + </description> + </method> <method name="get_point_path"> <return type="PackedVector2Array" /> <argument index="0" name="from_id" type="int" /> @@ -238,12 +244,6 @@ Returns the weight scale of the point associated with the given [code]id[/code]. </description> </method> - <method name="get_points"> - <return type="Array" /> - <description> - Returns an array of all points. - </description> - </method> <method name="has_point" qualifiers="const"> <return type="bool" /> <argument index="0" name="id" type="int" /> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 8a12314ba8..c75b2e305e 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -791,8 +791,8 @@ <constant name="NOTIFICATION_DRAG_END" value="22"> Notification received when a drag ends. </constant> - <constant name="NOTIFICATION_PATH_CHANGED" value="23"> - Notification received when the node's [NodePath] changed. + <constant name="NOTIFICATION_PATH_RENAMED" value="23"> + Notification received when the node's name or one of its parents' name is changed. This notification is [i]not[/i] received when the node is removed from the scene tree to be added to another parent later on. </constant> <constant name="NOTIFICATION_INTERNAL_PROCESS" value="25"> Notification received every frame when the internal process flag is set (see [method set_process_internal]). diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml index b723c9f4d4..32abd1caea 100644 --- a/doc/classes/SpriteBase3D.xml +++ b/doc/classes/SpriteBase3D.xml @@ -60,7 +60,8 @@ If [code]true[/code], texture is flipped vertically. </member> <member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)"> - A color value that gets multiplied on, could be used for mood-coloring or to simulate the color of light. + A color value used to [i]multiply[/i] the texture's colors. Can be used for mood-coloring or to simulate the color of light. + [b]Note:[/b] If a [member GeometryInstance3D.material_override] is defined on the [SpriteBase3D], the material override must be configured to take vertex colors into account for albedo. Otherwise, the color defined in [member modulate] will be ignored. For a [BaseMaterial3D], [member BaseMaterial3D.vertex_color_use_as_albedo] must be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/color] must be inserted in the shader's [code]fragment()[/code] function. </member> <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)"> The texture's drawing offset. diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index 1f32bba5a1..ad1e5c0050 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -4,8 +4,9 @@ Tabbed container. </brief_description> <description> - Sets the active tab's [code]visible[/code] property to the value [code]true[/code]. Sets all other children's to [code]false[/code]. + Arranges [Control] children into a tabbed view, creating a tab for each one. The active tab's corresponding [Control] has its [code]visible[/code] property set to [code]true[/code], and all other children's to [code]false[/code]. Ignores non-[Control] children. + [b]Note:[/b] The drawing of the clickable tabs themselves is handled by this node. Adding [TabBar]s as children is not needed. </description> <tutorials> </tutorials> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index be41cdde99..97cbf6918d 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -225,17 +225,17 @@ </description> </operator> <operator name="operator *"> - <return type="Transform2D" /> - <argument index="0" name="right" type="Transform2D" /> + <return type="Rect2" /> + <argument index="0" name="right" type="Rect2" /> <description> - Composes these two transformation matrices by multiplying them together. This has the effect of transforming the second transform (the child) by the first transform (the parent). + Transforms (multiplies) the [Rect2] by the given [Transform2D] matrix. </description> </operator> <operator name="operator *"> - <return type="Rect2" /> - <argument index="0" name="right" type="Rect2" /> + <return type="Transform2D" /> + <argument index="0" name="right" type="Transform2D" /> <description> - Transforms (multiplies) the [Rect2] by the given [Transform2D] matrix. + Composes these two transformation matrices by multiplying them together. This has the effect of transforming the second transform (the child) by the first transform (the parent). </description> </operator> <operator name="operator *"> diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml index 511574f6aa..e62cb9216e 100644 --- a/doc/classes/Transform3D.xml +++ b/doc/classes/Transform3D.xml @@ -152,6 +152,13 @@ </description> </operator> <operator name="operator *"> + <return type="AABB" /> + <argument index="0" name="right" type="AABB" /> + <description> + Transforms (multiplies) the [AABB] by the given [Transform3D] matrix. + </description> + </operator> + <operator name="operator *"> <return type="PackedVector3Array" /> <argument index="0" name="right" type="PackedVector3Array" /> <description> @@ -166,13 +173,6 @@ </description> </operator> <operator name="operator *"> - <return type="AABB" /> - <argument index="0" name="right" type="AABB" /> - <description> - Transforms (multiplies) the [AABB] by the given [Transform3D] matrix. - </description> - </operator> - <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="Vector3" /> <description> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 595af6222c..15f7d2f9e3 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -125,16 +125,16 @@ </method> <method name="direction_to" qualifiers="const"> <return type="Vector2" /> - <argument index="0" name="b" type="Vector2" /> + <argument index="0" name="to" type="Vector2" /> <description> - Returns the normalized vector pointing from this vector to [code]b[/code]. This is equivalent to using [code](b - a).normalized()[/code]. + Returns the normalized vector pointing from this vector to [code]to[/code]. This is equivalent to using [code](b - a).normalized()[/code]. </description> </method> <method name="distance_squared_to" qualifiers="const"> <return type="float" /> <argument index="0" name="to" type="Vector2" /> <description> - Returns the squared distance between this vector and [code]b[/code]. + Returns the squared distance between this vector and [code]to[/code]. This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula. </description> </method> @@ -358,19 +358,19 @@ </operator> <operator name="operator *"> <return type="Vector2" /> - <argument index="0" name="right" type="Vector2" /> + <argument index="0" name="right" type="Transform2D" /> <description> - Multiplies each component of the [Vector2] by the components of the given [Vector2]. - [codeblock] - print(Vector2(10, 20) * Vector2(3, 4)) # Prints "(30, 80)" - [/codeblock] + Inversely transforms (multiplies) the [Vector2] by the given [Transform2D] transformation matrix. </description> </operator> <operator name="operator *"> <return type="Vector2" /> - <argument index="0" name="right" type="Transform2D" /> + <argument index="0" name="right" type="Vector2" /> <description> - Inversely transforms (multiplies) the [Vector2] by the given [Transform2D] transformation matrix. + Multiplies each component of the [Vector2] by the components of the given [Vector2]. + [codeblock] + print(Vector2(10, 20) * Vector2(3, 4)) # Prints "(30, 80)" + [/codeblock] </description> </operator> <operator name="operator *"> diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 62d467c505..6d87ce9ea8 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -86,7 +86,7 @@ <return type="Vector3" /> <argument index="0" name="with" type="Vector3" /> <description> - Returns the cross product of this vector and [code]b[/code]. + Returns the cross product of this vector and [code]with[/code]. </description> </method> <method name="cubic_interpolate" qualifiers="const"> @@ -101,31 +101,31 @@ </method> <method name="direction_to" qualifiers="const"> <return type="Vector3" /> - <argument index="0" name="b" type="Vector3" /> + <argument index="0" name="to" type="Vector3" /> <description> - Returns the normalized vector pointing from this vector to [code]b[/code]. This is equivalent to using [code](b - a).normalized()[/code]. + Returns the normalized vector pointing from this vector to [code]to[/code]. This is equivalent to using [code](b - a).normalized()[/code]. </description> </method> <method name="distance_squared_to" qualifiers="const"> <return type="float" /> - <argument index="0" name="b" type="Vector3" /> + <argument index="0" name="to" type="Vector3" /> <description> - Returns the squared distance between this vector and [code]b[/code]. + Returns the squared distance between this vector and [code]to[/code]. This method runs faster than [method distance_to], so prefer it if you need to compare vectors or need the squared distance for some formula. </description> </method> <method name="distance_to" qualifiers="const"> <return type="float" /> - <argument index="0" name="b" type="Vector3" /> + <argument index="0" name="to" type="Vector3" /> <description> - Returns the distance between this vector and [code]b[/code]. + Returns the distance between this vector and [code]to[/code]. </description> </method> <method name="dot" qualifiers="const"> <return type="float" /> <argument index="0" name="with" type="Vector3" /> <description> - Returns the dot product of this vector and [code]b[/code]. This can be used to compare the angle between two vectors. For example, this can be used to determine whether an enemy is facing the player. + Returns the dot product of this vector and [code]with[/code]. This can be used to compare the angle between two vectors. For example, this can be used to determine whether an enemy is facing the player. The dot product will be [code]0[/code] for a straight angle (90 degrees), greater than 0 for angles narrower than 90 degrees and lower than 0 for angles wider than 90 degrees. When using unit (normalized) vectors, the result will always be between [code]-1.0[/code] (180 degree angle) when the vectors are facing opposite directions, and [code]1.0[/code] (0 degree angle) when the vectors are aligned. [b]Note:[/b] [code]a.dot(b)[/code] is equivalent to [code]b.dot(a)[/code]. @@ -225,7 +225,7 @@ <return type="Basis" /> <argument index="0" name="with" type="Vector3" /> <description> - Returns the outer product with [code]b[/code]. + Returns the outer product with [code]with[/code]. </description> </method> <method name="posmod" qualifiers="const"> @@ -373,16 +373,6 @@ </operator> <operator name="operator *"> <return type="Vector3" /> - <argument index="0" name="right" type="Vector3" /> - <description> - Multiplies each component of the [Vector3] by the components of the given [Vector3]. - [codeblock] - print(Vector3(10, 20, 30) * Vector3(3, 4, 5)) # Prints "(30, 80, 150)" - [/codeblock] - </description> - </operator> - <operator name="operator *"> - <return type="Vector3" /> <argument index="0" name="right" type="Basis" /> <description> Inversely transforms (multiplies) the [Vector3] by the given [Basis] matrix. @@ -404,6 +394,16 @@ </operator> <operator name="operator *"> <return type="Vector3" /> + <argument index="0" name="right" type="Vector3" /> + <description> + Multiplies each component of the [Vector3] by the components of the given [Vector3]. + [codeblock] + print(Vector3(10, 20, 30) * Vector3(3, 4, 5)) # Prints "(30, 80, 150)" + [/codeblock] + </description> + </operator> + <operator name="operator *"> + <return type="Vector3" /> <argument index="0" name="right" type="float" /> <description> Multiplies each component of the [Vector3] by the given [float]. diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 0418f29808..4a3f99696d 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -25,13 +25,13 @@ <method name="find_world_2d" qualifiers="const"> <return type="World2D" /> <description> - Returns the 2D world of the viewport. + Returns the first valid [World2D] for this viewport, searching the [member world_2d] property of itself and any Viewport ancestor. </description> </method> <method name="find_world_3d" qualifiers="const"> <return type="World3D" /> <description> - Returns the 3D world of the viewport, or if none the world of the parent viewport. + Returns the first valid [World3D] for this viewport, searching the [member world_3d] property of itself and any Viewport ancestor. </description> </method> <method name="get_camera_2d" qualifiers="const"> diff --git a/doc/classes/float.xml b/doc/classes/float.xml index c96360e6ba..9effe9d5bf 100644 --- a/doc/classes/float.xml +++ b/doc/classes/float.xml @@ -62,10 +62,13 @@ </description> </operator> <operator name="operator *"> - <return type="float" /> - <argument index="0" name="right" type="float" /> + <return type="Color" /> + <argument index="0" name="right" type="Color" /> <description> - Multiplies two [float]s. + Multiplies each component of the [Color] by the given [float]. + [codeblock] + print(1.5 * Color(0.5, 0.5, 0.5)) # Color(0.75, 0.75, 0.75) + [/codeblock] </description> </operator> <operator name="operator *"> @@ -113,13 +116,10 @@ </description> </operator> <operator name="operator *"> - <return type="Color" /> - <argument index="0" name="right" type="Color" /> + <return type="float" /> + <argument index="0" name="right" type="float" /> <description> - Multiplies each component of the [Color] by the given [float]. - [codeblock] - print(1.5 * Color(0.5, 0.5, 0.5)) # Color(0.75, 0.75, 0.75) - [/codeblock] + Multiplies two [float]s. </description> </operator> <operator name="operator *"> diff --git a/doc/classes/int.xml b/doc/classes/int.xml index bb36d83741..d212fe42bf 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -132,20 +132,6 @@ </description> </operator> <operator name="operator *"> - <return type="int" /> - <argument index="0" name="right" type="int" /> - <description> - Multiplies two [int]s. - </description> - </operator> - <operator name="operator *"> - <return type="float" /> - <argument index="0" name="right" type="float" /> - <description> - Multiplies an [int] and a [float]. The result is a [float]. - </description> - </operator> - <operator name="operator *"> <return type="Vector2" /> <argument index="0" name="right" type="Vector2" /> <description> @@ -176,6 +162,20 @@ Multiplies each component of the [Vector3i] by the given [int]. </description> </operator> + <operator name="operator *"> + <return type="float" /> + <argument index="0" name="right" type="float" /> + <description> + Multiplies an [int] and a [float]. The result is a [float]. + </description> + </operator> + <operator name="operator *"> + <return type="int" /> + <argument index="0" name="right" type="int" /> + <description> + Multiplies two [int]s. + </description> + </operator> <operator name="operator +"> <return type="float" /> <argument index="0" name="right" type="float" /> diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index f9443e11db..168080f2f1 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -758,6 +758,10 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener code += a + " - " + n + " * (" + a + " / " + n + "))"; } break; + case SL::OP_EMPTY: { + // Semicolon (or empty statement) - ignored. + } break; + default: { if (p_use_scope) { code += "("; diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index f07c654bd6..dc21d1d8e5 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -307,7 +307,8 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) { if (!err) { return flags.st_mtime; } else { - ERR_FAIL_V_MSG(0, "Failed to get modified time for: " + p_file + "."); + print_verbose("Failed to get modified time for: " + p_file + ""); + return 0; }; } diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index cbc870d385..67ee6ac856 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -102,7 +102,7 @@ public: class UnixTerminalLogger : public StdLogger { public: - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR); + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR) override; virtual ~UnixTerminalLogger(); }; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 035c44a28c..ff81622408 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -335,7 +335,8 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) { if (rv == 0) { return st.st_mtime; } else { - ERR_FAIL_V_MSG(0, "Failed to get modified time for: " + file + "."); + print_verbose("Failed to get modified time for: " + p_file + ""); + return 0; } } diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index bfcd2dd4ca..1f01e9d4cf 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1314,10 +1314,10 @@ void CodeTextEditor::delete_lines() { int count = Math::abs(to_line - from_line) + 1; text_editor->set_caret_line(from_line, false); + text_editor->deselect(); for (int i = 0; i < count; i++) { _delete_line(from_line); } - text_editor->deselect(); } else { _delete_line(text_editor->get_caret_line()); } diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp index e53f66e72e..9346b8f1af 100644 --- a/editor/debugger/editor_debugger_inspector.cpp +++ b/editor/debugger/editor_debugger_inspector.cpp @@ -55,9 +55,14 @@ bool EditorDebuggerRemoteObject::_get(const StringName &p_name, Variant &r_ret) } void EditorDebuggerRemoteObject::_get_property_list(List<PropertyInfo> *p_list) const { - p_list->clear(); //sorry, no want category - for (const PropertyInfo &E : prop_list) { - p_list->push_back(E); + p_list->clear(); // Sorry, no want category. + for (const PropertyInfo &prop : prop_list) { + if (prop.name == "script") { + // Skip the script property, it's always added by the non-virtual method. + continue; + } + + p_list->push_back(prop); } } diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index a163b468e6..6fd8cb47ea 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -893,8 +893,13 @@ bool EditorData::script_class_is_parent(const String &p_class, const String &p_i if (!ScriptServer::is_global_class(p_class)) { return false; } - String base = script_class_get_base(p_class); + Ref<Script> script = script_class_load_script(p_class); + if (script.is_null()) { + return false; + } + + String base = script_class_get_base(p_class); Ref<Script> base_script = script->get_base_script(); while (p_inherits != base) { diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index 5c25e6aae9..7458f617c3 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -497,7 +497,7 @@ void LocalizationEditor::update_translations() { TreeItem *t = translation_filter->create_item(root); t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - t->set_text(0, n); + t->set_text(0, vformat("[%s] %s", l, n)); t->set_editable(0, true); t->set_tooltip(0, l); t->set_checked(0, is_checked); @@ -537,7 +537,7 @@ void LocalizationEditor::update_translations() { if (langnames.length() > 0) { langnames += ","; } - langnames += names[i]; + langnames += vformat("[%s] %s", langs[i], names[i]); translation_locales_idxs_remap.write[l_idx] = i; l_idx++; } @@ -546,7 +546,7 @@ void LocalizationEditor::update_translations() { if (i > 0) { langnames += ","; } - langnames += names[i]; + langnames += vformat("[%s] %s", langs[i], names[i]); } } diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 75d2bed1b2..c4a938f91d 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -945,7 +945,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->move_child(add_node, 0); add_node->get_popup()->connect("id_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_add_node)); - add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu)); + add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu), varray(false)); add_options.push_back(AddOption("Animation", "AnimationNodeAnimation")); add_options.push_back(AddOption("OneShot", "AnimationNodeOneShot", 2)); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index a3378d1550..d9ce7cfd94 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2339,7 +2339,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { if (selection2.size() > 0) { drag_type = DRAG_MOVE; - drag_from = click; + drag_from = drag_start_origin; _save_canvas_item_state(drag_selection); } return true; @@ -5267,7 +5267,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { select_button->set_pressed(true); select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), Key::Q)); select_button->set_shortcut_context(this); - select_button->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("RMB: Add node at position clicked.")); + select_button->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("RMB: Add node at position clicked.")); hb->add_child(memnew(VSeparator)); @@ -5296,7 +5296,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SCALE)); scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), Key::S)); scale_button->set_shortcut_context(this); - scale_button->set_tooltip(TTR("Scale Mode")); + scale_button->set_tooltip(TTR("Shift: Scale proportionally.")); hb->add_child(memnew(VSeparator)); diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index daf34903e6..d99d6709ad 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -460,7 +460,7 @@ void CurveEditor::remove_point(int index) { Curve::Point p = _curve_ref->get_point(index); ur.add_do_method(*_curve_ref, "remove_point", index); - ur.add_undo_method(*_curve_ref, "add_point", p.pos, p.left_tangent, p.right_tangent, p.left_mode, p.right_mode); + ur.add_undo_method(*_curve_ref, "add_point", p.position, p.left_tangent, p.right_tangent, p.left_mode, p.right_mode); if (index == _selected_point) { set_selected_point(-1); diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp index 44c789b145..4b50f484a4 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp @@ -57,6 +57,27 @@ void GPUParticles2DEditorPlugin::_file_selected(const String &p_file) { emission_mask->popup_centered(); } +void GPUParticles2DEditorPlugin::_selection_changed() { + List<Node *> selected_nodes = editor->get_editor_selection()->get_selected_node_list(); + + if (selected_particles.is_empty() && selected_nodes.is_empty()) { + return; + } + + for (GPUParticles2D *SP : selected_particles) { + SP->set_show_visibility_rect(false); + } + selected_particles.clear(); + + for (Node *P : selected_nodes) { + GPUParticles2D *selected_particle = Object::cast_to<GPUParticles2D>(P); + if (selected_particle != nullptr) { + selected_particle->set_show_visibility_rect(true); + selected_particles.push_back(selected_particle); + } + } +} + void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) { switch (p_idx) { case MENU_GENERATE_VISIBILITY_RECT: { @@ -334,6 +355,7 @@ void GPUParticles2DEditorPlugin::_notification(int p_what) { menu->get_popup()->connect("id_pressed", callable_mp(this, &GPUParticles2DEditorPlugin::_menu_callback)); menu->set_icon(menu->get_theme_icon(SNAME("GPUParticles2D"), SNAME("EditorIcons"))); file->connect("file_selected", callable_mp(this, &GPUParticles2DEditorPlugin::_file_selected)); + EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed", callable_mp(this, &GPUParticles2DEditorPlugin::_selection_changed)); } } diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h index 0b2028b745..bdfc021aa7 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.h +++ b/editor/plugins/gpu_particles_2d_editor_plugin.h @@ -56,6 +56,7 @@ class GPUParticles2DEditorPlugin : public EditorPlugin { }; GPUParticles2D *particles; + List<GPUParticles2D *> selected_particles; EditorFileDialog *file; EditorNode *editor; @@ -79,6 +80,7 @@ class GPUParticles2DEditorPlugin : public EditorPlugin { void _menu_callback(int p_idx); void _generate_visibility_rect(); void _generate_emission_mask(); + void _selection_changed(); protected: void _notification(int p_what); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 74fbef3caf..154f9bd6b7 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -2579,7 +2579,7 @@ void CPUParticles3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { GPUParticles3DGizmoPlugin::GPUParticles3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particles", Color(0.8, 0.7, 0.4)); create_material("particles_material", gizmo_color); - gizmo_color.a = 0.1; + gizmo_color.a = MAX((gizmo_color.a - 0.2) * 0.02, 0.0); create_material("particles_solid_material", gizmo_color); create_icon_material("particles_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoGPUParticles3D"), SNAME("EditorIcons"))); create_handle_material("handles"); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index d3b462cda5..0a8cfa3815 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1749,7 +1749,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } else { const bool movement_threshold_passed = _edit.original_mouse_pos.distance_to(_edit.mouse_pos) > 8 * EDSCALE; if (clicked.is_valid() && movement_threshold_passed) { - _compute_edit(_edit.mouse_pos); + _compute_edit(_edit.original_mouse_pos); clicked = ObjectID(); _edit.mode = TRANSFORM_TRANSLATE; diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 5f21c8c881..bb5ef0f6eb 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -964,6 +964,7 @@ void Skeleton3DEditor::select_bone(int p_idx) { Skeleton3DEditor::~Skeleton3DEditor() { if (skeleton) { + select_bone(-1); #ifdef TOOLS_ENABLED skeleton->disconnect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible)); skeleton->disconnect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed)); @@ -973,6 +974,7 @@ Skeleton3DEditor::~Skeleton3DEditor() { #endif handles_mesh_instance->get_parent()->remove_child(handles_mesh_instance); } + edit_mode_toggled(false); handles_mesh_instance->queue_delete(); diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 73b1fc7c67..37d52174f9 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -598,7 +598,10 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p } if (drag_type == DRAG_TYPE_CLIPBOARD_PASTE) { - // Do nothing. + // Cancel tile pasting on right-click + if (mb->get_button_index() == MouseButton::RIGHT) { + drag_type = DRAG_TYPE_NONE; + } } else if (tool_buttons_group->get_pressed_button() == select_tool_button) { drag_start_mouse_pos = mpos; if (tile_map_selection.has(tile_map->world_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed()) { diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 0be1f6d85b..9f8a42eccc 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1233,46 +1233,6 @@ ProjectList::Item ProjectList::load_project_data(const String &p_property_key, b const String main_scene = cf->get_value("application", "run/main_scene", ""); PackedStringArray project_features = cf->get_value("application", "config/features", PackedStringArray()); - bool project_features_dirty = false; - // If there is no feature list currently present, force one to generate. - if (project_features.is_empty()) { - project_features = ProjectSettings::get_required_features(); - project_features_dirty = true; - } - // Check the rendering API. - const String rendering_api = cf->get_value("rendering", "quality/driver/driver_name", ""); - if (rendering_api != "") { - // Add the rendering API as a project feature if it doesn't already exist. - if (!project_features.has(rendering_api)) { - project_features.append(rendering_api); - project_features_dirty = true; - } - } - // Check for the existence of a csproj file. - if (FileAccess::exists(path.plus_file(project_name + ".csproj"))) { - // If there is a csproj file, add the C# feature if it doesn't already exist. - if (!project_features.has("C#")) { - project_features.append("C#"); - project_features_dirty = true; - } - } else { - // If there isn't a csproj file, remove the C# feature if it exists. - if (project_features.has("C#")) { - project_features.remove_at(project_features.find("C#")); - project_features_dirty = true; - } - } - if (project_features_dirty) { - project_features.sort(); - // Write the updated feature list, but only if the project config version is the same. - // Never write to project files with a different config version! - if (config_version == ProjectSettings::CONFIG_VERSION) { - ProjectSettings *ps = ProjectSettings::get_singleton(); - ps->load_custom(conf); - ps->set("application/config/features", project_features); - ps->save_custom(conf); - } - } PackedStringArray unsupported_features = ProjectSettings::get_unsupported_features(project_features); uint64_t last_edited = 0; @@ -1470,7 +1430,7 @@ void ProjectList::create_project_item_control(int p_index) { int length = unsupported_features_str.length(); if (length > 0) { Label *unsupported_label = memnew(Label(unsupported_features_str)); - unsupported_label->set_custom_minimum_size(Size2(length * 15, 10)); + unsupported_label->set_custom_minimum_size(Size2(length * 15, 10) * EDSCALE); unsupported_label->add_theme_font_override("font", get_theme_font(SNAME("title"), SNAME("EditorFonts"))); unsupported_label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); unsupported_label->set_clip_text(true); @@ -2783,7 +2743,7 @@ ProjectManager::ProjectManager() { for (int i = 0; i < editor_languages.size(); i++) { String lang = editor_languages[i]; String lang_name = TranslationServer::get_singleton()->get_locale_name(lang); - language_btn->add_item(lang_name + " [" + lang + "]", i); + language_btn->add_item(vformat("[%s] %s", lang, lang_name), i); language_btn->set_item_metadata(i, lang); if (current_lang == lang) { language_btn->select(i); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 611038a947..cf89120beb 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -419,6 +419,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (!selected_item) { selected_item = tree->get_root(); + if (!selected_item) { + break; + } } bool collapsed = _is_collapsed_recursive(selected_item); @@ -1306,6 +1309,7 @@ void SceneTreeDock::_notification(int p_what) { button_instance->set_icon(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); button_create_script->set_icon(get_theme_icon(SNAME("ScriptCreate"), SNAME("EditorIcons"))); button_detach_script->set_icon(get_theme_icon(SNAME("ScriptRemove"), SNAME("EditorIcons"))); + button_tree_menu->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); button_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons"))); button_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons"))); button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons"))); diff --git a/main/SCsub b/main/SCsub index 87d64e48f9..79dc4bff15 100644 --- a/main/SCsub +++ b/main/SCsub @@ -20,12 +20,13 @@ env_main.CommandNoCache( env.Run(main_builders.make_splash, "Building splash screen header."), ) -env_main.Depends("#main/splash_editor.gen.h", "#main/splash_editor.png") -env_main.CommandNoCache( - "#main/splash_editor.gen.h", - "#main/splash_editor.png", - env.Run(main_builders.make_splash_editor, "Building editor splash screen header."), -) +if not env_main["no_editor_splash"]: + env_main.Depends("#main/splash_editor.gen.h", "#main/splash_editor.png") + env_main.CommandNoCache( + "#main/splash_editor.gen.h", + "#main/splash_editor.png", + env.Run(main_builders.make_splash_editor, "Building editor splash screen header."), + ) env_main.Depends("#main/app_icon.gen.h", "#main/app_icon.png") env_main.CommandNoCache( diff --git a/main/main.cpp b/main/main.cpp index b4fbc1929c..e760c930f2 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -56,7 +56,6 @@ #include "main/main_timer_sync.h" #include "main/performance.h" #include "main/splash.gen.h" -#include "main/splash_editor.gen.h" #include "modules/register_module_types.h" #include "platform/register_platform_apis.h" #include "scene/main/scene_tree.h" @@ -86,6 +85,9 @@ #include "editor/editor_settings.h" #include "editor/progress_dialog.h" #include "editor/project_manager.h" +#ifndef NO_EDITOR_SPLASH +#include "main/splash_editor.gen.h" +#endif #endif #include "modules/modules_enabled.gen.h" // For mono. diff --git a/main/splash_editor.png b/main/splash_editor.png Binary files differdeleted file mode 100644 index 49af9fde22..0000000000 --- a/main/splash_editor.png +++ /dev/null diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 1f962772e7..edb2bcb4c7 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -107,7 +107,14 @@ btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalCo PhysicsDirectSpaceState3D::ShapeResult &result = m_results[count]; - result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is an odd name but contains the compound shape ID + // Triangle index is an odd name but contains the compound shape ID. + // A shape part of -1 indicates the index is a shape index and not a triangle index. + if (convexResult.m_localShapeInfo && convexResult.m_localShapeInfo->m_shapePart == -1) { + result.shape = convexResult.m_localShapeInfo->m_triangleIndex; + } else { + result.shape = 0; + } + result.rid = gObj->get_self(); result.collider_id = gObj->get_instance_id(); result.collider = result.collider_id.is_null() ? nullptr : ObjectDB::get_instance(result.collider_id); @@ -171,11 +178,14 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) } btScalar GodotClosestConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) { - if (convexResult.m_localShapeInfo) { - m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is an odd name but contains the compound shape ID + // Triangle index is an odd name but contains the compound shape ID. + // A shape part of -1 indicates the index is a shape index and not a triangle index. + if (convexResult.m_localShapeInfo && convexResult.m_localShapeInfo->m_shapePart == -1) { + m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; } else { m_shapeId = 0; } + return btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace); } @@ -219,10 +229,22 @@ btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, con CollisionObjectBullet *colObj; if (m_self_object == colObj0Wrap->getCollisionObject()) { colObj = static_cast<CollisionObjectBullet *>(colObj1Wrap->getCollisionObject()->getUserPointer()); - result.shape = cp.m_index1; + // Checking for compound shape because the index might be uninitialized otherwise. + // A partId of -1 indicates the index is a shape index and not a triangle index. + if (colObj1Wrap->getCollisionObject()->getCollisionShape()->isCompound() && cp.m_partId1 == -1) { + result.shape = cp.m_index1; + } else { + result.shape = 0; + } } else { colObj = static_cast<CollisionObjectBullet *>(colObj0Wrap->getCollisionObject()->getUserPointer()); - result.shape = cp.m_index0; + // Checking for compound shape because the index might be uninitialized otherwise. + // A partId of -1 indicates the index is a shape index and not a triangle index. + if (colObj0Wrap->getCollisionObject()->getCollisionShape()->isCompound() && cp.m_partId0 == -1) { + result.shape = cp.m_index0; + } else { + result.shape = 0; + } } result.collider_id = colObj->get_instance_id(); @@ -311,14 +333,26 @@ btScalar GodotRestInfoContactResultCallback::addSingleResult(btManifoldPoint &cp CollisionObjectBullet *colObj; if (m_self_object == colObj0Wrap->getCollisionObject()) { colObj = static_cast<CollisionObjectBullet *>(colObj1Wrap->getCollisionObject()->getUserPointer()); - m_result->shape = cp.m_index1; + // Checking for compound shape because the index might be uninitialized otherwise. + // A partId of -1 indicates the index is a shape index and not a triangle index. + if (colObj1Wrap->getCollisionObject()->getCollisionShape()->isCompound() && cp.m_partId1 == -1) { + m_result->shape = cp.m_index1; + } else { + m_result->shape = 0; + } B_TO_G(cp.getPositionWorldOnB(), m_result->point); B_TO_G(cp.m_normalWorldOnB, m_result->normal); m_rest_info_bt_point = cp.getPositionWorldOnB(); m_rest_info_collision_object = colObj1Wrap->getCollisionObject(); } else { colObj = static_cast<CollisionObjectBullet *>(colObj0Wrap->getCollisionObject()->getUserPointer()); - m_result->shape = cp.m_index0; + // Checking for compound shape because the index might be uninitialized otherwise. + // A partId of -1 indicates the index is a shape index and not a triangle index. + if (colObj0Wrap->getCollisionObject()->getCollisionShape()->isCompound() && cp.m_partId0 == -1) { + m_result->shape = cp.m_index0; + } else { + m_result->shape = 0; + } B_TO_G(cp.m_normalWorldOnB * -1, m_result->normal); m_rest_info_bt_point = cp.getPositionWorldOnA(); m_rest_info_collision_object = colObj0Wrap->getCollisionObject(); diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h index 96a649d77a..3dfa21aec8 100644 --- a/modules/bullet/godot_result_callbacks.h +++ b/modules/bullet/godot_result_callbacks.h @@ -70,8 +70,10 @@ public: virtual bool needsCollision(btBroadphaseProxy *proxy0) const; virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace) { - if (rayResult.m_localShapeInfo) { - m_shapeId = rayResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID + // Triangle index is an odd name but contains the compound shape ID. + // A shape part of -1 indicates the index is a shape index and not a triangle index. + if (rayResult.m_localShapeInfo && rayResult.m_localShapeInfo->m_shapePart == -1) { + m_shapeId = rayResult.m_localShapeInfo->m_triangleIndex; } else { m_shapeId = 0; } diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 9c8adb4cf1..33f4198ac1 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -4,10 +4,10 @@ Built-in GDScript functions. </brief_description> <description> - List of core built-in GDScript functions. Math functions and other utilities. Everything else is provided by objects. (Keywords: builtin, built in, global functions.) + A list of GDScript-specific utility functions accessed in any script. + For the list of the global functions and constants see [@GlobalScope]. </description> <tutorials> - <link title="Random number generation">$DOCS_URL/tutorials/math/random_number_generation.html</link> </tutorials> <methods> <method name="Color8"> diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp index 49e9f5f97e..a9c1f0bb9a 100644 --- a/modules/minimp3/audio_stream_mp3.cpp +++ b/modules/minimp3/audio_stream_mp3.cpp @@ -125,7 +125,7 @@ AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() { Ref<AudioStreamPlayback> AudioStreamMP3::instance_playback() { Ref<AudioStreamPlaybackMP3> mp3s; - ERR_FAIL_COND_V_MSG(data == nullptr, mp3s, + ERR_FAIL_COND_V_MSG(data.is_empty(), mp3s, "This AudioStreamMP3 does not have an audio file assigned " "to it. AudioStreamMP3 should not be created from the " "inspector or with `.new()`. Instead, load an audio file."); @@ -134,7 +134,7 @@ Ref<AudioStreamPlayback> AudioStreamMP3::instance_playback() { mp3s->mp3_stream = Ref<AudioStreamMP3>(this); mp3s->mp3d = (mp3dec_ex_t *)memalloc(sizeof(mp3dec_ex_t)); - int errorcode = mp3dec_ex_open_buf(mp3s->mp3d, (const uint8_t *)data, data_len, MP3D_SEEK_TO_SAMPLE); + int errorcode = mp3dec_ex_open_buf(mp3s->mp3d, data.ptr(), data_len, MP3D_SEEK_TO_SAMPLE); mp3s->frames_mixed = 0; mp3s->active = false; @@ -152,11 +152,7 @@ String AudioStreamMP3::get_stream_name() const { } void AudioStreamMP3::clear_data() { - if (data) { - memfree(data); - data = nullptr; - data_len = 0; - } + data.clear(); } void AudioStreamMP3::set_data(const Vector<uint8_t> &p_data) { @@ -165,7 +161,7 @@ void AudioStreamMP3::set_data(const Vector<uint8_t> &p_data) { mp3dec_ex_t mp3d; int err = mp3dec_ex_open_buf(&mp3d, src_datar, src_data_len, MP3D_SEEK_TO_SAMPLE); - ERR_FAIL_COND(err != 0); + ERR_FAIL_COND_MSG(err || mp3d.info.hz == 0, "Failed to decode mp3 file. Make sure it is a valid mp3 audio file."); channels = mp3d.info.channels; sample_rate = mp3d.info.hz; @@ -175,23 +171,13 @@ void AudioStreamMP3::set_data(const Vector<uint8_t> &p_data) { clear_data(); - data = memalloc(src_data_len); - memcpy(data, src_datar, src_data_len); + data.resize(src_data_len); + memcpy(data.ptrw(), src_datar, src_data_len); data_len = src_data_len; } Vector<uint8_t> AudioStreamMP3::get_data() const { - Vector<uint8_t> vdata; - - if (data_len && data) { - vdata.resize(data_len); - { - uint8_t *w = vdata.ptrw(); - memcpy(w, data, data_len); - } - } - - return vdata; + return data; } void AudioStreamMP3::set_loop(bool p_enable) { diff --git a/modules/minimp3/audio_stream_mp3.h b/modules/minimp3/audio_stream_mp3.h index 3c8bdd8c53..e3adfe683b 100644 --- a/modules/minimp3/audio_stream_mp3.h +++ b/modules/minimp3/audio_stream_mp3.h @@ -75,7 +75,7 @@ class AudioStreamMP3 : public AudioStream { friend class AudioStreamPlaybackMP3; - void *data = nullptr; + PackedByteArray data; uint32_t data_len = 0; float sample_rate = 1.0; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 544f2a7584..0ceb45d425 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -788,11 +788,7 @@ bool CSharpLanguage::is_assembly_reloading_needed() { GDMonoAssembly *proj_assembly = gdmono->get_project_assembly(); - String appname = ProjectSettings::get_singleton()->get("application/config/name"); - String appname_safe = OS::get_singleton()->get_safe_dir_name(appname); - if (appname_safe.is_empty()) { - appname_safe = "UnnamedProject"; - } + String appname_safe = ProjectSettings::get_singleton()->get_safe_project_name(); appname_safe += ".dll"; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 0c3331900a..30ecd22db7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -184,13 +184,13 @@ namespace Godot } /// <summary> - /// Returns the cross product of this vector and <paramref name="b"/>. + /// Returns the cross product of this vector and <paramref name="with"/>. /// </summary> - /// <param name="b">The other vector.</param> + /// <param name="with">The other vector.</param> /// <returns>The cross product value.</returns> - public real_t Cross(Vector2 b) + public real_t Cross(Vector2 with) { - return (x * b.y) - (y * b.x); + return (x * with.y) - (y * with.x); } /// <summary> @@ -222,13 +222,13 @@ namespace Godot } /// <summary> - /// Returns the normalized vector pointing from this vector to <paramref name="b"/>. + /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> - /// <param name="b">The other vector to point towards.</param> - /// <returns>The direction from this vector to <paramref name="b"/>.</returns> - public Vector2 DirectionTo(Vector2 b) + /// <param name="to">The other vector to point towards.</param> + /// <returns>The direction from this vector to <paramref name="to"/>.</returns> + public Vector2 DirectionTo(Vector2 to) { - return new Vector2(b.x - x, b.y - y).Normalized(); + return new Vector2(to.x - x, to.y - y).Normalized(); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index 6cac16d53b..3bbc2ae2ba 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -149,45 +149,45 @@ namespace Godot } /// <summary> - /// Returns the cross product of this vector and <paramref name="b"/>. + /// Returns the cross product of this vector and <paramref name="with"/>. /// </summary> - /// <param name="b">The other vector.</param> + /// <param name="with">The other vector.</param> /// <returns>The cross product vector.</returns> - public int Cross(Vector2i b) + public int Cross(Vector2i with) { - return x * b.y - y * b.x; + return x * with.y - y * with.x; } /// <summary> - /// Returns the squared distance between this vector and <paramref name="b"/>. + /// Returns the squared distance between this vector and <paramref name="to"/>. /// This method runs faster than <see cref="DistanceTo"/>, so prefer it if /// you need to compare vectors or need the squared distance for some formula. /// </summary> - /// <param name="b">The other vector to use.</param> + /// <param name="to">The other vector to use.</param> /// <returns>The squared distance between the two vectors.</returns> - public int DistanceSquaredTo(Vector2i b) + public int DistanceSquaredTo(Vector2i to) { - return (b - this).LengthSquared(); + return (to - this).LengthSquared(); } /// <summary> - /// Returns the distance between this vector and <paramref name="b"/>. + /// Returns the distance between this vector and <paramref name="to"/>. /// </summary> - /// <param name="b">The other vector to use.</param> + /// <param name="to">The other vector to use.</param> /// <returns>The distance between the two vectors.</returns> - public real_t DistanceTo(Vector2i b) + public real_t DistanceTo(Vector2i to) { - return (b - this).Length(); + return (to - this).Length(); } /// <summary> - /// Returns the dot product of this vector and <paramref name="b"/>. + /// Returns the dot product of this vector and <paramref name="with"/>. /// </summary> - /// <param name="b">The other vector to use.</param> + /// <param name="with">The other vector to use.</param> /// <returns>The dot product of the two vectors.</returns> - public int Dot(Vector2i b) + public int Dot(Vector2i with) { - return x * b.x + y * b.y; + return x * with.x + y * with.y; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 63d9be0a6d..15acf88f62 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -170,17 +170,17 @@ namespace Godot } /// <summary> - /// Returns the cross product of this vector and <paramref name="b"/>. + /// Returns the cross product of this vector and <paramref name="with"/>. /// </summary> - /// <param name="b">The other vector.</param> + /// <param name="with">The other vector.</param> /// <returns>The cross product vector.</returns> - public Vector3 Cross(Vector3 b) + public Vector3 Cross(Vector3 with) { return new Vector3 ( - (y * b.z) - (z * b.y), - (z * b.x) - (x * b.z), - (x * b.y) - (y * b.x) + (y * with.z) - (z * with.y), + (z * with.x) - (x * with.z), + (x * with.y) - (y * with.x) ); } @@ -212,46 +212,46 @@ namespace Godot } /// <summary> - /// Returns the normalized vector pointing from this vector to <paramref name="b"/>. + /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> - /// <param name="b">The other vector to point towards.</param> - /// <returns>The direction from this vector to <paramref name="b"/>.</returns> - public Vector3 DirectionTo(Vector3 b) + /// <param name="to">The other vector to point towards.</param> + /// <returns>The direction from this vector to <paramref name="to"/>.</returns> + public Vector3 DirectionTo(Vector3 to) { - return new Vector3(b.x - x, b.y - y, b.z - z).Normalized(); + return new Vector3(to.x - x, to.y - y, to.z - z).Normalized(); } /// <summary> - /// Returns the squared distance between this vector and <paramref name="b"/>. + /// Returns the squared distance between this vector and <paramref name="to"/>. /// This method runs faster than <see cref="DistanceTo"/>, so prefer it if /// you need to compare vectors or need the squared distance for some formula. /// </summary> - /// <param name="b">The other vector to use.</param> + /// <param name="to">The other vector to use.</param> /// <returns>The squared distance between the two vectors.</returns> - public real_t DistanceSquaredTo(Vector3 b) + public real_t DistanceSquaredTo(Vector3 to) { - return (b - this).LengthSquared(); + return (to - this).LengthSquared(); } /// <summary> - /// Returns the distance between this vector and <paramref name="b"/>. + /// Returns the distance between this vector and <paramref name="to"/>. /// </summary> /// <seealso cref="DistanceSquaredTo(Vector3)"/> - /// <param name="b">The other vector to use.</param> + /// <param name="to">The other vector to use.</param> /// <returns>The distance between the two vectors.</returns> - public real_t DistanceTo(Vector3 b) + public real_t DistanceTo(Vector3 to) { - return (b - this).Length(); + return (to - this).Length(); } /// <summary> - /// Returns the dot product of this vector and <paramref name="b"/>. + /// Returns the dot product of this vector and <paramref name="with"/>. /// </summary> - /// <param name="b">The other vector to use.</param> + /// <param name="with">The other vector to use.</param> /// <returns>The dot product of the two vectors.</returns> - public real_t Dot(Vector3 b) + public real_t Dot(Vector3 with) { - return (x * b.x) + (y * b.y) + (z * b.z); + return (x * with.x) + (y * with.y) + (z * with.z); } /// <summary> @@ -412,16 +412,16 @@ namespace Godot } /// <summary> - /// Returns the outer product with <paramref name="b"/>. + /// Returns the outer product with <paramref name="with"/>. /// </summary> - /// <param name="b">The other vector.</param> + /// <param name="with">The other vector.</param> /// <returns>A <see cref="Basis"/> representing the outer product matrix.</returns> - public Basis Outer(Vector3 b) + public Basis Outer(Vector3 with) { return new Basis( - x * b.x, x * b.y, x * b.z, - y * b.x, y * b.y, y * b.z, - z * b.x, z * b.y, z * b.z + x * with.x, x * with.y, x * with.z, + y * with.x, y * with.y, y * with.z, + z * with.x, z * with.y, z * with.z ); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index 474876fc91..562f653fa8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -124,36 +124,36 @@ namespace Godot } /// <summary> - /// Returns the squared distance between this vector and <paramref name="b"/>. + /// Returns the squared distance between this vector and <paramref name="to"/>. /// This method runs faster than <see cref="DistanceTo"/>, so prefer it if /// you need to compare vectors or need the squared distance for some formula. /// </summary> - /// <param name="b">The other vector to use.</param> + /// <param name="to">The other vector to use.</param> /// <returns>The squared distance between the two vectors.</returns> - public int DistanceSquaredTo(Vector3i b) + public int DistanceSquaredTo(Vector3i to) { - return (b - this).LengthSquared(); + return (to - this).LengthSquared(); } /// <summary> - /// Returns the distance between this vector and <paramref name="b"/>. + /// Returns the distance between this vector and <paramref name="to"/>. /// </summary> /// <seealso cref="DistanceSquaredTo(Vector3i)"/> - /// <param name="b">The other vector to use.</param> + /// <param name="to">The other vector to use.</param> /// <returns>The distance between the two vectors.</returns> - public real_t DistanceTo(Vector3i b) + public real_t DistanceTo(Vector3i to) { - return (b - this).Length(); + return (to - this).Length(); } /// <summary> - /// Returns the dot product of this vector and <paramref name="b"/>. + /// Returns the dot product of this vector and <paramref name="with"/>. /// </summary> - /// <param name="b">The other vector to use.</param> + /// <param name="with">The other vector to use.</param> /// <returns>The dot product of the two vectors.</returns> - public int Dot(Vector3i b) + public int Dot(Vector3i with) { - return x * b.x + y * b.y + z * b.z; + return x * with.x + y * with.y + z * with.z; } /// <summary> diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index fa9e6eed15..8d9ba82fd4 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -28,11 +28,11 @@ if env["javascript_eval"]: sys_env.AddJSLibraries(["js/libs/library_godot_javascript_singleton.js"]) for lib in sys_env["JS_LIBS"]: - sys_env.Append(LINKFLAGS=["--js-library", lib]) + sys_env.Append(LINKFLAGS=["--js-library", lib.abspath]) for js in env["JS_PRE"]: - sys_env.Append(LINKFLAGS=["--pre-js", env.File(js).path]) + sys_env.Append(LINKFLAGS=["--pre-js", js.abspath]) for ext in env["JS_EXTERNS"]: - sys_env["ENV"]["EMCC_CLOSURE_ARGS"] += " --externs " + ext.path + sys_env["ENV"]["EMCC_CLOSURE_ARGS"] += " --externs " + ext.abspath build = [] if env["gdnative_enabled"]: diff --git a/platform/javascript/js/libs/library_godot_input.js b/platform/javascript/js/libs/library_godot_input.js index d85d0d5335..945dbba902 100644 --- a/platform/javascript/js/libs/library_godot_input.js +++ b/platform/javascript/js/libs/library_godot_input.js @@ -393,7 +393,9 @@ const GodotInput = { const rect = canvas.getBoundingClientRect(); const pos = GodotInput.computePosition(evt, rect); const modifiers = GodotInput.getModifiers(evt); - if (p_pressed && document.activeElement !== GodotConfig.canvas) { + // Since the event is consumed, focus manually. + // NOTE: The iframe container may not have focus yet, so focus even when already active. + if (p_pressed) { GodotConfig.canvas.focus(); } if (func(p_pressed, evt.button, pos[0], pos[1], modifiers)) { @@ -412,7 +414,9 @@ const GodotInput = { const func = GodotRuntime.get_func(callback); const canvas = GodotConfig.canvas; function touch_cb(type, evt) { - if (type === 0 && document.activeElement !== GodotConfig.canvas) { + // Since the event is consumed, focus manually. + // NOTE: The iframe container may not have focus yet, so focus even when already active. + if (type === 0) { GodotConfig.canvas.focus(); } const rect = canvas.getBoundingClientRect(); @@ -420,9 +424,9 @@ const GodotInput = { for (let i = 0; i < touches.length; i++) { const touch = touches[i]; const pos = GodotInput.computePosition(touch, rect); - GodotRuntime.setHeapValue(coords + (i * 2), pos[0], 'double'); - GodotRuntime.setHeapValue(coords + (i * 2 + 8), pos[1], 'double'); - GodotRuntime.setHeapValue(ids + i, touch.identifier, 'i32'); + GodotRuntime.setHeapValue(coords + (i * 2) * 8, pos[0], 'double'); + GodotRuntime.setHeapValue(coords + (i * 2 + 1) * 8, pos[1], 'double'); + GodotRuntime.setHeapValue(ids + i * 4, touch.identifier, 'i32'); } func(type, touches.length); if (evt.cancelable) { diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 45a81be80a..39608bdea8 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -178,7 +178,7 @@ class OSXTerminalLogger : public StdLogger { public: - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR) { + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR) { if (!should_log(true)) { return; } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index d8d4e92d9d..6a0a4790fc 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -447,7 +447,12 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, ZeroMemory(&pi.pi, sizeof(pi.pi)); LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; - int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi); + DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS; +#ifndef DEBUG_ENABLED + dwCreationFlags |= CREATE_NO_WINDOW; +#endif + + int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, dwCreationFlags, nullptr, nullptr, si_w, &pi.pi); ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); WaitForSingleObject(pi.pi.hProcess, INFINITE); @@ -475,7 +480,12 @@ Error OS_Windows::create_process(const String &p_path, const List<String> &p_arg ZeroMemory(&pi.pi, sizeof(pi.pi)); LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; - int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi); + DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS; +#ifndef DEBUG_ENABLED + dwCreationFlags |= CREATE_NO_WINDOW; +#endif + + int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, dwCreationFlags, nullptr, nullptr, si_w, &pi.pi); ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); ProcessID pid = pi.pi.dwProcessId; diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp index e54a61fdfd..d4148630f0 100644 --- a/platform/windows/windows_terminal_logger.cpp +++ b/platform/windows/windows_terminal_logger.cpp @@ -71,7 +71,7 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er #endif } -void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) { +void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) { if (!should_log(true)) { return; } diff --git a/platform/windows/windows_terminal_logger.h b/platform/windows/windows_terminal_logger.h index aacfe5869e..86b65ae30a 100644 --- a/platform/windows/windows_terminal_logger.h +++ b/platform/windows/windows_terminal_logger.h @@ -37,8 +37,8 @@ class WindowsTerminalLogger : public StdLogger { public: - virtual void logv(const char *p_format, va_list p_list, bool p_err); - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); + virtual void logv(const char *p_format, va_list p_list, bool p_err) override; + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR) override; virtual ~WindowsTerminalLogger(); }; diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index bf5671be19..b6902686fe 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -176,7 +176,7 @@ Transform2D Camera2D::get_camera_transform() { Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom); - if (!limit_smoothing_enabled) { + if (!smoothing_enabled || !limit_smoothing_enabled) { if (screen_rect.position.x < limit[SIDE_LEFT]) { screen_rect.position.x = limit[SIDE_LEFT]; } diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index f1f4d1b769..4384ec8141 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -170,6 +170,13 @@ void GPUParticles2D::set_trail_section_subdivisions(int p_subdivisions) { update(); } +#ifdef TOOLS_ENABLED +void GPUParticles2D::set_show_visibility_rect(bool p_show_visibility_rect) { + show_visibility_rect = p_show_visibility_rect; + update(); +} +#endif + bool GPUParticles2D::is_trail_enabled() const { return trail_enabled; } @@ -452,7 +459,7 @@ void GPUParticles2D::_notification(int p_what) { RS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid); #ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && (this == get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) { + if (show_visibility_rect) { draw_rect(visibility_rect, Color(0, 0.7, 0.9, 0.4), false); } #endif @@ -588,6 +595,9 @@ GPUParticles2D::GPUParticles2D() { set_speed_scale(1); set_fixed_fps(30); set_collision_base_size(collision_base_size); +#ifdef TOOLS_ENABLED + show_visibility_rect = false; +#endif } GPUParticles2D::~GPUParticles2D() { diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index d7eee461b4..a9e66b3051 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -58,7 +58,9 @@ private: bool local_coords; int fixed_fps; bool fractional_delta; - +#ifdef TOOLS_ENABLED + bool show_visibility_rect; +#endif Ref<Material> process_material; DrawOrder draw_order; @@ -81,7 +83,6 @@ protected: static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const override; void _notification(int p_what); - void _update_collision_size(); public: @@ -102,6 +103,10 @@ public: void set_trail_sections(int p_sections); void set_trail_section_subdivisions(int p_subdivisions); +#ifdef TOOLS_ENABLED + void set_show_visibility_rect(bool p_show_visibility_rect); +#endif + bool is_emitting() const; int get_amount() const; double get_lifetime() const; diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index ed30e871d7..40211f2a9b 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -100,16 +100,18 @@ void Path2D::_notification(int p_what) { #endif const Color color = Color(0.5, 0.6, 1.0, 0.7); - for (int i = 0; i < curve->get_point_count(); i++) { - Vector2 prev_p = curve->get_point_position(i); + _cached_draw_pts.resize(curve->get_point_count() * 8); + int count = 0; - for (int j = 1; j <= 8; j++) { - real_t frac = j / 8.0; + for (int i = 0; i < curve->get_point_count(); i++) { + for (int j = 0; j < 8; j++) { + real_t frac = j * (1.0 / 8.0); Vector2 p = curve->interpolate(i, frac); - draw_line(prev_p, p, color, line_width); - prev_p = p; + _cached_draw_pts.set(count++, p); } } + + draw_polyline(_cached_draw_pts, color, line_width, true); } } diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 3b12f025fc..7e8478283f 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -38,6 +38,7 @@ class Path2D : public Node2D { GDCLASS(Path2D, Node2D); Ref<Curve2D> curve; + Vector<Vector2> _cached_draw_pts; void _curve_changed(); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index ea04918988..1b07c086c0 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -198,7 +198,7 @@ private: struct PlaybackData { AnimationData *from = nullptr; - float pos = 0.0; + double pos = 0.0; float speed_scale = 1.0; }; diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 3c8949ddfb..56c04b32e3 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -367,7 +367,7 @@ void SceneDebuggerObject::serialize(Array &r_arr, int p_max_size) { PropertyHint hint = pi.hint; String hint_string = pi.hint_string; - if (!res.is_null()) { + if (!res.is_null() && !res->get_path().is_empty()) { var = res->get_path(); } else { //only send information that can be sent.. int len = 0; //test how big is this to encode diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 57de75a71d..a8c5966569 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -1419,40 +1419,23 @@ void CodeEdit::fold_line(int p_line) { /* End line is the same therefore we have a block of single line delimiters. */ if (end_line == p_line) { for (int i = p_line + 1; i <= line_count; i++) { - if (i == line_count) { - end_line = line_count; - break; - } - if ((in_string != -1 && is_in_string(i) == -1) || (in_comment != -1 && is_in_comment(i) == -1)) { - end_line = i - 1; break; } + end_line = i; } } } else { int start_indent = get_indent_level(p_line); for (int i = p_line + 1; i <= line_count; i++) { - if (get_line(p_line).strip_edges().size() == 0 || is_in_string(i) != -1 || is_in_comment(i) != -1) { - end_line = i; + if (get_line(i).strip_edges().size() == 0) { continue; } - - if (i == line_count) { - /* Do not fold empty last line of script if any */ + if (get_indent_level(i) > start_indent) { end_line = i; - if (get_line(i).strip_edges().size() == 0) { - end_line--; - } - break; + continue; } - - if ((get_indent_level(i) <= start_indent && get_line(i).strip_edges().size() != 0)) { - /* Keep an empty line unfolded if any */ - end_line = i - 1; - if (get_line(i - 1).strip_edges().size() == 0 && i - 2 > p_line) { - end_line = i - 2; - } + if (is_in_string(i) == -1 && is_in_comment(i) == -1) { break; } } diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index 57ee7fd494..c7d5a600a1 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -164,7 +164,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (rb_hover != -1) { - // pressed + // Right mouse button clicked. emit_signal(SNAME("tab_rmb_clicked"), rb_hover); } @@ -174,7 +174,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (cb_hover != -1) { - // pressed + // Close button pressed. emit_signal(SNAME("tab_close_pressed"), cb_hover); } @@ -183,7 +183,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { } if (mb->is_pressed() && (mb->get_button_index() == MouseButton::LEFT || (select_with_rmb && mb->get_button_index() == MouseButton::RIGHT))) { - // clicks + // Clicks. Point2 pos = mb->get_position(); if (buttons_visible) { @@ -235,7 +235,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { return; } - if (tabs[i].cb_rect.has_point(pos)) { + if (tabs[i].cb_rect.has_point(pos) && (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current))) { cb_pressing = true; update(); return; @@ -659,7 +659,7 @@ void TabBar::_update_hover() { } const Point2 &pos = get_local_mouse_position(); - // test hovering to display right or close button + // test hovering to display right or close button. int hover_now = -1; int hover_buttons = -1; for (int i = offset; i < tabs.size(); i++) { @@ -684,7 +684,7 @@ void TabBar::_update_hover() { emit_signal(SNAME("tab_hovered"), hover); } - if (hover_buttons == -1) { // no hover + if (hover_buttons == -1) { // No hover. rb_hover = hover_buttons; cb_hover = hover_buttons; } @@ -860,7 +860,7 @@ bool TabBar::can_drop_data(const Point2 &p_point, const Variant &p_data) const { if (from_path == to_path) { return true; } else if (get_tabs_rearrange_group() != -1) { - // drag and drop between other TabBars + // Drag and drop between other TabBars. Node *from_node = get_node(from_path); TabBar *from_tabs = Object::cast_to<TabBar>(from_node); if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) { @@ -895,7 +895,7 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) { emit_signal(SNAME("active_tab_rearranged"), hover_now); set_current_tab(hover_now); } else if (get_tabs_rearrange_group() != -1) { - // drag and drop between Tabs + // Drag and drop between Tabs. Node *from_node = get_node(from_path); TabBar *from_tabs = Object::cast_to<TabBar>(from_node); if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) { diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp index fe11de128a..3c10c6bd66 100644 --- a/scene/gui/texture_progress_bar.cpp +++ b/scene/gui/texture_progress_bar.cpp @@ -387,7 +387,6 @@ void TextureProgressBar::draw_nine_patch_stretched(const Ref<Texture2D> &p_textu } void TextureProgressBar::_notification(int p_what) { - const float corners[12] = { -0.125, -0.375, -0.625, -0.875, 0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875 }; switch (p_what) { case NOTIFICATION_DRAW: { if (nine_patch_stretch && (mode == FILL_LEFT_TO_RIGHT || mode == FILL_RIGHT_TO_LEFT || mode == FILL_TOP_TO_BOTTOM || mode == FILL_BOTTOM_TO_TOP || mode == FILL_BILINEAR_LEFT_AND_RIGHT || mode == FILL_BILINEAR_TOP_AND_BOTTOM)) { @@ -452,7 +451,7 @@ void TextureProgressBar::_notification(int p_what) { float val = get_as_ratio() * rad_max_degrees / 360; if (val == 1) { Rect2 region = Rect2(progress_offset, s); - Rect2 source = Rect2(Point2(), s); + Rect2 source = Rect2(Point2(), progress->get_size()); draw_texture_rect_region(progress, region, source, tint_progress); } else if (val != 0) { Array pts; @@ -466,16 +465,14 @@ void TextureProgressBar::_notification(int p_what) { } float end = start + direction * val; - pts.append(start); - pts.append(end); float from = MIN(start, end); float to = MAX(start, end); - for (int i = 0; i < 12; i++) { - if (corners[i] > from && corners[i] < to) { - pts.append(corners[i]); - } + pts.append(from); + for (float corner = Math::floor(from * 4 + 0.5) * 0.25 + 0.125; corner < to; corner += 0.25) { + pts.append(corner); } - pts.sort(); + pts.append(to); + Vector<Point2> uvs; Vector<Point2> points; uvs.push_back(get_relative_center()); @@ -492,6 +489,8 @@ void TextureProgressBar::_notification(int p_what) { colors.push_back(tint_progress); draw_polygon(points, colors, uvs, progress); } + + // Draw a reference cross. if (Engine::get_singleton()->is_editor_hint()) { Point2 p; @@ -502,6 +501,7 @@ void TextureProgressBar::_notification(int p_what) { } p *= get_relative_center(); + p += progress_offset; p = p.floor(); draw_line(p - Point2(8, 0), p + Point2(8, 0), Color(0.9, 0.5, 0.5), 2); draw_line(p - Point2(0, 8), p + Point2(0, 8), Color(0.9, 0.5, 0.5), 2); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 5e004d6863..0d646ff2a9 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -114,7 +114,7 @@ void Node::_notification(int p_notification) { get_multiplayer()->scene_enter_exit_notify(data.scene_file_path, this, false); } } break; - case NOTIFICATION_PATH_CHANGED: { + case NOTIFICATION_PATH_RENAMED: { if (data.path_cache) { memdelete(data.path_cache); data.path_cache = nullptr; @@ -899,7 +899,7 @@ void Node::set_name(const String &p_name) { data.parent->_validate_child_name(this); } - propagate_notification(NOTIFICATION_PATH_CHANGED); + propagate_notification(NOTIFICATION_PATH_RENAMED); if (is_inside_tree()) { emit_signal(SNAME("renamed")); @@ -2829,7 +2829,7 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_INSTANCED); BIND_CONSTANT(NOTIFICATION_DRAG_BEGIN); BIND_CONSTANT(NOTIFICATION_DRAG_END); - BIND_CONSTANT(NOTIFICATION_PATH_CHANGED); + BIND_CONSTANT(NOTIFICATION_PATH_RENAMED); BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS); BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE); diff --git a/scene/main/node.h b/scene/main/node.h index 2dd32a2e1d..dc74a33580 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -256,7 +256,7 @@ public: NOTIFICATION_INSTANCED = 20, NOTIFICATION_DRAG_BEGIN = 21, NOTIFICATION_DRAG_END = 22, - NOTIFICATION_PATH_CHANGED = 23, + NOTIFICATION_PATH_RENAMED = 23, //NOTIFICATION_TRANSLATION_CHANGED = 24, moved below NOTIFICATION_INTERNAL_PROCESS = 25, NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26, diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index f9e96a0784..3ac1a0eaf0 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -396,14 +396,15 @@ void Viewport::_notification(int p_what) { #ifndef _3D_DISABLED PhysicsServer3D::get_singleton()->space_set_debug_contacts(find_world_3d()->get_space(), get_tree()->get_collision_debug_contact_count()); contact_3d_debug_multimesh = RenderingServer::get_singleton()->multimesh_create(); - RenderingServer::get_singleton()->multimesh_allocate_data(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, true); + RenderingServer::get_singleton()->multimesh_allocate_data(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, false); RenderingServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0); RenderingServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid()); contact_3d_debug_instance = RenderingServer::get_singleton()->instance_create(); RenderingServer::get_singleton()->instance_set_base(contact_3d_debug_instance, contact_3d_debug_multimesh); RenderingServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance, find_world_3d()->get_scenario()); - //RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true); + RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true); #endif // _3D_DISABLED + set_physics_process_internal(true); } } break; @@ -1707,12 +1708,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (mm->get_button_mask() == MouseButton::NONE) { // Nothing pressed. - bool can_tooltip = true; - bool is_tooltip_shown = false; if (gui.tooltip_popup) { - if (can_tooltip && gui.tooltip_control) { + if (gui.tooltip_control) { String tooltip = _gui_get_tooltip(over, gui.tooltip_control->get_global_transform().xform_inv(mpos)); if (tooltip.length() == 0) { @@ -1737,7 +1736,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } } - if (can_tooltip && !is_tooltip_shown) { + if (!is_tooltip_shown && over->can_process()) { if (gui.tooltip_timer.is_valid()) { gui.tooltip_timer->release_connections(); gui.tooltip_timer = Ref<SceneTreeTimer>(); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index b87639de6a..bf3efd7599 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -33,15 +33,15 @@ #include "core/core_string_names.h" template <class T> -static _FORCE_INLINE_ T _bezier_interp(real_t t, T start, T control_1, T control_2, T end) { +static _FORCE_INLINE_ T _bezier_interp(real_t p_t, T p_start, T p_control_1, T p_control_2, T p_end) { /* Formula from Wikipedia article on Bezier curves. */ - real_t omt = (1.0 - t); + real_t omt = (1.0 - p_t); real_t omt2 = omt * omt; real_t omt3 = omt2 * omt; - real_t t2 = t * t; - real_t t3 = t2 * t; + real_t t2 = p_t * p_t; + real_t t3 = t2 * p_t; - return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3; + return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3; } const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed"; @@ -49,46 +49,46 @@ const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed"; Curve::Curve() { } -int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, TangentMode left_mode, TangentMode right_mode) { +int Curve::add_point(Vector2 p_position, real_t p_left_tangent, real_t p_right_tangent, TangentMode p_left_mode, TangentMode p_right_mode) { // Add a point and preserve order // Curve bounds is in 0..1 - if (p_pos.x > MAX_X) { - p_pos.x = MAX_X; - } else if (p_pos.x < MIN_X) { - p_pos.x = MIN_X; + if (p_position.x > MAX_X) { + p_position.x = MAX_X; + } else if (p_position.x < MIN_X) { + p_position.x = MIN_X; } int ret = -1; if (_points.size() == 0) { - _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + _points.push_back(Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode)); ret = 0; } else if (_points.size() == 1) { // TODO Is the `else` able to handle this block already? - real_t diff = p_pos.x - _points[0].pos.x; + real_t diff = p_position.x - _points[0].position.x; if (diff > 0) { - _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + _points.push_back(Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode)); ret = 1; } else { - _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + _points.insert(0, Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode)); ret = 0; } } else { - int i = get_index(p_pos.x); + int i = get_index(p_position.x); - if (i == 0 && p_pos.x < _points[0].pos.x) { + if (i == 0 && p_position.x < _points[0].position.x) { // Insert before anything else - _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + _points.insert(0, Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode)); ret = 0; } else { // Insert between i and i+1 ++i; - _points.insert(i, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); + _points.insert(i, Point(p_position, p_left_tangent, p_right_tangent, p_left_mode, p_right_mode)); ret = i; } } @@ -100,7 +100,7 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, T return ret; } -int Curve::get_index(real_t offset) const { +int Curve::get_index(real_t p_offset) const { // Lower-bound float binary search int imin = 0; @@ -109,13 +109,13 @@ int Curve::get_index(real_t offset) const { while (imax - imin > 1) { int m = (imin + imax) / 2; - real_t a = _points[m].pos.x; - real_t b = _points[m + 1].pos.x; + real_t a = _points[m].position.x; + real_t b = _points[m + 1].position.x; - if (a < offset && b < offset) { + if (a < p_offset && b < p_offset) { imin = m; - } else if (a > offset) { + } else if (a > p_offset) { imax = m; } else { @@ -124,7 +124,7 @@ int Curve::get_index(real_t offset) const { } // Will happen if the offset is out of bounds - if (offset > _points[imax].pos.x) { + if (p_offset > _points[imax].position.x) { return imax; } return imin; @@ -134,7 +134,7 @@ void Curve::clean_dupes() { bool dirty = false; for (int i = 1; i < _points.size(); ++i) { - real_t diff = _points[i - 1].pos.x - _points[i].pos.x; + real_t diff = _points[i - 1].position.x - _points[i].position.x; if (diff <= CMP_EPSILON) { _points.remove_at(i); --i; @@ -147,62 +147,62 @@ void Curve::clean_dupes() { } } -void Curve::set_point_left_tangent(int i, real_t tangent) { - ERR_FAIL_INDEX(i, _points.size()); - _points.write[i].left_tangent = tangent; - _points.write[i].left_mode = TANGENT_FREE; +void Curve::set_point_left_tangent(int p_index, real_t p_tangent) { + ERR_FAIL_INDEX(p_index, _points.size()); + _points.write[p_index].left_tangent = p_tangent; + _points.write[p_index].left_mode = TANGENT_FREE; mark_dirty(); } -void Curve::set_point_right_tangent(int i, real_t tangent) { - ERR_FAIL_INDEX(i, _points.size()); - _points.write[i].right_tangent = tangent; - _points.write[i].right_mode = TANGENT_FREE; +void Curve::set_point_right_tangent(int p_index, real_t p_tangent) { + ERR_FAIL_INDEX(p_index, _points.size()); + _points.write[p_index].right_tangent = p_tangent; + _points.write[p_index].right_mode = TANGENT_FREE; mark_dirty(); } -void Curve::set_point_left_mode(int i, TangentMode p_mode) { - ERR_FAIL_INDEX(i, _points.size()); - _points.write[i].left_mode = p_mode; - if (i > 0) { +void Curve::set_point_left_mode(int p_index, TangentMode p_mode) { + ERR_FAIL_INDEX(p_index, _points.size()); + _points.write[p_index].left_mode = p_mode; + if (p_index > 0) { if (p_mode == TANGENT_LINEAR) { - Vector2 v = (_points[i - 1].pos - _points[i].pos).normalized(); - _points.write[i].left_tangent = v.y / v.x; + Vector2 v = (_points[p_index - 1].position - _points[p_index].position).normalized(); + _points.write[p_index].left_tangent = v.y / v.x; } } mark_dirty(); } -void Curve::set_point_right_mode(int i, TangentMode p_mode) { - ERR_FAIL_INDEX(i, _points.size()); - _points.write[i].right_mode = p_mode; - if (i + 1 < _points.size()) { +void Curve::set_point_right_mode(int p_index, TangentMode p_mode) { + ERR_FAIL_INDEX(p_index, _points.size()); + _points.write[p_index].right_mode = p_mode; + if (p_index + 1 < _points.size()) { if (p_mode == TANGENT_LINEAR) { - Vector2 v = (_points[i + 1].pos - _points[i].pos).normalized(); - _points.write[i].right_tangent = v.y / v.x; + Vector2 v = (_points[p_index + 1].position - _points[p_index].position).normalized(); + _points.write[p_index].right_tangent = v.y / v.x; } } mark_dirty(); } -real_t Curve::get_point_left_tangent(int i) const { - ERR_FAIL_INDEX_V(i, _points.size(), 0); - return _points[i].left_tangent; +real_t Curve::get_point_left_tangent(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), 0); + return _points[p_index].left_tangent; } -real_t Curve::get_point_right_tangent(int i) const { - ERR_FAIL_INDEX_V(i, _points.size(), 0); - return _points[i].right_tangent; +real_t Curve::get_point_right_tangent(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), 0); + return _points[p_index].right_tangent; } -Curve::TangentMode Curve::get_point_left_mode(int i) const { - ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE); - return _points[i].left_mode; +Curve::TangentMode Curve::get_point_left_mode(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), TANGENT_FREE); + return _points[p_index].left_mode; } -Curve::TangentMode Curve::get_point_right_mode(int i) const { - ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE); - return _points[i].right_mode; +Curve::TangentMode Curve::get_point_right_mode(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), TANGENT_FREE); + return _points[p_index].right_mode; } void Curve::remove_point(int p_index) { @@ -216,18 +216,18 @@ void Curve::clear_points() { mark_dirty(); } -void Curve::set_point_value(int p_index, real_t pos) { +void Curve::set_point_value(int p_index, real_t p_position) { ERR_FAIL_INDEX(p_index, _points.size()); - _points.write[p_index].pos.y = pos; + _points.write[p_index].position.y = p_position; update_auto_tangents(p_index); mark_dirty(); } -int Curve::set_point_offset(int p_index, float offset) { +int Curve::set_point_offset(int p_index, real_t p_offset) { ERR_FAIL_INDEX_V(p_index, _points.size(), -1); Point p = _points[p_index]; remove_point(p_index); - int i = add_point(Vector2(offset, p.pos.y)); + int i = add_point(Vector2(p_offset, p.position.y)); _points.write[i].left_tangent = p.left_tangent; _points.write[i].right_tangent = p.right_tangent; _points.write[i].left_mode = p.left_mode; @@ -241,7 +241,7 @@ int Curve::set_point_offset(int p_index, float offset) { Vector2 Curve::get_point_position(int p_index) const { ERR_FAIL_INDEX_V(p_index, _points.size(), Vector2(0, 0)); - return _points[p_index].pos; + return _points[p_index].position; } Curve::Point Curve::get_point(int p_index) const { @@ -249,35 +249,35 @@ Curve::Point Curve::get_point(int p_index) const { return _points[p_index]; } -void Curve::update_auto_tangents(int i) { - Point &p = _points.write[i]; +void Curve::update_auto_tangents(int p_index) { + Point &p = _points.write[p_index]; - if (i > 0) { + if (p_index > 0) { if (p.left_mode == TANGENT_LINEAR) { - Vector2 v = (_points[i - 1].pos - p.pos).normalized(); + Vector2 v = (_points[p_index - 1].position - p.position).normalized(); p.left_tangent = v.y / v.x; } - if (_points[i - 1].right_mode == TANGENT_LINEAR) { - Vector2 v = (_points[i - 1].pos - p.pos).normalized(); - _points.write[i - 1].right_tangent = v.y / v.x; + if (_points[p_index - 1].right_mode == TANGENT_LINEAR) { + Vector2 v = (_points[p_index - 1].position - p.position).normalized(); + _points.write[p_index - 1].right_tangent = v.y / v.x; } } - if (i + 1 < _points.size()) { + if (p_index + 1 < _points.size()) { if (p.right_mode == TANGENT_LINEAR) { - Vector2 v = (_points[i + 1].pos - p.pos).normalized(); + Vector2 v = (_points[p_index + 1].position - p.position).normalized(); p.right_tangent = v.y / v.x; } - if (_points[i + 1].left_mode == TANGENT_LINEAR) { - Vector2 v = (_points[i + 1].pos - p.pos).normalized(); - _points.write[i + 1].left_tangent = v.y / v.x; + if (_points[p_index + 1].left_mode == TANGENT_LINEAR) { + Vector2 v = (_points[p_index + 1].position - p.position).normalized(); + _points.write[p_index + 1].left_tangent = v.y / v.x; } } } #define MIN_Y_RANGE 0.01 -void Curve::set_min_value(float p_min) { +void Curve::set_min_value(real_t p_min) { if (_minmax_set_once & 0b11 && p_min > _max_value - MIN_Y_RANGE) { _min_value = _max_value - MIN_Y_RANGE; } else { @@ -289,7 +289,7 @@ void Curve::set_min_value(float p_min) { emit_signal(SNAME(SIGNAL_RANGE_CHANGED)); } -void Curve::set_max_value(float p_max) { +void Curve::set_max_value(real_t p_max) { if (_minmax_set_once & 0b11 && p_max < _min_value + MIN_Y_RANGE) { _max_value = _min_value + MIN_Y_RANGE; } else { @@ -299,32 +299,32 @@ void Curve::set_max_value(float p_max) { emit_signal(SNAME(SIGNAL_RANGE_CHANGED)); } -real_t Curve::interpolate(real_t offset) const { +real_t Curve::interpolate(real_t p_offset) const { if (_points.size() == 0) { return 0; } if (_points.size() == 1) { - return _points[0].pos.y; + return _points[0].position.y; } - int i = get_index(offset); + int i = get_index(p_offset); if (i == _points.size() - 1) { - return _points[i].pos.y; + return _points[i].position.y; } - real_t local = offset - _points[i].pos.x; + real_t local = p_offset - _points[i].position.x; if (i == 0 && local <= 0) { - return _points[0].pos.y; + return _points[0].position.y; } return interpolate_local_nocheck(i, local); } -real_t Curve::interpolate_local_nocheck(int index, real_t local_offset) const { - const Point a = _points[index]; - const Point b = _points[index + 1]; +real_t Curve::interpolate_local_nocheck(int p_index, real_t p_local_offset) const { + const Point a = _points[p_index]; + const Point b = _points[p_index + 1]; /* Cubic bezier * @@ -341,16 +341,16 @@ real_t Curve::interpolate_local_nocheck(int index, real_t local_offset) const { */ // Control points are chosen at equal distances - real_t d = b.pos.x - a.pos.x; - if (Math::abs(d) <= CMP_EPSILON) { - return b.pos.y; + real_t d = b.position.x - a.position.x; + if (Math::is_zero_approx(d)) { + return b.position.y; } - local_offset /= d; + p_local_offset /= d; d /= 3.0; - real_t yac = a.pos.y + d * a.right_tangent; - real_t ybc = b.pos.y - d * b.left_tangent; + real_t yac = a.position.y + d * a.right_tangent; + real_t ybc = b.position.y - d * b.left_tangent; - real_t y = _bezier_interp(local_offset, a.pos.y, yac, ybc, b.pos.y); + real_t y = _bezier_interp(p_local_offset, a.position.y, yac, ybc, b.position.y); return y; } @@ -369,7 +369,7 @@ Array Curve::get_data() const { const Point p = _points[j]; int i = j * ELEMS; - output[i] = p.pos; + output[i] = p.position; output[i + 1] = p.left_tangent; output[i + 2] = p.right_tangent; output[i + 3] = p.left_mode; @@ -379,39 +379,39 @@ Array Curve::get_data() const { return output; } -void Curve::set_data(Array input) { +void Curve::set_data(const Array p_input) { const unsigned int ELEMS = 5; - ERR_FAIL_COND(input.size() % ELEMS != 0); + ERR_FAIL_COND(p_input.size() % ELEMS != 0); _points.clear(); // Validate input - for (int i = 0; i < input.size(); i += ELEMS) { - ERR_FAIL_COND(input[i].get_type() != Variant::VECTOR2); - ERR_FAIL_COND(!input[i + 1].is_num()); - ERR_FAIL_COND(input[i + 2].get_type() != Variant::FLOAT); + for (int i = 0; i < p_input.size(); i += ELEMS) { + ERR_FAIL_COND(p_input[i].get_type() != Variant::VECTOR2); + ERR_FAIL_COND(!p_input[i + 1].is_num()); + ERR_FAIL_COND(p_input[i + 2].get_type() != Variant::FLOAT); - ERR_FAIL_COND(input[i + 3].get_type() != Variant::INT); - int left_mode = input[i + 3]; + ERR_FAIL_COND(p_input[i + 3].get_type() != Variant::INT); + int left_mode = p_input[i + 3]; ERR_FAIL_COND(left_mode < 0 || left_mode >= TANGENT_MODE_COUNT); - ERR_FAIL_COND(input[i + 4].get_type() != Variant::INT); - int right_mode = input[i + 4]; + ERR_FAIL_COND(p_input[i + 4].get_type() != Variant::INT); + int right_mode = p_input[i + 4]; ERR_FAIL_COND(right_mode < 0 || right_mode >= TANGENT_MODE_COUNT); } - _points.resize(input.size() / ELEMS); + _points.resize(p_input.size() / ELEMS); for (int j = 0; j < _points.size(); ++j) { Point &p = _points.write[j]; int i = j * ELEMS; - p.pos = input[i]; - p.left_tangent = input[i + 1]; - p.right_tangent = input[i + 2]; + p.position = p_input[i]; + p.left_tangent = p_input[i + 1]; + p.right_tangent = p_input[i + 2]; // TODO For some reason the compiler won't convert from Variant to enum - int left_mode = input[i + 3]; - int right_mode = input[i + 4]; + int left_mode = p_input[i + 3]; + int right_mode = p_input[i + 4]; p.left_mode = (TangentMode)left_mode; p.right_mode = (TangentMode)right_mode; } @@ -431,8 +431,8 @@ void Curve::bake() { } if (_points.size() != 0) { - _baked_cache.write[0] = _points[0].pos.y; - _baked_cache.write[_baked_cache.size() - 1] = _points[_points.size() - 1].pos.y; + _baked_cache.write[0] = _points[0].position.y; + _baked_cache.write[_baked_cache.size() - 1] = _points[_points.size() - 1].position.y; } _baked_cache_dirty = false; @@ -445,7 +445,7 @@ void Curve::set_bake_resolution(int p_resolution) { _baked_cache_dirty = true; } -real_t Curve::interpolate_baked(real_t offset) const { +real_t Curve::interpolate_baked(real_t p_offset) const { if (_baked_cache_dirty) { // Last-second bake if not done already const_cast<Curve *>(this)->bake(); @@ -456,13 +456,13 @@ real_t Curve::interpolate_baked(real_t offset) const { if (_points.size() == 0) { return 0; } - return _points[0].pos.y; + return _points[0].position.y; } else if (_baked_cache.size() == 1) { return _baked_cache[0]; } // Get interpolation index - real_t fi = offset * _baked_cache.size(); + real_t fi = p_offset * _baked_cache.size(); int i = Math::floor(fi); if (i < 0) { i = 0; @@ -481,7 +481,7 @@ real_t Curve::interpolate_baked(real_t offset) const { } } -void Curve::ensure_default_setup(float p_min, float p_max) { +void Curve::ensure_default_setup(real_t p_min, real_t p_max) { if (_points.size() == 0 && _min_value == 0 && _max_value == 1) { add_point(Vector2(0, 1)); add_point(Vector2(1, 1)); @@ -535,9 +535,9 @@ int Curve2D::get_point_count() const { return points.size(); } -void Curve2D::add_point(const Vector2 &p_pos, const Vector2 &p_in, const Vector2 &p_out, int p_atpos) { +void Curve2D::add_point(const Vector2 &p_position, const Vector2 &p_in, const Vector2 &p_out, int p_atpos) { Point n; - n.pos = p_pos; + n.position = p_position; n.in = p_in; n.out = p_out; if (p_atpos >= 0 && p_atpos < points.size()) { @@ -550,17 +550,17 @@ void Curve2D::add_point(const Vector2 &p_pos, const Vector2 &p_in, const Vector2 emit_signal(CoreStringNames::get_singleton()->changed); } -void Curve2D::set_point_position(int p_index, const Vector2 &p_pos) { +void Curve2D::set_point_position(int p_index, const Vector2 &p_position) { ERR_FAIL_INDEX(p_index, points.size()); - points.write[p_index].pos = p_pos; + points.write[p_index].position = p_position; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } Vector2 Curve2D::get_point_position(int p_index) const { ERR_FAIL_INDEX_V(p_index, points.size(), Vector2()); - return points[p_index].pos; + return points[p_index].position; } void Curve2D::set_point_in(int p_index, const Vector2 &p_in) { @@ -604,19 +604,19 @@ void Curve2D::clear_points() { } } -Vector2 Curve2D::interpolate(int p_index, float p_offset) const { +Vector2 Curve2D::interpolate(int p_index, const real_t p_offset) const { int pc = points.size(); ERR_FAIL_COND_V(pc == 0, Vector2()); if (p_index >= pc - 1) { - return points[pc - 1].pos; + return points[pc - 1].position; } else if (p_index < 0) { - return points[0].pos; + return points[0].position; } - Vector2 p0 = points[p_index].pos; + Vector2 p0 = points[p_index].position; Vector2 p1 = p0 + points[p_index].out; - Vector2 p3 = points[p_index + 1].pos; + Vector2 p3 = points[p_index + 1].position; Vector2 p2 = p3 + points[p_index + 1].in; return _bezier_interp(p_offset, p0, p1, p2, p3); @@ -632,15 +632,15 @@ Vector2 Curve2D::interpolatef(real_t p_findex) const { return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0)); } -void Curve2D::_bake_segment2d(Map<float, Vector2> &r_bake, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, float p_tol) const { - float mp = p_begin + (p_end - p_begin) * 0.5; +void Curve2D::_bake_segment2d(Map<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const { + real_t mp = p_begin + (p_end - p_begin) * 0.5; Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b); Vector2 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b); Vector2 na = (mid - beg).normalized(); Vector2 nb = (end - mid).normalized(); - float dp = na.dot(nb); + real_t dp = na.dot(nb); if (dp < Math::cos(Math::deg2rad(p_tol))) { r_bake[mp] = mid; @@ -668,47 +668,47 @@ void Curve2D::_bake() const { if (points.size() == 1) { baked_point_cache.resize(1); - baked_point_cache.set(0, points[0].pos); + baked_point_cache.set(0, points[0].position); baked_dist_cache.resize(1); baked_dist_cache.set(0, 0.0); return; } - Vector2 pos = points[0].pos; - float dist = 0.0; + Vector2 position = points[0].position; + real_t dist = 0.0; List<Vector2> pointlist; - List<float> distlist; + List<real_t> distlist; - pointlist.push_back(pos); //start always from origin + pointlist.push_back(position); //start always from origin distlist.push_back(0.0); for (int i = 0; i < points.size() - 1; i++) { - float step = 0.1; // at least 10 substeps ought to be enough? - float p = 0.0; + real_t step = 0.1; // at least 10 substeps ought to be enough? + real_t p = 0.0; while (p < 1.0) { - float np = p + step; + real_t np = p + step; if (np > 1.0) { np = 1.0; } - Vector2 npp = _bezier_interp(np, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos); - float d = pos.distance_to(npp); + Vector2 npp = _bezier_interp(np, points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position); + real_t d = position.distance_to(npp); if (d > bake_interval) { // OK! between P and NP there _has_ to be Something, let's go searching! int iterations = 10; //lots of detail! - float low = p; - float hi = np; - float mid = low + (hi - low) * 0.5; + real_t low = p; + real_t hi = np; + real_t mid = low + (hi - low) * 0.5; for (int j = 0; j < iterations; j++) { - npp = _bezier_interp(mid, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos); - d = pos.distance_to(npp); + npp = _bezier_interp(mid, points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position); + d = position.distance_to(npp); if (bake_interval < d) { hi = mid; @@ -718,11 +718,11 @@ void Curve2D::_bake() const { mid = low + (hi - low) * 0.5; } - pos = npp; + position = npp; p = mid; dist += d; - pointlist.push_back(pos); + pointlist.push_back(position); distlist.push_back(dist); } else { p = np; @@ -730,9 +730,9 @@ void Curve2D::_bake() const { } } - Vector2 lastpos = points[points.size() - 1].pos; + Vector2 lastpos = points[points.size() - 1].position; - float rem = pos.distance_to(lastpos); + real_t rem = position.distance_to(lastpos); dist += rem; baked_max_ofs = dist; pointlist.push_back(lastpos); @@ -742,7 +742,7 @@ void Curve2D::_bake() const { baked_dist_cache.resize(distlist.size()); Vector2 *w = baked_point_cache.ptrw(); - float *wd = baked_dist_cache.ptrw(); + real_t *wd = baked_dist_cache.ptrw(); for (int i = 0; i < pointlist.size(); i++) { w[i] = pointlist[i]; @@ -750,7 +750,7 @@ void Curve2D::_bake() const { } } -float Curve2D::get_baked_length() const { +real_t Curve2D::get_baked_length() const { if (baked_cache_dirty) { _bake(); } @@ -758,7 +758,7 @@ float Curve2D::get_baked_length() const { return baked_max_ofs; } -Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const { +Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const { if (baked_cache_dirty) { _bake(); } @@ -784,7 +784,7 @@ Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const { int start = 0, end = bpc, idx = (end + start) / 2; // binary search to find baked points while (start < idx) { - float offset = baked_dist_cache[idx]; + real_t offset = baked_dist_cache[idx]; if (p_offset <= offset) { end = idx; } else { @@ -793,13 +793,13 @@ Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const { idx = (end + start) / 2; } - float offset_begin = baked_dist_cache[idx]; - float offset_end = baked_dist_cache[idx + 1]; + real_t offset_begin = baked_dist_cache[idx]; + real_t offset_end = baked_dist_cache[idx + 1]; - float idx_interval = offset_end - offset_begin; + real_t idx_interval = offset_end - offset_begin; ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector2(), "failed to find baked segment"); - float frac = (p_offset - offset_begin) / idx_interval; + real_t frac = (p_offset - offset_begin) / idx_interval; if (p_cubic) { Vector2 pre = idx > 0 ? r[idx - 1] : r[idx]; @@ -818,13 +818,13 @@ PackedVector2Array Curve2D::get_baked_points() const { return baked_point_cache; } -void Curve2D::set_bake_interval(float p_tolerance) { +void Curve2D::set_bake_interval(real_t p_tolerance) { bake_interval = p_tolerance; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } -float Curve2D::get_bake_interval() const { +real_t Curve2D::get_bake_interval() const { return bake_interval; } @@ -846,16 +846,16 @@ Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const { const Vector2 *r = baked_point_cache.ptr(); Vector2 nearest; - float nearest_dist = -1.0f; + real_t nearest_dist = -1.0f; for (int i = 0; i < pc - 1; i++) { Vector2 origin = r[i]; Vector2 direction = (r[i + 1] - origin) / bake_interval; - float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval); + real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval); Vector2 proj = origin + direction * d; - float dist = proj.distance_squared_to(p_to_point); + real_t dist = proj.distance_squared_to(p_to_point); if (nearest_dist < 0.0f || dist < nearest_dist) { nearest = proj; @@ -866,7 +866,7 @@ Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const { return nearest; } -float Curve2D::get_closest_offset(const Vector2 &p_to_point) const { +real_t Curve2D::get_closest_offset(const Vector2 &p_to_point) const { // Brute force method if (baked_cache_dirty) { @@ -883,18 +883,18 @@ float Curve2D::get_closest_offset(const Vector2 &p_to_point) const { const Vector2 *r = baked_point_cache.ptr(); - float nearest = 0.0f; - float nearest_dist = -1.0f; - float offset = 0.0f; + real_t nearest = 0.0f; + real_t nearest_dist = -1.0f; + real_t offset = 0.0f; for (int i = 0; i < pc - 1; i++) { Vector2 origin = r[i]; Vector2 direction = (r[i + 1] - origin) / bake_interval; - float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval); + real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval); Vector2 proj = origin + direction * d; - float dist = proj.distance_squared_to(p_to_point); + real_t dist = proj.distance_squared_to(p_to_point); if (nearest_dist < 0.0f || dist < nearest_dist) { nearest = offset + d; @@ -917,7 +917,7 @@ Dictionary Curve2D::_get_data() const { for (int i = 0; i < points.size(); i++) { w[i * 3 + 0] = points[i].in; w[i * 3 + 1] = points[i].out; - w[i * 3 + 2] = points[i].pos; + w[i * 3 + 2] = points[i].position; } dc["points"] = d; @@ -937,42 +937,42 @@ void Curve2D::_set_data(const Dictionary &p_data) { for (int i = 0; i < points.size(); i++) { points.write[i].in = r[i * 3 + 0]; points.write[i].out = r[i * 3 + 1]; - points.write[i].pos = r[i * 3 + 2]; + points.write[i].position = r[i * 3 + 2]; } baked_cache_dirty = true; } -PackedVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const { +PackedVector2Array Curve2D::tessellate(int p_max_stages, real_t p_tolerance) const { PackedVector2Array tess; if (points.size() == 0) { return tess; } - Vector<Map<float, Vector2>> midpoints; + Vector<Map<real_t, Vector2>> midpoints; midpoints.resize(points.size() - 1); int pc = 1; for (int i = 0; i < points.size() - 1; i++) { - _bake_segment2d(midpoints.write[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance); + _bake_segment2d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_tolerance); pc++; pc += midpoints[i].size(); } tess.resize(pc); Vector2 *bpw = tess.ptrw(); - bpw[0] = points[0].pos; + bpw[0] = points[0].position; int pidx = 0; for (int i = 0; i < points.size() - 1; i++) { - for (const KeyValue<float, Vector2> &E : midpoints[i]) { + for (const KeyValue<real_t, Vector2> &E : midpoints[i]) { pidx++; bpw[pidx] = E.value; } pidx++; - bpw[pidx] = points[i + 1].pos; + bpw[pidx] = points[i + 1].position; } return tess; @@ -1026,9 +1026,9 @@ int Curve3D::get_point_count() const { return points.size(); } -void Curve3D::add_point(const Vector3 &p_pos, const Vector3 &p_in, const Vector3 &p_out, int p_atpos) { +void Curve3D::add_point(const Vector3 &p_position, const Vector3 &p_in, const Vector3 &p_out, int p_atpos) { Point n; - n.pos = p_pos; + n.position = p_position; n.in = p_in; n.out = p_out; if (p_atpos >= 0 && p_atpos < points.size()) { @@ -1041,20 +1041,20 @@ void Curve3D::add_point(const Vector3 &p_pos, const Vector3 &p_in, const Vector3 emit_signal(CoreStringNames::get_singleton()->changed); } -void Curve3D::set_point_position(int p_index, const Vector3 &p_pos) { +void Curve3D::set_point_position(int p_index, const Vector3 &p_position) { ERR_FAIL_INDEX(p_index, points.size()); - points.write[p_index].pos = p_pos; + points.write[p_index].position = p_position; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } Vector3 Curve3D::get_point_position(int p_index) const { ERR_FAIL_INDEX_V(p_index, points.size(), Vector3()); - return points[p_index].pos; + return points[p_index].position; } -void Curve3D::set_point_tilt(int p_index, float p_tilt) { +void Curve3D::set_point_tilt(int p_index, real_t p_tilt) { ERR_FAIL_INDEX(p_index, points.size()); points.write[p_index].tilt = p_tilt; @@ -1062,7 +1062,7 @@ void Curve3D::set_point_tilt(int p_index, float p_tilt) { emit_signal(CoreStringNames::get_singleton()->changed); } -float Curve3D::get_point_tilt(int p_index) const { +real_t Curve3D::get_point_tilt(int p_index) const { ERR_FAIL_INDEX_V(p_index, points.size(), 0); return points[p_index].tilt; } @@ -1108,19 +1108,19 @@ void Curve3D::clear_points() { } } -Vector3 Curve3D::interpolate(int p_index, float p_offset) const { +Vector3 Curve3D::interpolate(int p_index, real_t p_offset) const { int pc = points.size(); ERR_FAIL_COND_V(pc == 0, Vector3()); if (p_index >= pc - 1) { - return points[pc - 1].pos; + return points[pc - 1].position; } else if (p_index < 0) { - return points[0].pos; + return points[0].position; } - Vector3 p0 = points[p_index].pos; + Vector3 p0 = points[p_index].position; Vector3 p1 = p0 + points[p_index].out; - Vector3 p3 = points[p_index + 1].pos; + Vector3 p3 = points[p_index + 1].position; Vector3 p2 = p3 + points[p_index + 1].in; return _bezier_interp(p_offset, p0, p1, p2, p3); @@ -1136,15 +1136,15 @@ Vector3 Curve3D::interpolatef(real_t p_findex) const { return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0)); } -void Curve3D::_bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, float p_tol) const { - float mp = p_begin + (p_end - p_begin) * 0.5; +void Curve3D::_bake_segment3d(Map<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const { + real_t mp = p_begin + (p_end - p_begin) * 0.5; Vector3 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); Vector3 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b); Vector3 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b); Vector3 na = (mid - beg).normalized(); Vector3 nb = (end - mid).normalized(); - float dp = na.dot(nb); + real_t dp = na.dot(nb); if (dp < Math::cos(Math::deg2rad(p_tol))) { r_bake[mp] = mid; @@ -1173,7 +1173,7 @@ void Curve3D::_bake() const { if (points.size() == 1) { baked_point_cache.resize(1); - baked_point_cache.set(0, points[0].pos); + baked_point_cache.set(0, points[0].position); baked_tilt_cache.resize(1); baked_tilt_cache.set(0, points[0].tilt); baked_dist_cache.resize(1); @@ -1189,39 +1189,39 @@ void Curve3D::_bake() const { return; } - Vector3 pos = points[0].pos; - float dist = 0.0; + Vector3 position = points[0].position; + real_t dist = 0.0; List<Plane> pointlist; - List<float> distlist; + List<real_t> distlist; - pointlist.push_back(Plane(pos, points[0].tilt)); + pointlist.push_back(Plane(position, points[0].tilt)); distlist.push_back(0.0); for (int i = 0; i < points.size() - 1; i++) { - float step = 0.1; // at least 10 substeps ought to be enough? - float p = 0.0; + real_t step = 0.1; // at least 10 substeps ought to be enough? + real_t p = 0.0; while (p < 1.0) { - float np = p + step; + real_t np = p + step; if (np > 1.0) { np = 1.0; } - Vector3 npp = _bezier_interp(np, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos); - float d = pos.distance_to(npp); + Vector3 npp = _bezier_interp(np, points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position); + real_t d = position.distance_to(npp); if (d > bake_interval) { // OK! between P and NP there _has_ to be Something, let's go searching! int iterations = 10; //lots of detail! - float low = p; - float hi = np; - float mid = low + (hi - low) * 0.5; + real_t low = p; + real_t hi = np; + real_t mid = low + (hi - low) * 0.5; for (int j = 0; j < iterations; j++) { - npp = _bezier_interp(mid, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos); - d = pos.distance_to(npp); + npp = _bezier_interp(mid, points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position); + d = position.distance_to(npp); if (bake_interval < d) { hi = mid; @@ -1231,10 +1231,10 @@ void Curve3D::_bake() const { mid = low + (hi - low) * 0.5; } - pos = npp; + position = npp; p = mid; Plane post; - post.normal = pos; + post.normal = position; post.d = Math::lerp(points[i].tilt, points[i + 1].tilt, mid); dist += d; @@ -1246,10 +1246,10 @@ void Curve3D::_bake() const { } } - Vector3 lastpos = points[points.size() - 1].pos; - float lastilt = points[points.size() - 1].tilt; + Vector3 lastpos = points[points.size() - 1].position; + real_t lastilt = points[points.size() - 1].tilt; - float rem = pos.distance_to(lastpos); + real_t rem = position.distance_to(lastpos); dist += rem; baked_max_ofs = dist; pointlist.push_back(Plane(lastpos, lastilt)); @@ -1266,7 +1266,7 @@ void Curve3D::_bake() const { Vector3 *up_write = baked_up_vector_cache.ptrw(); baked_dist_cache.resize(pointlist.size()); - float *wd = baked_dist_cache.ptrw(); + real_t *wd = baked_dist_cache.ptrw(); Vector3 sideways; Vector3 up; @@ -1288,7 +1288,7 @@ void Curve3D::_bake() const { forward = idx > 0 ? (w[idx] - w[idx - 1]).normalized() : prev_forward; - float y_dot = prev_up.dot(forward); + real_t y_dot = prev_up.dot(forward); if (y_dot > (1.0f - CMP_EPSILON)) { sideways = prev_sideways; @@ -1315,7 +1315,7 @@ void Curve3D::_bake() const { } } -float Curve3D::get_baked_length() const { +real_t Curve3D::get_baked_length() const { if (baked_cache_dirty) { _bake(); } @@ -1323,7 +1323,7 @@ float Curve3D::get_baked_length() const { return baked_max_ofs; } -Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const { +Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const { if (baked_cache_dirty) { _bake(); } @@ -1349,7 +1349,7 @@ Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const { int start = 0, end = bpc, idx = (end + start) / 2; // binary search to find baked points while (start < idx) { - float offset = baked_dist_cache[idx]; + real_t offset = baked_dist_cache[idx]; if (p_offset <= offset) { end = idx; } else { @@ -1358,13 +1358,13 @@ Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const { idx = (end + start) / 2; } - float offset_begin = baked_dist_cache[idx]; - float offset_end = baked_dist_cache[idx + 1]; + real_t offset_begin = baked_dist_cache[idx]; + real_t offset_end = baked_dist_cache[idx + 1]; - float idx_interval = offset_end - offset_begin; + real_t idx_interval = offset_end - offset_begin; ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(), "failed to find baked segment"); - float frac = (p_offset - offset_begin) / idx_interval; + real_t frac = (p_offset - offset_begin) / idx_interval; if (p_cubic) { Vector3 pre = idx > 0 ? r[idx - 1] : r[idx]; @@ -1375,7 +1375,7 @@ Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const { } } -float Curve3D::interpolate_baked_tilt(float p_offset) const { +real_t Curve3D::interpolate_baked_tilt(real_t p_offset) const { if (baked_cache_dirty) { _bake(); } @@ -1399,7 +1399,7 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const { } int idx = Math::floor((double)p_offset / (double)bake_interval); - float frac = Math::fmod(p_offset, bake_interval); + real_t frac = Math::fmod(p_offset, bake_interval); if (idx >= bpc - 1) { return r[bpc - 1]; @@ -1414,7 +1414,7 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const { return Math::lerp(r[idx], r[idx + 1], (real_t)frac); } -Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt) const { +Vector3 Curve3D::interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt) const { if (baked_cache_dirty) { _bake(); } @@ -1432,10 +1432,10 @@ Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt) const Vector3 *rp = baked_point_cache.ptr(); const real_t *rt = baked_tilt_cache.ptr(); - float offset = CLAMP(p_offset, 0.0f, baked_max_ofs); + real_t offset = CLAMP(p_offset, 0.0f, baked_max_ofs); int idx = Math::floor((double)offset / (double)bake_interval); - float frac = Math::fmod(offset, bake_interval) / bake_interval; + real_t frac = Math::fmod(offset, bake_interval) / bake_interval; if (idx == count - 1) { return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx]; @@ -1503,16 +1503,16 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const { const Vector3 *r = baked_point_cache.ptr(); Vector3 nearest; - float nearest_dist = -1.0f; + real_t nearest_dist = -1.0f; for (int i = 0; i < pc - 1; i++) { Vector3 origin = r[i]; Vector3 direction = (r[i + 1] - origin) / bake_interval; - float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval); + real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval); Vector3 proj = origin + direction * d; - float dist = proj.distance_squared_to(p_to_point); + real_t dist = proj.distance_squared_to(p_to_point); if (nearest_dist < 0.0f || dist < nearest_dist) { nearest = proj; @@ -1523,7 +1523,7 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const { return nearest; } -float Curve3D::get_closest_offset(const Vector3 &p_to_point) const { +real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const { // Brute force method if (baked_cache_dirty) { @@ -1540,18 +1540,18 @@ float Curve3D::get_closest_offset(const Vector3 &p_to_point) const { const Vector3 *r = baked_point_cache.ptr(); - float nearest = 0.0f; - float nearest_dist = -1.0f; - float offset = 0.0f; + real_t nearest = 0.0f; + real_t nearest_dist = -1.0f; + real_t offset = 0.0f; for (int i = 0; i < pc - 1; i++) { Vector3 origin = r[i]; Vector3 direction = (r[i + 1] - origin) / bake_interval; - float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval); + real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval); Vector3 proj = origin + direction * d; - float dist = proj.distance_squared_to(p_to_point); + real_t dist = proj.distance_squared_to(p_to_point); if (nearest_dist < 0.0f || dist < nearest_dist) { nearest = offset + d; @@ -1564,13 +1564,13 @@ float Curve3D::get_closest_offset(const Vector3 &p_to_point) const { return nearest; } -void Curve3D::set_bake_interval(float p_tolerance) { +void Curve3D::set_bake_interval(real_t p_tolerance) { bake_interval = p_tolerance; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } -float Curve3D::get_bake_interval() const { +real_t Curve3D::get_bake_interval() const { return bake_interval; } @@ -1597,7 +1597,7 @@ Dictionary Curve3D::_get_data() const { for (int i = 0; i < points.size(); i++) { w[i * 3 + 0] = points[i].in; w[i * 3 + 1] = points[i].out; - w[i * 3 + 2] = points[i].pos; + w[i * 3 + 2] = points[i].position; wt[i] = points[i].tilt; } @@ -1622,43 +1622,43 @@ void Curve3D::_set_data(const Dictionary &p_data) { for (int i = 0; i < points.size(); i++) { points.write[i].in = r[i * 3 + 0]; points.write[i].out = r[i * 3 + 1]; - points.write[i].pos = r[i * 3 + 2]; + points.write[i].position = r[i * 3 + 2]; points.write[i].tilt = rt[i]; } baked_cache_dirty = true; } -PackedVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const { +PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) const { PackedVector3Array tess; if (points.size() == 0) { return tess; } - Vector<Map<float, Vector3>> midpoints; + Vector<Map<real_t, Vector3>> midpoints; midpoints.resize(points.size() - 1); int pc = 1; for (int i = 0; i < points.size() - 1; i++) { - _bake_segment3d(midpoints.write[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance); + _bake_segment3d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_tolerance); pc++; pc += midpoints[i].size(); } tess.resize(pc); Vector3 *bpw = tess.ptrw(); - bpw[0] = points[0].pos; + bpw[0] = points[0].position; int pidx = 0; for (int i = 0; i < points.size() - 1; i++) { - for (const KeyValue<float, Vector3> &E : midpoints[i]) { + for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { pidx++; bpw[pidx] = E.value; } pidx++; - bpw[pidx] = points[i + 1].pos; + bpw[pidx] = points[i + 1].position; } return tess; diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 5808fd6508..16facda85a 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -50,7 +50,7 @@ public: }; struct Point { - Vector2 pos; + Vector2 position; real_t left_tangent = 0.0; real_t right_tangent = 0.0; TangentMode left_mode = TANGENT_FREE; @@ -59,12 +59,12 @@ public: Point() { } - Point(Vector2 p_pos, + Point(const Vector2 &p_position, real_t p_left = 0.0, real_t p_right = 0.0, TangentMode p_left_mode = TANGENT_FREE, TangentMode p_right_mode = TANGENT_FREE) { - pos = p_pos; + position = p_position; left_tangent = p_left; right_tangent = p_right; left_mode = p_left_mode; @@ -76,7 +76,7 @@ public: int get_point_count() const { return _points.size(); } - int add_point(Vector2 p_pos, + int add_point(Vector2 p_position, real_t left_tangent = 0, real_t right_tangent = 0, TangentMode left_mode = TANGENT_FREE, @@ -85,34 +85,34 @@ public: void remove_point(int p_index); void clear_points(); - int get_index(real_t offset) const; + int get_index(real_t p_offset) const; - void set_point_value(int p_index, real_t pos); - int set_point_offset(int p_index, float offset); + void set_point_value(int p_index, real_t p_position); + int set_point_offset(int p_index, real_t p_offset); Vector2 get_point_position(int p_index) const; Point get_point(int p_index) const; - float get_min_value() const { return _min_value; } - void set_min_value(float p_min); + real_t get_min_value() const { return _min_value; } + void set_min_value(real_t p_min); - float get_max_value() const { return _max_value; } - void set_max_value(float p_max); + real_t get_max_value() const { return _max_value; } + void set_max_value(real_t p_max); - real_t interpolate(real_t offset) const; - real_t interpolate_local_nocheck(int index, real_t local_offset) const; + real_t interpolate(real_t p_offset) const; + real_t interpolate_local_nocheck(int p_index, real_t p_local_offset) const; void clean_dupes(); - void set_point_left_tangent(int i, real_t tangent); - void set_point_right_tangent(int i, real_t tangent); - void set_point_left_mode(int i, TangentMode p_mode); - void set_point_right_mode(int i, TangentMode p_mode); + void set_point_left_tangent(int p_index, real_t p_tangent); + void set_point_right_tangent(int p_index, real_t p_tangent); + void set_point_left_mode(int p_index, TangentMode p_mode); + void set_point_right_mode(int p_index, TangentMode p_mode); - real_t get_point_left_tangent(int i) const; - real_t get_point_right_tangent(int i) const; - TangentMode get_point_left_mode(int i) const; - TangentMode get_point_right_mode(int i) const; + real_t get_point_left_tangent(int p_index) const; + real_t get_point_right_tangent(int p_index) const; + TangentMode get_point_left_mode(int p_index) const; + TangentMode get_point_right_mode(int p_index) const; void update_auto_tangents(int i); @@ -122,9 +122,9 @@ public: void bake(); int get_bake_resolution() const { return _bake_resolution; } void set_bake_resolution(int p_resolution); - real_t interpolate_baked(real_t offset) const; + real_t interpolate_baked(real_t p_offset) const; - void ensure_default_setup(float p_min, float p_max); + void ensure_default_setup(real_t p_min, real_t p_max); protected: static void _bind_methods(); @@ -136,8 +136,8 @@ private: bool _baked_cache_dirty = false; Vector<real_t> _baked_cache; int _bake_resolution = 100; - float _min_value = 0.0; - float _max_value = 1.0; + real_t _min_value = 0.0; + real_t _max_value = 1.0; int _minmax_set_once = 0b00; // Encodes whether min and max have been set a first time, first bit for min and second for max. }; @@ -149,26 +149,26 @@ class Curve2D : public Resource { struct Point { Vector2 in; Vector2 out; - Vector2 pos; + Vector2 position; }; Vector<Point> points; struct BakedPoint { - float ofs = 0.0; + real_t ofs = 0.0; Vector2 point; }; mutable bool baked_cache_dirty = false; mutable PackedVector2Array baked_point_cache; - mutable PackedFloat32Array baked_dist_cache; - mutable float baked_max_ofs = 0.0; + mutable Vector<real_t> baked_dist_cache; + mutable real_t baked_max_ofs = 0.0; void _bake() const; - float bake_interval = 5.0; + real_t bake_interval = 5.0; - void _bake_segment2d(Map<float, Vector2> &r_bake, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, float p_tol) const; + void _bake_segment2d(Map<real_t, Vector2> &r_bake, real_t p_begin, real_t p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, real_t p_tol) const; Dictionary _get_data() const; void _set_data(const Dictionary &p_data); @@ -177,8 +177,8 @@ protected: public: int get_point_count() const; - void add_point(const Vector2 &p_pos, const Vector2 &p_in = Vector2(), const Vector2 &p_out = Vector2(), int p_atpos = -1); - void set_point_position(int p_index, const Vector2 &p_pos); + void add_point(const Vector2 &p_position, const Vector2 &p_in = Vector2(), const Vector2 &p_out = Vector2(), int p_atpos = -1); + void set_point_position(int p_index, const Vector2 &p_position); Vector2 get_point_position(int p_index) const; void set_point_in(int p_index, const Vector2 &p_in); Vector2 get_point_in(int p_index) const; @@ -187,19 +187,19 @@ public: void remove_point(int p_index); void clear_points(); - Vector2 interpolate(int p_index, float p_offset) const; + Vector2 interpolate(int p_index, real_t p_offset) const; Vector2 interpolatef(real_t p_findex) const; - void set_bake_interval(float p_tolerance); - float get_bake_interval() const; + void set_bake_interval(real_t p_tolerance); + real_t get_bake_interval() const; - float get_baked_length() const; - Vector2 interpolate_baked(float p_offset, bool p_cubic = false) const; + real_t get_baked_length() const; + Vector2 interpolate_baked(real_t p_offset, bool p_cubic = false) const; PackedVector2Array get_baked_points() const; //useful for going through Vector2 get_closest_point(const Vector2 &p_to_point) const; - float get_closest_offset(const Vector2 &p_to_point) const; + real_t get_closest_offset(const Vector2 &p_to_point) const; - PackedVector2Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display + PackedVector2Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display Curve2D(); }; @@ -210,14 +210,14 @@ class Curve3D : public Resource { struct Point { Vector3 in; Vector3 out; - Vector3 pos; - float tilt = 0.0; + Vector3 position; + real_t tilt = 0.0; }; Vector<Point> points; struct BakedPoint { - float ofs = 0.0; + real_t ofs = 0.0; Vector3 point; }; @@ -225,15 +225,15 @@ class Curve3D : public Resource { mutable PackedVector3Array baked_point_cache; mutable Vector<real_t> baked_tilt_cache; mutable PackedVector3Array baked_up_vector_cache; - mutable PackedFloat32Array baked_dist_cache; - mutable float baked_max_ofs = 0.0; + mutable Vector<real_t> baked_dist_cache; + mutable real_t baked_max_ofs = 0.0; void _bake() const; - float bake_interval = 0.2; + real_t bake_interval = 0.2; bool up_vector_enabled = true; - void _bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, float p_tol) const; + void _bake_segment3d(Map<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const; Dictionary _get_data() const; void _set_data(const Dictionary &p_data); @@ -242,11 +242,11 @@ protected: public: int get_point_count() const; - void add_point(const Vector3 &p_pos, const Vector3 &p_in = Vector3(), const Vector3 &p_out = Vector3(), int p_atpos = -1); - void set_point_position(int p_index, const Vector3 &p_pos); + void add_point(const Vector3 &p_position, const Vector3 &p_in = Vector3(), const Vector3 &p_out = Vector3(), int p_atpos = -1); + void set_point_position(int p_index, const Vector3 &p_position); Vector3 get_point_position(int p_index) const; - void set_point_tilt(int p_index, float p_tilt); - float get_point_tilt(int p_index) const; + void set_point_tilt(int p_index, real_t p_tilt); + real_t get_point_tilt(int p_index) const; void set_point_in(int p_index, const Vector3 &p_in); Vector3 get_point_in(int p_index) const; void set_point_out(int p_index, const Vector3 &p_out); @@ -254,25 +254,25 @@ public: void remove_point(int p_index); void clear_points(); - Vector3 interpolate(int p_index, float p_offset) const; + Vector3 interpolate(int p_index, real_t p_offset) const; Vector3 interpolatef(real_t p_findex) const; - void set_bake_interval(float p_tolerance); - float get_bake_interval() const; + void set_bake_interval(real_t p_tolerance); + real_t get_bake_interval() const; void set_up_vector_enabled(bool p_enable); bool is_up_vector_enabled() const; - float get_baked_length() const; - Vector3 interpolate_baked(float p_offset, bool p_cubic = false) const; - float interpolate_baked_tilt(float p_offset) const; - Vector3 interpolate_baked_up_vector(float p_offset, bool p_apply_tilt = false) const; + real_t get_baked_length() const; + Vector3 interpolate_baked(real_t p_offset, bool p_cubic = false) const; + real_t interpolate_baked_tilt(real_t p_offset) const; + Vector3 interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt = false) const; PackedVector3Array get_baked_points() const; //useful for going through Vector<real_t> get_baked_tilts() const; //useful for going through PackedVector3Array get_baked_up_vectors() const; Vector3 get_closest_point(const Vector3 &p_to_point) const; - float get_closest_offset(const Vector3 &p_to_point) const; + real_t get_closest_offset(const Vector3 &p_to_point) const; - PackedVector3Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display + PackedVector3Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display Curve3D(); }; diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp index fe7124de9e..4f9a055bfb 100644 --- a/scene/resources/immediate_mesh.cpp +++ b/scene/resources/immediate_mesh.cpp @@ -144,6 +144,7 @@ void ImmediateMesh::surface_add_vertex_2d(const Vector2 &p_vertex) { active_surface_data.vertex_2d = true; } + void ImmediateMesh::surface_end() { ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it."); ERR_FAIL_COND_MSG(!vertices.size(), "No vertices were added, surface can't be created."); @@ -185,7 +186,7 @@ void ImmediateMesh::surface_end() { vtx[2] = vertices[i].z; } if (i == 0) { - aabb.position = vertices[i]; + aabb = AABB(vertices[i], SMALL_VEC3); // Must have a bit of size. } else { aabb.expand_to(vertices[i]); } diff --git a/scene/resources/immediate_mesh.h b/scene/resources/immediate_mesh.h index 6673ee6f3d..92bf91441d 100644 --- a/scene/resources/immediate_mesh.h +++ b/scene/resources/immediate_mesh.h @@ -75,6 +75,8 @@ class ImmediateMesh : public Mesh { Vector<uint8_t> surface_vertex_create_cache; Vector<uint8_t> surface_attribute_create_cache; + const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON); + protected: static void _bind_methods(); diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index 1a829968e3..a7c20b2cb9 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -318,26 +318,24 @@ String VisualShaderNodeParticleMeshEmitter::get_input_port_name(int p_port) cons String VisualShaderNodeParticleMeshEmitter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code; - if (mesh.is_valid()) { - if (is_output_port_connected(0)) { // position - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n"; - } + if (is_output_port_connected(0)) { // position + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n"; + } - if (is_output_port_connected(1)) { // normal - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n"; - } + if (is_output_port_connected(1)) { // normal + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n"; + } - if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n"; - } + if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n"; + } - if (is_output_port_connected(4)) { // uv - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n"; - } + if (is_output_port_connected(4)) { // uv + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n"; + } - if (is_output_port_connected(5)) { // uv2 - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n"; - } + if (is_output_port_connected(5)) { // uv2 + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n"; } return code; @@ -503,67 +501,97 @@ void VisualShaderNodeParticleMeshEmitter::_update_textures() { Vector<Vector2> uvs; Vector<Vector2> uvs2; + const int surface_count = mesh->get_surface_count(); + if (use_all_surfaces) { - for (int i = 0; i < max_surface_index; i++) { + for (int i = 0; i < surface_count; i++) { + const Array surface_arrays = mesh->surface_get_arrays(i); + const int surface_arrays_size = surface_arrays.size(); + // position - Array vertex_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_VERTEX]; - for (int j = 0; j < vertex_array.size(); j++) { - vertices.push_back((Vector3)vertex_array[j]); + if (surface_arrays_size > Mesh::ARRAY_VERTEX) { + Array vertex_array = surface_arrays[Mesh::ARRAY_VERTEX]; + for (int j = 0; j < vertex_array.size(); j++) { + vertices.push_back((Vector3)vertex_array[j]); + } } // normal - Array normal_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_NORMAL]; - for (int j = 0; j < normal_array.size(); j++) { - normals.push_back((Vector3)normal_array[j]); + if (surface_arrays_size > Mesh::ARRAY_NORMAL) { + Array normal_array = surface_arrays[Mesh::ARRAY_NORMAL]; + for (int j = 0; j < normal_array.size(); j++) { + normals.push_back((Vector3)normal_array[j]); + } } // color - Array color_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_COLOR]; - for (int j = 0; j < color_array.size(); j++) { - colors.push_back((Color)color_array[j]); + if (surface_arrays_size > Mesh::ARRAY_COLOR) { + Array color_array = surface_arrays[Mesh::ARRAY_COLOR]; + for (int j = 0; j < color_array.size(); j++) { + colors.push_back((Color)color_array[j]); + } } // uv - Array uv_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV]; - for (int j = 0; j < uv_array.size(); j++) { - uvs.push_back((Vector2)uv_array[j]); + if (surface_arrays_size > Mesh::ARRAY_TEX_UV) { + Array uv_array = surface_arrays[Mesh::ARRAY_TEX_UV]; + for (int j = 0; j < uv_array.size(); j++) { + uvs.push_back((Vector2)uv_array[j]); + } } // uv2 - Array uv2_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV2]; - for (int j = 0; j < uv2_array.size(); j++) { - uvs2.push_back((Vector2)uv2_array[j]); + if (surface_arrays_size > Mesh::ARRAY_TEX_UV2) { + Array uv2_array = surface_arrays[Mesh::ARRAY_TEX_UV2]; + for (int j = 0; j < uv2_array.size(); j++) { + uvs2.push_back((Vector2)uv2_array[j]); + } } } } else { - // position - Array vertex_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_VERTEX]; - for (int i = 0; i < vertex_array.size(); i++) { - vertices.push_back((Vector3)vertex_array[i]); - } + if (surface_index >= 0 && surface_index < surface_count) { + const Array surface_arrays = mesh->surface_get_arrays(surface_index); + const int surface_arrays_size = surface_arrays.size(); - // normal - Array normal_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_NORMAL]; - for (int i = 0; i < normal_array.size(); i++) { - normals.push_back((Vector3)normal_array[i]); - } + // position + if (surface_arrays_size > Mesh::ARRAY_VERTEX) { + Array vertex_array = surface_arrays[Mesh::ARRAY_VERTEX]; + for (int i = 0; i < vertex_array.size(); i++) { + vertices.push_back((Vector3)vertex_array[i]); + } + } - // color - Array color_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_COLOR]; - for (int i = 0; i < color_array.size(); i++) { - colors.push_back((Color)color_array[i]); - } + // normal + if (surface_arrays_size > Mesh::ARRAY_NORMAL) { + Array normal_array = surface_arrays[Mesh::ARRAY_NORMAL]; + for (int i = 0; i < normal_array.size(); i++) { + normals.push_back((Vector3)normal_array[i]); + } + } - // uv - Array uv_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV]; - for (int j = 0; j < uv_array.size(); j++) { - uvs.push_back((Vector2)uv_array[j]); - } + // color + if (surface_arrays_size > Mesh::ARRAY_COLOR) { + Array color_array = surface_arrays[Mesh::ARRAY_COLOR]; + for (int i = 0; i < color_array.size(); i++) { + colors.push_back((Color)color_array[i]); + } + } + + // uv + if (surface_arrays_size > Mesh::ARRAY_TEX_UV) { + Array uv_array = surface_arrays[Mesh::ARRAY_TEX_UV]; + for (int j = 0; j < uv_array.size(); j++) { + uvs.push_back((Vector2)uv_array[j]); + } + } - // uv2 - Array uv2_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV2]; - for (int j = 0; j < uv2_array.size(); j++) { - uvs2.push_back((Vector2)uv2_array[j]); + // uv2 + if (surface_arrays_size > Mesh::ARRAY_TEX_UV2) { + Array uv2_array = surface_arrays[Mesh::ARRAY_TEX_UV2]; + for (int j = 0; j < uv2_array.size(); j++) { + uvs2.push_back((Vector2)uv2_array[j]); + } + } } } @@ -579,12 +607,6 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) { return; } - if (p_mesh.is_valid()) { - max_surface_index = p_mesh->get_surface_count(); - } else { - max_surface_index = 0; - } - if (mesh.is_valid()) { Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures); @@ -623,7 +645,16 @@ bool VisualShaderNodeParticleMeshEmitter::is_use_all_surfaces() const { } void VisualShaderNodeParticleMeshEmitter::set_surface_index(int p_surface_index) { - if (p_surface_index == surface_index || p_surface_index < 0 || p_surface_index >= max_surface_index) { + if (mesh.is_valid()) { + if (mesh->get_surface_count() > 0) { + p_surface_index = CLAMP(p_surface_index, 0, mesh->get_surface_count() - 1); + } else { + p_surface_index = 0; + } + } else if (p_surface_index < 0) { + p_surface_index = 0; + } + if (surface_index == p_surface_index) { return; } surface_index = p_surface_index; diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index 79459432f1..ae7ea69225 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -111,7 +111,6 @@ class VisualShaderNodeParticleMeshEmitter : public VisualShaderNodeParticleEmitt Ref<Mesh> mesh; bool use_all_surfaces = true; int surface_index = 0; - int max_surface_index = 0; Ref<ImageTexture> position_texture; Ref<ImageTexture> normal_texture; diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index d9ee91084f..0837e41db8 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -65,7 +65,11 @@ public: Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); } - WindowID get_window_at_screen_position(const Point2i &p_position) const override { return -1; } + WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override { return 0; } + void show_window(WindowID p_id) override {} + void delete_sub_window(WindowID p_id) override {} + + WindowID get_window_at_screen_position(const Point2i &p_position) const override { return 0; } void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override {} ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override { return ObjectID(); } @@ -93,7 +97,7 @@ public: Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); } void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {} - Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }; + Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); } void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {} Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); } @@ -102,10 +106,13 @@ public: void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override {} WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override { return WINDOW_MODE_MINIMIZED; } + void window_set_vsync_mode(VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override {} + VSyncMode window_get_vsync_mode(WindowID p_window) const override { return VSyncMode::VSYNC_ENABLED; } + bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override { return false; } void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override {} - virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override { return false; } + bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override { return false; } void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override {} void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override {} @@ -114,6 +121,9 @@ public: bool can_any_window_draw() const override { return false; } + void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override {} + void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override {} + void process_events() override {} void set_icon(const Ref<Image> &p_icon) override {} diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp index 6d1c5539aa..44da5d4f3b 100644 --- a/servers/physics_2d/godot_body_2d.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -549,6 +549,9 @@ void GodotBody2D::integrate_forces(real_t p_step) { gravity *= gravity_scale; + prev_linear_velocity = linear_velocity; + prev_angular_velocity = angular_velocity; + Vector2 motion; bool do_motion = false; diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 0df93482dc..ba4c39737a 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -50,6 +50,9 @@ class GodotBody2D : public GodotCollisionObject2D { Vector2 linear_velocity; real_t angular_velocity = 0.0; + Vector2 prev_linear_velocity; + real_t prev_angular_velocity = 0.0; + Vector2 constant_linear_velocity; real_t constant_angular_velocity = 0.0; @@ -209,6 +212,9 @@ public: _FORCE_INLINE_ void set_angular_velocity(real_t p_velocity) { angular_velocity = p_velocity; } _FORCE_INLINE_ real_t get_angular_velocity() const { return angular_velocity; } + _FORCE_INLINE_ Vector2 get_prev_linear_velocity() const { return prev_linear_velocity; } + _FORCE_INLINE_ real_t get_prev_angular_velocity() const { return prev_angular_velocity; } + _FORCE_INLINE_ void set_biased_linear_velocity(const Vector2 &p_velocity) { biased_linear_velocity = p_velocity; } _FORCE_INLINE_ Vector2 get_biased_linear_velocity() const { return biased_linear_velocity; } diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp index 97eeefbfe6..67b0f21456 100644 --- a/servers/physics_2d/godot_body_pair_2d.cpp +++ b/servers/physics_2d/godot_body_pair_2d.cpp @@ -32,7 +32,6 @@ #include "godot_collision_solver_2d.h" #include "godot_space_2d.h" -#define POSITION_CORRECTION #define ACCUMULATE_IMPULSES void GodotBodyPair2D::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) { @@ -453,9 +452,9 @@ bool GodotBodyPair2D::pre_solve(real_t p_step) { c.bounce = combine_bounce(A, B); if (c.bounce) { - Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x); - Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x); - Vector2 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; + Vector2 crA(-A->get_prev_angular_velocity() * c.rA.y, A->get_prev_angular_velocity() * c.rA.x); + Vector2 crB(-B->get_prev_angular_velocity() * c.rB.y, B->get_prev_angular_velocity() * c.rB.x); + Vector2 dv = B->get_prev_linear_velocity() + crB - A->get_prev_linear_velocity() - crA; c.bounce = c.bounce * dv.dot(c.normal); } diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp index 40d946655d..d5098a2a5f 100644 --- a/servers/physics_3d/godot_body_3d.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -604,6 +604,9 @@ void GodotBody3D::integrate_forces(real_t p_step) { gravity *= gravity_scale; + prev_linear_velocity = linear_velocity; + prev_angular_velocity = angular_velocity; + Vector3 motion; bool do_motion = false; diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index bba9ec6c3a..6ea6d1fcaa 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -45,6 +45,9 @@ class GodotBody3D : public GodotCollisionObject3D { Vector3 linear_velocity; Vector3 angular_velocity; + Vector3 prev_linear_velocity; + Vector3 prev_angular_velocity; + Vector3 constant_linear_velocity; Vector3 constant_angular_velocity; @@ -207,6 +210,9 @@ public: _FORCE_INLINE_ void set_angular_velocity(const Vector3 &p_velocity) { angular_velocity = p_velocity; } _FORCE_INLINE_ Vector3 get_angular_velocity() const { return angular_velocity; } + _FORCE_INLINE_ Vector3 get_prev_linear_velocity() const { return prev_linear_velocity; } + _FORCE_INLINE_ Vector3 get_prev_angular_velocity() const { return prev_angular_velocity; } + _FORCE_INLINE_ const Vector3 &get_biased_linear_velocity() const { return biased_linear_velocity; } _FORCE_INLINE_ const Vector3 &get_biased_angular_velocity() const { return biased_angular_velocity; } diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp index f0002870ae..8a701466ed 100644 --- a/servers/physics_3d/godot_body_pair_3d.cpp +++ b/servers/physics_3d/godot_body_pair_3d.cpp @@ -35,18 +35,6 @@ #include "core/os/os.h" -/* -#define NO_ACCUMULATE_IMPULSES -#define NO_SPLIT_IMPULSES - -#define NO_FRICTION -*/ - -#define NO_TANGENTIALS -/* BODY PAIR */ - -//#define ALLOWED_PENETRATION 0.01 -#define RELAXATION_TIMESTEPS 3 #define MIN_VELOCITY 0.0001 #define MAX_BIAS_ROTATION (Math_PI / 8) @@ -370,10 +358,9 @@ bool GodotBodyPair3D::pre_solve(real_t p_step) { c.bounce = combine_bounce(A, B); if (c.bounce) { - Vector3 crA = A->get_angular_velocity().cross(c.rA); - Vector3 crB = B->get_angular_velocity().cross(c.rB); - Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; - //normal impule + Vector3 crA = A->get_prev_angular_velocity().cross(c.rA); + Vector3 crB = B->get_prev_angular_velocity().cross(c.rB); + Vector3 dv = B->get_prev_linear_velocity() + crB - A->get_prev_linear_velocity() - crA; c.bounce = c.bounce * dv.dot(c.normal); } } diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index b952ecbff0..4a98cf0831 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -460,14 +460,6 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterRender::PushConstant)); uint32_t instances = 1; -#if 0 - for (uint32_t j = i+1; j < element_count; j++) { - if (elements[i].type!=elements[j].type) { - break; - } - instances++; - } -#endif RD::get_singleton()->draw_list_draw(draw_list, true, instances); i += instances; } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 04acc871b4..29e4a63cbb 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -2652,7 +2652,17 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName //regular uniform uint32_t offset = p_uniform_offsets[E.value.order]; #ifdef DEBUG_ENABLED - uint32_t size = ShaderLanguage::get_type_size(E.value.type); + uint32_t size = 0U; + // The following code enforces a 16-byte alignment of uniform arrays. + if (E.value.array_size > 0) { + size = ShaderLanguage::get_type_size(E.value.type) * E.value.array_size; + int m = (16 * E.value.array_size); + if ((size % m) != 0U) { + size += m - (size % m); + } + } else { + size = ShaderLanguage::get_type_size(E.value.type); + } ERR_CONTINUE(offset + size > p_buffer_size); #endif uint8_t *data = &p_buffer[offset]; @@ -10023,7 +10033,7 @@ RendererStorageRD::RendererStorageRD() { actions.renames["RESTART"] = "restart"; actions.renames["CUSTOM"] = "PARTICLE.custom"; actions.renames["TRANSFORM"] = "PARTICLE.xform"; - actions.renames["TIME"] = "FRAME.time"; + actions.renames["TIME"] = "frame_history.data[0].time"; actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["E"] = _MKSTR(Math_E); diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index f7c8ca1487..b02b3d2723 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -661,6 +661,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge uniform_sizes.write[uniform.order] = _get_datatype_size(ShaderLanguage::TYPE_UINT); uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT); } else { + // The following code enforces a 16-byte alignment of uniform arrays. if (uniform.array_size > 0) { int size = _get_datatype_size(uniform.type) * uniform.array_size; int m = (16 * uniform.array_size); @@ -668,10 +669,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge size += m - (size % m); } uniform_sizes.write[uniform.order] = size; + uniform_alignments.write[uniform.order] = 16; } else { uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type); + uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type); } - uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type); } } @@ -1316,6 +1318,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge code += ")"; } break; + case SL::OP_EMPTY: { + // Semicolon (or empty statement) - ignored. + } break; default: { if (p_use_scope) { diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 8e33610ae2..e4628b2d5a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -1757,7 +1757,11 @@ void main() { } } +#ifdef MOLTENVK_USED + imageStore(geom_facing_grid, grid_pos, uvec4(imageLoad(geom_facing_grid, grid_pos).r | facing_bits)); //store facing bits +#else imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits +#endif if (length(emission) > 0.001) { float lumas[6]; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 8a14834569..eddf5bf53d 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -85,14 +85,14 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) { // FSR is not design for downsampling. // Throw a warning and fallback to VIEWPORT_SCALING_3D_MODE_BILINEAR - print_error("FSR does not support supersampling. Falling back to bilinear mode."); + WARN_PRINT_ONCE("FSR 3D resolution scaling does not support supersampling. Falling back to bilinear scaling."); scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR; } if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && !p_viewport->fsr_enabled) { // FSR is not actually available. // Throw a warning and fallback to disable scaling - print_error("FSR is not available. Disabled FSR scaling 3D. Try bilinear mode."); + WARN_PRINT_ONCE("FSR 3D resolution scaling is not available. Disabling 3D resolution scaling."); scaling_enabled = false; } @@ -123,7 +123,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { break; default: // This is an unknown mode. - print_error(vformat("Unknown scaling mode: %d, disabling scaling 3D", scaling_3d_mode)); + WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode)); width = p_viewport->size.width; height = p_viewport->size.height; render_width = width; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index dcbc5f5c8e..5602bb197b 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -185,9 +185,13 @@ Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref< String error; ShaderStage stage = ShaderStage(i); - Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, p_source->get_stage_source(stage), p_source->get_language(), &error, p_allow_cache); - bytecode->set_stage_bytecode(stage, spirv); - bytecode->set_stage_compile_error(stage, error); + String source = p_source->get_stage_source(stage); + + if (!source.is_empty()) { + Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, source, p_source->get_language(), &error, p_allow_cache); + bytecode->set_stage_bytecode(stage, spirv); + bytecode->set_stage_compile_error(stage, error); + } } return bytecode; } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index c7a7ed154e..052b1d6d9f 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -4293,7 +4293,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, cons return n; } -Error ShaderLanguage::_parse_global_array_size(int &r_array_size) { +Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info) { if (r_array_size > 0) { _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; @@ -4305,7 +4305,7 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size) { if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { _set_tkpos(pos); - Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size); + Node *n = _parse_array_size(nullptr, p_function_info, array_size); if (!n) { return ERR_PARSE_ERROR; } @@ -5208,9 +5208,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expression.push_back(e); continue; } else { - _set_error("Expected expression, found: " + get_token_text(tk)); - return nullptr; - //nothing + if (tk.type != TK_SEMICOLON) { + _set_error("Expected expression, found: " + get_token_text(tk)); + return nullptr; + } else { +#if DEBUG_ENABLED + if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { + _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning."); + } +#endif // DEBUG_ENABLED + _set_tkpos(prepos); + + OperatorNode *func = alloc_node<OperatorNode>(); + func->op = OP_EMPTY; + expr = func; + } } ERR_FAIL_COND_V(!expr, nullptr); @@ -6386,7 +6398,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun ArrayDeclarationNode::Declaration adecl; if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { - _set_error("Expected identifier or '[' after type."); + _set_error("Expected identifier or '[' after datatype."); return ERR_PARSE_ERROR; } @@ -7441,10 +7453,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int texture_uniforms = 0; int texture_binding = 0; + int uniforms = 0; int instance_index = 0; ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL; stages = &p_functions; + const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo(); while (tk.type != TK_EOF) { switch (tk.type) { @@ -7488,7 +7502,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_IDENTIFIER) { st.name = tk.text; - if (shader->structs.has(st.name)) { + if (shader->constants.has(st.name) || shader->structs.has(st.name)) { _set_error("Redefinition of '" + String(st.name) + "'"); return ERR_PARSE_ERROR; } @@ -7560,7 +7574,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int array_size = 0; if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(array_size); + Error error = _parse_global_array_size(array_size, constants); if (error != OK) { return error; } @@ -7587,7 +7601,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(member->array_size); + Error error = _parse_global_array_size(member->array_size, constants); if (error != OK) { return error; } @@ -7714,7 +7728,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(array_size); + Error error = _parse_global_array_size(array_size, constants); if (error != OK) { return error; } @@ -7729,7 +7743,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct prev_pos = _get_tkpos(); name = tk.text; - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { + if (_find_identifier(nullptr, false, constants, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -7762,7 +7776,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(uniform2.array_size); + Error error = _parse_global_array_size(uniform2.array_size, constants); if (error != OK) { return error; } @@ -7791,6 +7805,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } uniform2.texture_order = -1; + if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) { + uniform2.order = uniforms++; + } } if (uniform2.array_size > 0) { @@ -8013,7 +8030,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *expr = _parse_and_reduce_expression(nullptr, constants); if (!expr) { return ERR_PARSE_ERROR; } @@ -8109,7 +8126,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct DataPrecision precision = PRECISION_DEFAULT; DataType type; StringName name; - int return_array_size = 0; + int array_size = 0; if (tk.type == TK_CONST) { is_constant = true; @@ -8148,13 +8165,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct prev_pos = _get_tkpos(); tk = _get_token(); + bool unknown_size = false; + if (tk.type == TK_BRACKET_OPEN) { + if (is_constant && RenderingServer::get_singleton()->is_low_end()) { + _set_error("Global const arrays are only supported on high-end platform!"); + return ERR_PARSE_ERROR; + } bool error = false; tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - return_array_size = (int)tk.constant; - if (return_array_size > 0) { + array_size = (int)tk.constant; + if (array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8163,11 +8186,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { error = true; } + } else if (tk.type == TK_BRACKET_CLOSE) { + unknown_size = true; } else { error = true; } if (error) { - _set_error("Expected integer constant > 0"); + _set_error("Expected integer constant > 0 or ']'"); return ERR_PARSE_ERROR; } @@ -8179,16 +8204,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name); if (name == StringName()) { - _set_error("Expected function name after datatype"); - return ERR_PARSE_ERROR; - } - - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { - _set_error("Redefinition of '" + String(name) + "'"); + if (is_constant) { + _set_error("Expected identifier or '[' after datatype."); + } else { + _set_error("Expected function name after datatype."); + } return ERR_PARSE_ERROR; } - if (has_builtin(p_functions, name)) { + if (shader->structs.has(name) || _find_identifier(nullptr, false, constants, name) || has_builtin(p_functions, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -8201,7 +8225,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } //variable - + bool first = true; while (true) { ShaderNode::Constant constant; constant.name = name; @@ -8209,16 +8233,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.type_str = struct_name; constant.precision = precision; constant.initializer = nullptr; - constant.array_size = 0; - - bool unknown_size = false; + constant.array_size = (first ? array_size : 0); + first = false; if (tk.type == TK_BRACKET_OPEN) { if (RenderingServer::get_singleton()->is_low_end()) { - _set_error("Global const arrays are supported only on high-end platform!"); + _set_error("Global const arrays are only supported on high-end platform!"); + return ERR_PARSE_ERROR; + } + if (constant.array_size > 0 || unknown_size) { + _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; } - tk = _get_token(); if (tk.type == TK_BRACKET_CLOSE) { unknown_size = true; @@ -8296,7 +8322,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { _set_tkpos(prev_pos); - Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *n = _parse_and_reduce_expression(nullptr, constants); if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { _set_error("Expected single integer constant > 0"); return ERR_PARSE_ERROR; @@ -8377,7 +8403,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization while (true) { - Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *n = _parse_and_reduce_expression(nullptr, constants); if (!n) { return ERR_PARSE_ERROR; } @@ -8432,7 +8458,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.initializer = static_cast<ConstantNode *>(expr); } else { //variable created with assignment! must parse an expression - Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *expr = _parse_and_reduce_expression(nullptr, constants); if (!expr) { return ERR_PARSE_ERROR; } @@ -8448,7 +8474,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.initializer = static_cast<ConstantNode *>(expr); - if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) { + if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), expr->get_array_size())) { return ERR_PARSE_ERROR; } } @@ -8479,7 +8505,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } name = tk.text; - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { + if (_find_identifier(nullptr, false, constants, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -8513,6 +8539,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } } + if (p_functions.has("constants")) { // Adds global constants: 'PI', 'TAU', 'E' + for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) { + builtins.built_ins.insert(E.key, E.value); + } + } + ShaderNode::Function function; function.callable = !p_functions.has(name); @@ -8528,7 +8560,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct func_node->return_type = type; func_node->return_struct_name = struct_name; func_node->return_precision = precision; - func_node->return_array_size = return_array_size; + func_node->return_array_size = array_size; if (p_functions.has(name)) { func_node->can_discard = p_functions[name].can_discard; @@ -8582,7 +8614,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct StringName param_struct_name; DataPrecision pprecision = PRECISION_DEFAULT; bool use_precision = false; - int array_size = 0; + int arg_array_size = 0; if (is_token_precision(tk.type)) { pprecision = get_token_precision(tk.type); @@ -8633,9 +8665,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - array_size = (int)tk.constant; + arg_array_size = (int)tk.constant; - if (array_size > 0) { + if (arg_array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8687,7 +8719,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - if (array_size > 0) { + if (arg_array_size > 0) { _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; } @@ -8695,9 +8727,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - array_size = (int)tk.constant; + arg_array_size = (int)tk.constant; - if (array_size > 0) { + if (arg_array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8717,7 +8749,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } - arg.array_size = array_size; + arg.array_size = arg_array_size; func_node->arguments.push_back(arg); if (tk.type == TK_COMMA) { @@ -8769,20 +8801,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } - int uniforms = 0; - - // Need to push arrays to first place in a uniform buffer in order to correct work. - for (Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { - if (E->get().texture_order == -1 && E->get().scope != ShaderNode::Uniform::SCOPE_INSTANCE && E->get().array_size > 0) { - E->get().order = uniforms++; - } - } - for (Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { - if (E->get().texture_order == -1 && E->get().scope != ShaderNode::Uniform::SCOPE_INSTANCE && E->get().array_size == 0) { - E->get().order = uniforms++; - } - } - int error_line; String error_message; if (!_check_varying_usages(&error_line, &error_message)) { @@ -9077,6 +9095,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct } } + if (p_functions.has("constants")) { + for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) { + ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; + if (E.value.constant) { + kind = ScriptCodeCompletionOption::KIND_CONSTANT; + } + matches.insert(E.key, kind); + } + } + if (skip_function != StringName() && p_functions.has(skip_function)) { for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) { ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index c82f71d10d..3de89a89a5 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -287,6 +287,7 @@ public: OP_CONSTRUCT, OP_STRUCT, OP_INDEX, + OP_EMPTY, OP_MAX }; @@ -989,7 +990,7 @@ private: bool _check_node_constness(const Node *p_node) const; Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size); - Error _parse_global_array_size(int &r_array_size); + Error _parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info); Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size); Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index eb5c9e66e8..359196e096 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -59,9 +59,9 @@ ShaderTypes::ShaderTypes() { /*************** SPATIAL ***********************/ shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; @@ -241,9 +241,9 @@ ShaderTypes::ShaderTypes() { /************ CANVAS ITEM **************************/ shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2; shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; @@ -334,9 +334,9 @@ ShaderTypes::ShaderTypes() { /************ PARTICLES **************************/ shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3; @@ -367,7 +367,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT); @@ -400,9 +400,9 @@ ShaderTypes::ShaderTypes() { /************ SKY **************************/ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SKY].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SKY].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE); shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL); @@ -446,9 +446,9 @@ ShaderTypes::ShaderTypes() { /************ FOG **************************/ shader_modes[RS::SHADER_FOG].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_FOG].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_FOG].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_FOG].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["WORLD_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp index 0b8476478c..bffae484a8 100644 --- a/servers/rendering/shader_warnings.cpp +++ b/servers/rendering/shader_warnings.cpp @@ -61,6 +61,8 @@ String ShaderWarning::get_message() const { return vformat("The varying '%s' is declared but never used.", subject); case UNUSED_LOCAL_VARIABLE: return vformat("The local variable '%s' is declared but never used.", subject); + case FORMATTING_ERROR: + return subject; default: break; } @@ -82,6 +84,7 @@ String ShaderWarning::get_name_from_code(Code p_code) { "UNUSED_UNIFORM", "UNUSED_VARYING", "UNUSED_LOCAL_VARIABLE", + "FORMATTING_ERROR", }; static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names."); @@ -110,6 +113,7 @@ static void init_code_to_flags_map() { code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG); + code_to_flags_map->insert(ShaderWarning::FORMATTING_ERROR, ShaderWarning::FORMATTING_ERROR_FLAG); } ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) { diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h index db872d8fb1..18915fffd8 100644 --- a/servers/rendering/shader_warnings.h +++ b/servers/rendering/shader_warnings.h @@ -47,6 +47,7 @@ public: UNUSED_UNIFORM, UNUSED_VARYING, UNUSED_LOCAL_VARIABLE, + FORMATTING_ERROR, WARNING_MAX, }; @@ -59,6 +60,7 @@ public: UNUSED_UNIFORM_FLAG = 16U, UNUSED_VARYING_FLAG = 32U, UNUSED_LOCAL_VARIABLE_FLAG = 64U, + FORMATTING_ERROR_FLAG = 128U, }; private: diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 7a958546b6..a23911e81a 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -199,11 +199,11 @@ RID RenderingServer::_make_test_cube() { normal_points[j][i % 3] = (i >= 3 ? -1 : 1); } - //tri 1 + // Tri 1 ADD_VTX(0); ADD_VTX(1); ADD_VTX(2); - //tri 2 + // Tri 2 ADD_VTX(2); ADD_VTX(3); ADD_VTX(0); @@ -317,9 +317,6 @@ RID RenderingServer::get_white_texture() { return white_texture; } -#define SMALL_VEC2 Vector2(0.00001, 0.00001) -#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001) - Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_vertex_stride, uint32_t p_attrib_stride, uint32_t p_skin_stride, Vector<uint8_t> &r_vertex_array, Vector<uint8_t> &r_attrib_array, Vector<uint8_t> &r_skin_array, int p_vertex_array_len, Vector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb) { uint8_t *vw = r_vertex_array.ptrw(); uint8_t *aw = r_attrib_array.ptrw(); @@ -333,7 +330,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint int max_bone = 0; for (int ai = 0; ai < RS::ARRAY_MAX; ai++) { - if (!(p_format & (1 << ai))) { // no array + if (!(p_format & (1 << ai))) { // No array continue; } @@ -345,7 +342,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint const Vector2 *src = array.ptr(); - // setting vertices means regenerating the AABB + // Setting vertices means regenerating the AABB. Rect2 aabb; { @@ -355,7 +352,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(float) * 2); if (i == 0) { - aabb = Rect2(src[i], SMALL_VEC2); //must have a bit of size + aabb = Rect2(src[i], SMALL_VEC2); // Must have a bit of size. } else { aabb.expand_to(src[i]); } @@ -370,7 +367,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint const Vector3 *src = array.ptr(); - // setting vertices means regenerating the AABB + // Setting vertices means regenerating the AABB. AABB aabb; { @@ -505,7 +502,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint case ARRAY_CUSTOM_RGBA8_UNORM: case ARRAY_CUSTOM_RGBA8_SNORM: case ARRAY_CUSTOM_RG_HALF: { - //size 4 + // Size 4 ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_BYTE_ARRAY, ERR_INVALID_PARAMETER); Vector<uint8_t> array = p_arrays[ai]; @@ -520,7 +517,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint } break; case ARRAY_CUSTOM_RGBA_HALF: { - //size 8 + // Size 8 ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_BYTE_ARRAY, ERR_INVALID_PARAMETER); Vector<uint8_t> array = p_arrays[ai]; @@ -537,7 +534,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint case ARRAY_CUSTOM_RG_FLOAT: case ARRAY_CUSTOM_RGB_FLOAT: case ARRAY_CUSTOM_RGBA_FLOAT: { - //RF + // RF ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); Vector<float> array = p_arrays[ai]; @@ -646,7 +643,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint } if (p_format & RS::ARRAY_FORMAT_BONES) { - //create AABBs for each detected bone + // Create AABBs for each detected bone. int total_bones = max_bone + 1; bool first = r_bone_aabb.size() == 0; @@ -657,7 +654,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint if (first) { for (int i = 0; i < total_bones; i++) { - r_bone_aabb.write[i].size = Vector3(-1, -1, -1); //negative means unused + r_bone_aabb.write[i].size = Vector3(-1, -1, -1); // Negative means unused. } } @@ -686,7 +683,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint ERR_FAIL_INDEX_V(idx, total_bones, ERR_INVALID_DATA); if (bptr[idx].size.x < 0) { - //first + // First bptr[idx] = AABB(v, SMALL_VEC3); any_valid = true; } else { @@ -749,7 +746,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i uint32_t *size_accum; for (int i = 0; i < RS::ARRAY_MAX; i++) { - r_offsets[i] = 0; //reset + r_offsets[i] = 0; // Reset if (i == RS::ARRAY_VERTEX) { size_accum = &r_vertex_element_size; @@ -759,7 +756,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i size_accum = &r_skin_element_size; } - if (!(p_format & (1 << i))) { // no array + if (!(p_format & (1 << i))) { // No array continue; } @@ -873,7 +870,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa uint32_t format = 0; - // validation + // Validation int index_array_len = 0; int array_len = 0; @@ -921,10 +918,10 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } } - ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // mandatory + ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // Mandatory if (p_blend_shapes.size()) { - //validate format for morphs + // Validate format for morphs. for (int i = 0; i < p_blend_shapes.size(); i++) { uint32_t bsformat = 0; Array arr = p_blend_shapes[i]; @@ -939,7 +936,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } for (uint32_t i = 0; i < RS::ARRAY_CUSTOM_COUNT; ++i) { - // include custom array format type. + // Include custom array format type. if (format & (1 << (ARRAY_CUSTOM0 + i))) { format |= (RS::ARRAY_FORMAT_CUSTOM_MASK << (RS::ARRAY_FORMAT_CUSTOM_BASE + i * RS::ARRAY_FORMAT_CUSTOM_BITS)) & p_compress_format; } @@ -954,7 +951,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa mesh_surface_make_offsets_from_format(format, array_len, index_array_len, offsets, vertex_element_size, attrib_element_size, skin_element_size); uint32_t mask = (1 << ARRAY_MAX) - 1; - format |= (~mask) & p_compress_format; //make the full format + format |= (~mask) & p_compress_format; // Make the full format. int vertex_array_size = vertex_element_size * array_len; int attrib_array_size = attrib_element_size * array_len; @@ -1010,13 +1007,13 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa Vector<int> indices = p_lods[E]; ERR_CONTINUE(indices.size() == 0); uint32_t index_count = indices.size(); - ERR_CONTINUE(index_count >= (uint32_t)index_array_len); //should be smaller.. + ERR_CONTINUE(index_count >= (uint32_t)index_array_len); // Should be smaller.. const int *r = indices.ptr(); Vector<uint8_t> data; if (array_len <= 65536) { - //16 bits indices + // 16 bits indices data.resize(indices.size() * 2); uint8_t *w = data.ptrw(); uint16_t *index_ptr = (uint16_t *)w; @@ -1024,7 +1021,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa index_ptr[i] = r[i]; } } else { - //32 bits indices + // 32 bits indices data.resize(indices.size() * 4); uint8_t *w = data.ptrw(); uint32_t *index_ptr = (uint32_t *)w; @@ -1204,7 +1201,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t case ARRAY_CUSTOM_RGBA8_SNORM: case ARRAY_CUSTOM_RG_HALF: case ARRAY_CUSTOM_RGBA_HALF: { - //size 4 + // Size 4 int s = type == ARRAY_CUSTOM_RGBA_HALF ? 8 : 4; Vector<uint8_t> arr; arr.resize(p_vertex_len * s); @@ -1472,12 +1469,12 @@ ShaderLanguage::DataType RenderingServer::global_variable_type_get_shader_dataty case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: return ShaderLanguage::TYPE_SAMPLERCUBE; default: - return ShaderLanguage::TYPE_MAX; //invalid or not found + return ShaderLanguage::TYPE_MAX; // Invalid or not found. } } RenderingDevice *RenderingServer::get_rendering_device() const { - // return the rendering device we're using globally + // Return the rendering device we're using globally. return RenderingDevice::get_singleton(); } @@ -2221,8 +2218,8 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX); BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED); - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); //then goes to disabled); must be manually updated - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // default + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled); must be manually updated. + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // Default BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS); @@ -2553,7 +2550,8 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &RenderingServer::canvas_item_set_modulate); ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &RenderingServer::canvas_item_set_self_modulate); ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &RenderingServer::canvas_item_set_draw_behind_parent); - //primitives + + /* Primitives */ ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false)); @@ -2704,7 +2702,7 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAX); /* Free */ - ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // shouldn't conflict with Object::free() + ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // Shouldn't conflict with Object::free(). /* Misc */ diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 85f92bc003..230132651f 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -55,6 +55,9 @@ class RenderingServer : public Object { RendererThreadPool *thread_pool = nullptr; + const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON); + const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON); + protected: RID _make_test_cube(); void _free_internal_rids(); @@ -108,7 +111,7 @@ public: virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0; - //these two APIs can be used together or in combination with the others. + // These two APIs can be used together or in combination with the others. virtual RID texture_2d_placeholder_create() = 0; virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_layered_type) = 0; virtual RID texture_3d_placeholder_create() = 0; @@ -210,18 +213,18 @@ public: enum ArrayType { ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit) - ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored - ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal + ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored. + ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal. ARRAY_COLOR = 3, // RGBA8 ARRAY_TEX_UV = 4, // RG32F ARRAY_TEX_UV2 = 5, // RG32F - ARRAY_CUSTOM0 = 6, // depends on ArrayCustomFormat + ARRAY_CUSTOM0 = 6, // Depends on ArrayCustomFormat. ARRAY_CUSTOM1 = 7, ARRAY_CUSTOM2 = 8, ARRAY_CUSTOM3 = 9, ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights) ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights) - ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF + ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF. ARRAY_MAX = 13 }; @@ -243,7 +246,7 @@ public: enum ArrayFormat { /* ARRAY FORMAT FLAGS */ - ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // mandatory + ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // Mandatory ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL, ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT, ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR, @@ -287,9 +290,9 @@ public: PrimitiveType primitive = PRIMITIVE_MAX; uint32_t format = 0; - Vector<uint8_t> vertex_data; // vertex, normal, tangent (change with skinning, blendshape) - Vector<uint8_t> attribute_data; // color,uv, uv2, custom0-3 - Vector<uint8_t> skin_data; // bone index, bone weight + Vector<uint8_t> vertex_data; // Vertex, Normal, Tangent (change with skinning, blendshape). + Vector<uint8_t> attribute_data; // Color, UV, UV2, Custom0-3. + Vector<uint8_t> skin_data; // Bone index, Bone weight. uint32_t vertex_count = 0; Vector<uint8_t> index_data; uint32_t index_count = 0; @@ -452,7 +455,7 @@ public: virtual void light_set_bake_mode(RID p_light, LightBakeMode p_bake_mode) = 0; virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0; - // omni light + // Omni light enum LightOmniShadowMode { LIGHT_OMNI_SHADOW_DUAL_PARABOLOID, LIGHT_OMNI_SHADOW_CUBE, @@ -460,7 +463,7 @@ public: virtual void light_omni_set_shadow_mode(RID p_light, LightOmniShadowMode p_mode) = 0; - // directional light + // Directional light enum LightDirectionalShadowMode { LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, @@ -671,7 +674,7 @@ public: virtual AABB particles_get_current_aabb(RID p_particles) = 0; - virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; //this is only used for 2D, in 3D it's automatic + virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; // This is only used for 2D, in 3D it's automatic. /* PARTICLES COLLISION API */ @@ -689,16 +692,16 @@ public: virtual void particles_collision_set_collision_type(RID p_particles_collision, ParticlesCollisionType p_type) = 0; virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0; - virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres - virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres + virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; // For spheres. + virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; // For non-spheres. virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0; virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0; virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0; - virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic + virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; // For SDF and vector field, heightfield is dynamic. - virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field + virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; // For SDF and vector field. - enum ParticlesCollisionHeightfieldResolution { //longest axis resolution + enum ParticlesCollisionHeightfieldResolution { // Longest axis resolution. PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_256, PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_512, PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024, @@ -708,7 +711,7 @@ public: PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX, }; - virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field + virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, ParticlesCollisionHeightfieldResolution p_resolution) = 0; // For SDF and vector field. /* FOG VOLUME API */ @@ -750,7 +753,7 @@ public: /* VIEWPORT API */ enum CanvasItemTextureFilter { - CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item + CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, // Uses canvas item setting for draw command, uses global setting for canvas item. CANVAS_ITEM_TEXTURE_FILTER_NEAREST, CANVAS_ITEM_TEXTURE_FILTER_LINEAR, CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, @@ -761,7 +764,7 @@ public: }; enum CanvasItemTextureRepeat { - CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item + CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, // Uses canvas item setting for draw command, uses global setting for canvas item. CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, CANVAS_ITEM_TEXTURE_REPEAT_ENABLED, CANVAS_ITEM_TEXTURE_REPEAT_MIRROR, @@ -791,8 +794,8 @@ public: enum ViewportUpdateMode { VIEWPORT_UPDATE_DISABLED, - VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated - VIEWPORT_UPDATE_WHEN_VISIBLE, // default + VIEWPORT_UPDATE_ONCE, // Then goes to disabled, must be manually updated. + VIEWPORT_UPDATE_WHEN_VISIBLE, // Default VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE, VIEWPORT_UPDATE_ALWAYS }; @@ -1171,7 +1174,7 @@ public: virtual void instance_set_ignore_culling(RID p_instance, bool p_enabled) = 0; - // don't use these in a game! + // Don't use these in a game! virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0; virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0; virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0; @@ -1245,7 +1248,7 @@ public: virtual void canvas_texture_set_channel(RID p_canvas_texture, CanvasTextureChannel p_channel, RID p_texture) = 0; virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; - //takes effect only for new draw commands + // Takes effect only for new draw commands. virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, CanvasItemTextureFilter p_filter) = 0; virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, CanvasItemTextureRepeat p_repeat) = 0; @@ -1443,7 +1446,7 @@ public: /* FREE */ - virtual void free(RID p_rid) = 0; ///< free RIDs associated with the rendering server + virtual void free(RID p_rid) = 0; // Free RIDs associated with the rendering server. /* EVENT QUEUING */ @@ -1529,7 +1532,7 @@ public: virtual ~RenderingServer(); private: - //binder helpers + // Binder helpers RID _texture_2d_layered_create(const TypedArray<Image> &p_layers, TextureLayeredType p_layered_type); RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data); void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data); @@ -1543,7 +1546,7 @@ private: void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses); }; -// make variant understand the enums +// Make variant understand the enums. VARIANT_ENUM_CAST(RenderingServer::TextureLayeredType); VARIANT_ENUM_CAST(RenderingServer::CubeMapLayer); VARIANT_ENUM_CAST(RenderingServer::ShaderMode); diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h index a95dd02ba5..0467d4417b 100644 --- a/tests/scene/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -2332,6 +2332,20 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { CHECK_FALSE(code_edit->is_line_folded(2)); CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + // Indent with blank lines. + code_edit->set_text("line1\n\tline2\n\n\nline3"); + CHECK(code_edit->can_fold_line(0)); + for (int i = 1; i < 2; i++) { + CHECK_FALSE(code_edit->can_fold_line(i)); + code_edit->fold_line(i); + CHECK_FALSE(code_edit->is_line_folded(i)); + } + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(1)); + CHECK_FALSE(code_edit->is_line_folded(2)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + // Nested indents. code_edit->set_text("line1\n\tline2\n\t\tline3\nline4"); CHECK(code_edit->can_fold_line(0)); @@ -2408,7 +2422,7 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { for (int i = 1; i < code_edit->get_line_count(); i++) { CHECK_FALSE(code_edit->is_line_folded(i)); } - CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 6); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 5); // End of file. code_edit->set_text("line1\n\tline2"); @@ -2490,7 +2504,7 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { // Multiline blocks. code_edit->add_comment_delimiter("&", "&", false); - code_edit->set_text("&line1\n\tline2&"); + code_edit->set_text("&line1\n\tline2&\nline3"); CHECK(code_edit->can_fold_line(0)); CHECK_FALSE(code_edit->can_fold_line(1)); code_edit->fold_line(1); @@ -2498,7 +2512,17 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { code_edit->fold_line(0); CHECK(code_edit->is_line_folded(0)); CHECK_FALSE(code_edit->is_line_folded(1)); - CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + + // Multiline comment before last line. + code_edit->set_text("&line1\nline2&\ntest"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(2)); + code_edit->fold_line(1); + CHECK_FALSE(code_edit->is_line_folded(1)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); // Has to be full line. code_edit->set_text("test &line1\n\tline2&"); @@ -2554,7 +2578,7 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { CHECK_FALSE(code_edit->is_line_folded(1)); CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 1); - // Non-indented comments/ strings. + // Non-indented comments/strings. // Single line code_edit->set_text("test\n\tline1\n#line1\n#line2\n\ttest"); CHECK(code_edit->can_fold_line(0)); @@ -2576,6 +2600,50 @@ TEST_CASE("[SceneTree][CodeEdit] folding") { CHECK_FALSE(code_edit->is_line_folded(1)); CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 4); + // Indent level 0->1, comment after lines + code_edit->set_text("line1\n\tline2\n#test"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(1)); + code_edit->fold_line(1); + CHECK_FALSE(code_edit->is_line_folded(1)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(1)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + + // Indent level 0->1, comment between lines + code_edit->set_text("line1\n#test\n\tline2\nline3"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(2)); + code_edit->fold_line(2); + CHECK_FALSE(code_edit->is_line_folded(2)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(2)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3); + + // Indent level 1->2, comment after lines + code_edit->set_text("\tline1\n\t\tline2\n#test"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(1)); + code_edit->fold_line(1); + CHECK_FALSE(code_edit->is_line_folded(1)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(1)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 2); + + // Indent level 1->2, comment between lines + code_edit->set_text("\tline1\n#test\n\t\tline2\nline3"); + CHECK(code_edit->can_fold_line(0)); + CHECK_FALSE(code_edit->can_fold_line(2)); + code_edit->fold_line(2); + CHECK_FALSE(code_edit->is_line_folded(2)); + code_edit->fold_line(0); + CHECK(code_edit->is_line_folded(0)); + CHECK_FALSE(code_edit->is_line_folded(2)); + CHECK(code_edit->get_next_visible_line_offset_from(1, 1) == 3); + // Multiline code_edit->set_text("test\n\tline1\n&line1\nline2&\n\ttest"); CHECK(code_edit->can_fold_line(0)); diff --git a/tests/scene/test_curve.h b/tests/scene/test_curve.h index 60eafad460..4ee1a1c15c 100644 --- a/tests/scene/test_curve.h +++ b/tests/scene/test_curve.h @@ -219,35 +219,33 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { TEST_CASE("[Curve2D] Linear sampling should return exact value") { Ref<Curve2D> curve = memnew(Curve2D); - int len = 2048; + real_t len = 2048.0; curve->add_point(Vector2(0, 0)); - curve->add_point(Vector2((float)len, 0)); + curve->add_point(Vector2(len, 0)); - float baked_length = curve->get_baked_length(); - CHECK((float)len == baked_length); + real_t baked_length = curve->get_baked_length(); + CHECK(len == baked_length); for (int i = 0; i < len; i++) { - float expected = (float)i; - Vector2 pos = curve->interpolate_baked(expected); - CHECK_MESSAGE(pos.x == expected, "interpolate_baked should return exact value"); + Vector2 pos = curve->interpolate_baked(i); + CHECK_MESSAGE(pos.x == i, "interpolate_baked should return exact value"); } } TEST_CASE("[Curve3D] Linear sampling should return exact value") { Ref<Curve3D> curve = memnew(Curve3D); - int len = 2048; + real_t len = 2048.0; curve->add_point(Vector3(0, 0, 0)); - curve->add_point(Vector3((float)len, 0, 0)); + curve->add_point(Vector3(len, 0, 0)); - float baked_length = curve->get_baked_length(); - CHECK((float)len == baked_length); + real_t baked_length = curve->get_baked_length(); + CHECK(len == baked_length); for (int i = 0; i < len; i++) { - float expected = (float)i; - Vector3 pos = curve->interpolate_baked(expected); - CHECK_MESSAGE(pos.x == expected, "interpolate_baked should return exact value"); + Vector3 pos = curve->interpolate_baked(i); + CHECK_MESSAGE(pos.x == i, "interpolate_baked should return exact value"); } } diff --git a/tests/servers/test_shader_lang.cpp b/tests/servers/test_shader_lang.cpp index 0591bf6adf..f4a32c6723 100644 --- a/tests/servers/test_shader_lang.cpp +++ b/tests/servers/test_shader_lang.cpp @@ -261,6 +261,8 @@ static String dump_node_code(SL::Node *p_node, int p_level) { } code += ")"; break; + case SL::OP_EMPTY: + break; default: { code = "(" + dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level) + ")"; break; diff --git a/thirdparty/README.md b/thirdparty/README.md index 03e9885bd0..f8055ac3e7 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -201,7 +201,7 @@ Files extracted from upstream source: ## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 3.1.1 (cd5c6cd0419ac5e4de975d6c476fb760bf06d2ce, 2021) +- Version: 3.1.2 (8aed5c21a31eece6a9f3cd775fda8facb6c28b9b, 2021) - License: MIT Files extracted from upstream source: @@ -359,6 +359,19 @@ instead of a combination of distance and attribute errors. Patches for both chan found in the `patches` directory. +## minimp3 + +- Upstream: https://github.com/lieff/minimp3 +- Version: git (afb604c06bc8beb145fecd42c0ceb5bda8795144, 2021) +- License: CC0 1.0 + +Files extracted from upstream repository: + +- `minimp3.h` +- `minimp3_ex.h` +- `LICENSE` + + ## miniupnpc - Upstream: https://github.com/miniupnp/miniupnp diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh index dd61509b2e..0beffb078f 100644 --- a/thirdparty/harfbuzz/src/hb-array.hh +++ b/thirdparty/harfbuzz/src/hb-array.hh @@ -51,13 +51,19 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> * Constructors. */ hb_array_t () = default; - hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {} + hb_array_t (const hb_array_t&) = default; + ~hb_array_t () = default; + hb_array_t& operator= (const hb_array_t&) = default; + hb_array_t& operator= (hb_array_t&&) = default; + + constexpr hb_array_t (std::nullptr_t) : hb_array_t () {} + constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {} template <unsigned int length_> - hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {} + constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {} template <typename U, hb_enable_if (hb_is_cr_convertible(U, Type))> - hb_array_t (const hb_array_t<U> &o) : + constexpr hb_array_t (const hb_array_t<U> &o) : hb_iter_with_fallback_t<hb_array_t, Type&> (), arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {} template <typename U, @@ -303,13 +309,19 @@ struct hb_sorted_array_t : static constexpr bool is_sorted_iterator = true; hb_sorted_array_t () = default; - hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {} + hb_sorted_array_t (const hb_sorted_array_t&) = default; + ~hb_sorted_array_t () = default; + hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default; + hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default; + + constexpr hb_sorted_array_t (std::nullptr_t) : hb_sorted_array_t () {} + constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {} template <unsigned int length_> - hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {} + constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {} template <typename U, hb_enable_if (hb_is_cr_convertible(U, Type))> - hb_sorted_array_t (const hb_array_t<U> &o) : + constexpr hb_sorted_array_t (const hb_array_t<U> &o) : hb_iter_t<hb_sorted_array_t, Type&> (), hb_array_t<Type> (o) {} template <typename U, diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh index bb4a0eb5d1..793dcf22ca 100644 --- a/thirdparty/harfbuzz/src/hb-map.hh +++ b/thirdparty/harfbuzz/src/hb-map.hh @@ -35,8 +35,10 @@ */ template <typename K, typename V, - K kINVALID = hb_is_pointer (K) ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1, - V vINVALID = hb_is_pointer (V) ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1> + typename k_invalid_t = K, + typename v_invalid_t = V, + k_invalid_t kINVALID = hb_is_pointer (K) ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1, + v_invalid_t vINVALID = hb_is_pointer (V) ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1> struct hb_hashmap_t { static constexpr K INVALID_KEY = kINVALID; @@ -62,8 +64,10 @@ struct hb_hashmap_t hb_copy (o, *this); } - static_assert (std::is_integral<K>::value || hb_is_pointer (K), ""); - static_assert (std::is_integral<V>::value || hb_is_pointer (V), ""); + static_assert (std::is_trivially_copyable<K>::value, ""); + static_assert (std::is_trivially_copyable<V>::value, ""); + static_assert (std::is_trivially_destructible<K>::value, ""); + static_assert (std::is_trivially_destructible<V>::value, ""); struct item_t { @@ -348,19 +352,23 @@ struct hb_hashmap_t struct hb_map_t : hb_hashmap_t<hb_codepoint_t, hb_codepoint_t, + hb_codepoint_t, + hb_codepoint_t, HB_MAP_VALUE_INVALID, HB_MAP_VALUE_INVALID> { using hashmap = hb_hashmap_t<hb_codepoint_t, hb_codepoint_t, + hb_codepoint_t, + hb_codepoint_t, HB_MAP_VALUE_INVALID, HB_MAP_VALUE_INVALID>; hb_map_t () = default; ~hb_map_t () = default; - hb_map_t (hb_map_t& o) = default; - hb_map_t& operator= (const hb_map_t& other) = default; - hb_map_t& operator= (hb_map_t&& other) = default; + hb_map_t (hb_map_t&) = default; + hb_map_t& operator= (const hb_map_t&) = default; + hb_map_t& operator= (hb_map_t&&) = default; hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {} template <typename Iterable, hb_requires (hb_is_iterable (Iterable))> diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh index 03476faba7..a3c55fa8f4 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh @@ -38,8 +38,8 @@ */ #define HB_OT_TAG_COLR HB_TAG('C','O','L','R') -#ifndef COLRV1_MAX_NESTING_LEVEL -#define COLRV1_MAX_NESTING_LEVEL 100 +#ifndef HB_COLRV1_MAX_NESTING_LEVEL +#define HB_COLRV1_MAX_NESTING_LEVEL 100 #endif #ifndef COLRV1_ENABLE_SUBSETTING @@ -102,7 +102,7 @@ struct hb_colrv1_closure_context_t : hb_set_t *glyphs_, hb_set_t *layer_indices_, hb_set_t *palette_indices_, - unsigned nesting_level_left_ = COLRV1_MAX_NESTING_LEVEL) : + unsigned nesting_level_left_ = HB_COLRV1_MAX_NESTING_LEVEL) : base (base_), glyphs (glyphs_), layer_indices (layer_indices_), @@ -985,7 +985,7 @@ struct ClipList for (const hb_codepoint_t _ : gids.iter ()) { if (_ == start_gid) continue; - + offset = gid_offset_map.get (_); if (_ == prev_gid + 1 && offset == prev_offset) { @@ -1027,7 +1027,7 @@ struct ClipList const hb_set_t& glyphset = *c->plan->_glyphset; const hb_map_t &glyph_map = *c->plan->glyph_map; - + hb_map_t new_gid_offset_map; hb_set_t new_gids; for (const ClipRecord& record : clips.iter ()) @@ -1062,6 +1062,18 @@ struct ClipList struct Paint { + + template <typename ...Ts> + bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const + { + TRACE_SANITIZE (this); + + if (unlikely (!c->check_start_recursion (HB_COLRV1_MAX_NESTING_LEVEL))) + return_trace (c->no_dispatch_return_value ()); + + return_trace (c->end_recursion (this->dispatch (c, std::forward<Ts> (ds)...))); + } + template <typename context_t, typename ...Ts> typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index 5d98278bed..882c3ae96f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -98,7 +98,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, struct hb_prune_langsys_context_t { hb_prune_langsys_context_t (const void *table_, - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_, + hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_, const hb_map_t *duplicate_feature_map_, hb_set_t *new_collected_feature_indexes_) :table (table_), @@ -137,7 +137,7 @@ struct hb_prune_langsys_context_t public: const void *table; - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map; + hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map; const hb_map_t *duplicate_feature_map; hb_set_t *new_feature_indexes; @@ -179,14 +179,14 @@ struct hb_subset_layout_context_t : hb_subset_context_t *subset_context; const hb_tag_t table_tag; const hb_map_t *lookup_index_map; - const hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map; + const hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map; const hb_map_t *feature_index_map; unsigned cur_script_index; hb_subset_layout_context_t (hb_subset_context_t *c_, hb_tag_t tag_, hb_map_t *lookup_map_, - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_, + hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_, hb_map_t *feature_index_map_) : subset_context (c_), table_tag (tag_), @@ -1357,7 +1357,7 @@ struct Lookup if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ()))) return_trace (false); - if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ())) + if (unlikely (get_type () == TSubTable::Extension && subtables && !c->get_edit_count ())) { /* The spec says all subtables of an Extension lookup should * have the same type, which shall not be the Extension type diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index c0ed2bcc03..6bc06b50ed 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -163,7 +163,7 @@ struct hb_closure_context_t : hb_set_t *glyphs_, hb_set_t *cur_intersected_glyphs_, hb_map_t *done_lookups_glyph_count_, - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set_, + hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set_, unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), glyphs (glyphs_), @@ -192,7 +192,7 @@ struct hb_closure_context_t : private: hb_map_t *done_lookups_glyph_count; - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set; + hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set; unsigned int lookup_count; }; @@ -1642,9 +1642,8 @@ struct Rule const hb_map_t *klass_map = nullptr) const { TRACE_SUBSET (this); - - const hb_array_t<const HBUINT16> input = inputZ.as_array ((inputCount ? inputCount - 1 : 0)); - if (!input.length) return_trace (false); + if (unlikely (!inputCount)) return_trace (false); + const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1); const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map; if (!hb_all (input, mapping)) return_trace (false); @@ -3631,7 +3630,7 @@ struct GSUBGPOS } void prune_langsys (const hb_map_t *duplicate_feature_map, - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map, + hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map, hb_set_t *new_feature_indexes /* OUT */) const { hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes); @@ -3689,7 +3688,7 @@ struct GSUBGPOS hb_map_t *duplicate_feature_map /* OUT */) const { if (feature_indices->is_empty ()) return; - hb_hashmap_t<hb_tag_t, hb_set_t *, (unsigned)-1, nullptr> unique_features; + hb_hashmap_t<hb_tag_t, hb_set_t *> unique_features; //find out duplicate features after subset for (unsigned i : feature_indices->iter ()) { @@ -3784,8 +3783,12 @@ struct GSUBGPOS // http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html continue; - if (f.featureParams.is_null () - && !f.intersects_lookup_indexes (lookup_indices) + + if (!f.featureParams.is_null () && + tag == HB_TAG ('s', 'i', 'z', 'e')) + continue; + + if (!f.intersects_lookup_indexes (lookup_indices) #ifndef HB_NO_VAR && !alternate_feature_indices.has (i) #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc index fbdedd0e20..4e1d23eba5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.cc +++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc @@ -1493,7 +1493,7 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face, { hb_set_t cur_intersected_glyphs; hb_map_t done_lookups_glyph_count; - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set; + hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set; OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index); @@ -1522,7 +1522,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, { hb_set_t cur_intersected_glyphs; hb_map_t done_lookups_glyph_count; - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set; + hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set; OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); const OT::GSUB& gsub = *face->table.GSUB->table; diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh index 94450eb53a..504de2de74 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh @@ -79,6 +79,7 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const post::accelerator_t _post; _post.init (c->plan->source); + hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index; for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) { hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); @@ -90,22 +91,28 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const else { hb_bytes_t s = _post.find_glyph_name (old_gid); - int standard_glyph_index = -1; - for (unsigned i = 0; i < format1_names_length; i++) + new_index = glyph_name_to_new_index.get (s); + if (new_index == (unsigned)-1) { - if (s == format1_names (i)) + int standard_glyph_index = -1; + for (unsigned i = 0; i < format1_names_length; i++) { - standard_glyph_index = i; - break; + if (s == format1_names (i)) + { + standard_glyph_index = i; + break; + } } + + if (standard_glyph_index == -1) + { + new_index = 258 + i; + i++; + } + else + { new_index = standard_glyph_index; } + glyph_name_to_new_index.set (s, new_index); } - if (standard_glyph_index == -1) - { - new_index = 258 + i; - i++; - } - else - { new_index = standard_glyph_index; } old_new_index_map.set (old_index, new_index); } old_gid_new_index_map.set (old_gid, new_index); diff --git a/thirdparty/harfbuzz/src/hb-sanitize.hh b/thirdparty/harfbuzz/src/hb-sanitize.hh index 2e536c7a81..65c2772201 100644 --- a/thirdparty/harfbuzz/src/hb-sanitize.hh +++ b/thirdparty/harfbuzz/src/hb-sanitize.hh @@ -123,6 +123,7 @@ struct hb_sanitize_context_t : hb_sanitize_context_t () : start (nullptr), end (nullptr), max_ops (0), max_subtables (0), + recursion_depth (0), writable (false), edit_count (0), blob (nullptr), num_glyphs (65536), @@ -205,6 +206,7 @@ struct hb_sanitize_context_t : (unsigned) HB_SANITIZE_MAX_OPS_MAX); this->edit_count = 0; this->debug_depth = 0; + this->recursion_depth = 0; DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1, "start [%p..%p] (%lu bytes)", @@ -278,6 +280,18 @@ struct hb_sanitize_context_t : return this->check_range (base, a, b, hb_static_size (T)); } + bool check_start_recursion (int max_depth) + { + if (unlikely (recursion_depth >= max_depth)) return false; + return ++recursion_depth; + } + + bool end_recursion (bool result) + { + recursion_depth--; + return result; + } + template <typename Type> bool check_struct (const Type *obj) const { return likely (this->check_range (obj, obj->min_size)); } @@ -389,6 +403,7 @@ struct hb_sanitize_context_t : const char *start, *end; mutable int max_ops, max_subtables; private: + int recursion_depth; bool writable; unsigned int edit_count; hb_blob_t *blob; diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh index 57689916f6..d22ae06087 100644 --- a/thirdparty/harfbuzz/src/hb-serialize.hh +++ b/thirdparty/harfbuzz/src/hb-serialize.hh @@ -652,7 +652,9 @@ struct hb_serialize_context_t hb_vector_t<object_t *> packed; /* Map view of packed objects. */ - hb_hashmap_t<const object_t *, objidx_t, nullptr, 0> packed_map; + hb_hashmap_t<const object_t *, objidx_t, + const object_t *, objidx_t, + nullptr, 0> packed_map; }; #endif /* HB_SERIALIZE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh index 8841427189..af02e9e12b 100644 --- a/thirdparty/harfbuzz/src/hb-set.hh +++ b/thirdparty/harfbuzz/src/hb-set.hh @@ -157,9 +157,9 @@ struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t> { hb_set_t () = default; ~hb_set_t () = default; - hb_set_t (hb_set_t& o) = default; - hb_set_t& operator= (const hb_set_t& other) = default; - hb_set_t& operator= (hb_set_t&& other) = default; + hb_set_t (hb_set_t&) = default; + hb_set_t& operator= (const hb_set_t&) = default; + hb_set_t& operator= (hb_set_t&&) = default; hb_set_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t<hb_bit_set_invertible_t> (lst) {} template <typename Iterable, hb_requires (hb_is_iterable (Iterable))> diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index 1e195ff660..53f8664d92 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.cc +++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc @@ -41,7 +41,7 @@ #include "hb-ot-math-table.hh" -typedef hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> script_langsys_map; +typedef hb_hashmap_t<unsigned, hb_set_t *> script_langsys_map; #ifndef HB_NO_SUBSET_CFF static inline void _add_cff_seac_components (const OT::cff1::accelerator_t &cff, @@ -100,11 +100,23 @@ static void _collect_layout_indices (hb_face_t *face, if (!features.alloc (table.get_feature_count () + 1)) return; + hb_set_t visited_features; + bool retain_all_features = true; for (unsigned i = 0; i < table.get_feature_count (); i++) { hb_tag_t tag = table.get_feature_tag (i); - if (tag && layout_features_to_retain->has (tag)) - features.push (tag); + if (!tag) continue; + if (!layout_features_to_retain->has (tag)) + { + retain_all_features = false; + continue; + } + + if (visited_features.has (tag)) + continue; + + features.push (tag); + visited_features.add (tag); } if (!features) @@ -113,7 +125,7 @@ static void _collect_layout_indices (hb_face_t *face, // The collect function needs a null element to signal end of the array. features.push (0); - if (features.get_size () == table.get_feature_count () + 1) + if (retain_all_features) { // Looking for all features, trigger the faster collection method. layout_collect_func (face, diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh index c30feeb42f..c0232480bf 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.hh +++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh @@ -84,8 +84,8 @@ struct hb_subset_plan_t hb_map_t *gpos_lookups; //active langsys we'd like to retain - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *gsub_langsys; - hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *gpos_langsys; + hb_hashmap_t<unsigned, hb_set_t *> *gsub_langsys; + hb_hashmap_t<unsigned, hb_set_t *> *gpos_langsys; //active features after removing redundant langsys and prune_features hb_map_t *gsub_features; diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index 1a4f0bf62a..c9fefa1df6 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -53,14 +53,14 @@ HB_BEGIN_DECLS * * The micro component of the library version available at compile-time. */ -#define HB_VERSION_MICRO 1 +#define HB_VERSION_MICRO 2 /** * HB_VERSION_STRING: * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "3.1.1" +#define HB_VERSION_STRING "3.1.2" /** * HB_VERSION_ATLEAST: diff --git a/thirdparty/minimp3/minimp3.h b/thirdparty/minimp3/minimp3.h index 796cbc1f8e..3220ae1a85 100644 --- a/thirdparty/minimp3/minimp3.h +++ b/thirdparty/minimp3/minimp3.h @@ -881,12 +881,22 @@ static void L3_midside_stereo(float *left, int n) int i = 0; float *right = left + 576; #if HAVE_SIMD - if (have_simd()) for (; i < n - 3; i += 4) + if (have_simd()) { - f4 vl = VLD(left + i); - f4 vr = VLD(right + i); - VSTORE(left + i, VADD(vl, vr)); - VSTORE(right + i, VSUB(vl, vr)); + for (; i < n - 3; i += 4) + { + f4 vl = VLD(left + i); + f4 vr = VLD(right + i); + VSTORE(left + i, VADD(vl, vr)); + VSTORE(right + i, VSUB(vl, vr)); + } +#ifdef __GNUC__ + /* Workaround for spurious -Waggressive-loop-optimizations warning from gcc. + * For more info see: https://github.com/lieff/minimp3/issues/88 + */ + if (__builtin_constant_p(n % 4 == 0) && n % 4 == 0) + return; +#endif } #endif /* HAVE_SIMD */ for (; i < n; i++) @@ -1353,7 +1363,7 @@ static void mp3d_DCT_II(float *grbuf, int n) } else #endif /* HAVE_SIMD */ #ifdef MINIMP3_ONLY_SIMD - {} + {} /* for HAVE_SIMD=1, MINIMP3_ONLY_SIMD=1 case we do not need non-intrinsic "else" branch */ #else /* MINIMP3_ONLY_SIMD */ for (; k < n; k++) { @@ -1583,7 +1593,7 @@ static void mp3d_synth(float *xl, mp3d_sample_t *dstl, int nch, float *lins) } else #endif /* HAVE_SIMD */ #ifdef MINIMP3_ONLY_SIMD - {} + {} /* for HAVE_SIMD=1, MINIMP3_ONLY_SIMD=1 case we do not need non-intrinsic "else" branch */ #else /* MINIMP3_ONLY_SIMD */ for (i = 14; i >= 0; i--) { diff --git a/thirdparty/minimp3/minimp3_ex.h b/thirdparty/minimp3/minimp3_ex.h index e29dd15b2e..2871705df3 100644 --- a/thirdparty/minimp3/minimp3_ex.h +++ b/thirdparty/minimp3/minimp3_ex.h @@ -6,6 +6,7 @@ This software is distributed without any warranty. See <http://creativecommons.org/publicdomain/zero/1.0/>. */ +#include <stddef.h> #include "minimp3.h" /* flags for mp3dec_ex_open_* functions */ @@ -128,8 +129,10 @@ int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int flags); #endif #endif /*MINIMP3_EXT_H*/ -#ifdef MINIMP3_IMPLEMENTATION +#if defined(MINIMP3_IMPLEMENTATION) && !defined(_MINIMP3_EX_IMPLEMENTATION_GUARD) +#define _MINIMP3_EX_IMPLEMENTATION_GUARD #include <limits.h> +#include "minimp3.h" static void mp3dec_skip_id3v1(const uint8_t *buf, size_t *pbuf_size) { @@ -1391,4 +1394,4 @@ void mp3dec_ex_close(mp3dec_ex_t *dec) } #endif -#endif /*MINIMP3_IMPLEMENTATION*/ +#endif /* MINIMP3_IMPLEMENTATION && !_MINIMP3_EX_IMPLEMENTATION_GUARD */ |